zoukankan      html  css  js  c++  java
  • opengl鼠标键盘控制相机漫游

    键盘wsad控制相机位移,鼠标左键按下控制相机旋转
    效果如下
    代码如下
    #include <stdio.h>
    #include <string.h> 
    #include <iostream>
    #include <fstream> 
    #include <sstream>
    #include <GL/glew.h>  
    #include <GL/freeglut.h>   
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp> 
    
    using namespace std;
    using namespace glm;
     
    const char* vsShaderName = "shader.vs";//顶点着色器
    const char* fsShaderName = "shader.fs";//片元着色器
    
    GLuint VBO;//顶点缓冲对象
    GLuint IBO;//索引缓冲对象 
    static  GLfloat *vertices;//顶点数组
    static unsigned int *indices; //索引数组
    GLuint ShaderProgram;
    GLuint MatrixID;
    int windowWidth = 800;
    int windowHeight = 800;
    //相机参数
    glm::mat4 ViewMatrix;//视图矩阵
    glm::mat4 ProjectionMatrix; //投影矩阵
    glm::mat4 MVP;//模型视图矩阵
    glm::mat4 ModelMatrix;//模型矩阵
    glm::vec3 position = glm::vec3(5, 5, 5); //相机位置
    float horizontalAngle = 3.14f;
    float verticalAngle = 0.0f;
    float initialFoV = 45.0f; //相机视场角
    float speed = 0.05f; //平移速度
    float mouseSpeed = 0.005f;
    int mouseX, mouseY;//鼠标位置 窗口坐标
    bool mouseLeftDown=false;//鼠标左键按下 
    
     // 传递键盘事件
    static void SpecialKeyboardCB(unsigned char Key, int x, int y)
    { 
    	glm::vec3 direction(
    		cos(verticalAngle) * sin(horizontalAngle),
    		sin(verticalAngle),
    		cos(verticalAngle) * cos(horizontalAngle)
    	);
    	glm::vec3 right = glm::vec3(
    		sin(horizontalAngle - 3.14f / 2.0f),
    		0,
    		cos(horizontalAngle - 3.14f / 2.0f)
    	);
    	glm::vec3 up = glm::cross(right, direction);
    
    	switch (Key) {  
    	case 'w':
    		position += direction  * speed;
    		//fprintf(stderr, "up 
    ");
    		break; 
    	case 'd':
    		position += right  * speed;
    		//fprintf(stderr, "right 
    ");
    		break; 
    	case 's':
    		position -= direction  * speed;
    		//fprintf(stderr, "down 
    ");
    		break; 
    	case 'a':
    		position -= right  * speed;
    		//fprintf(stderr, "left 
    ");
    		break;
    	case 27:
    		exit(1);
    		break;
    	default:
    		break;
    		//fprintf(stderr, "Unimplemented GLUT key
    ");
    		//exit(1); 
    	}
    
    	float FoV = initialFoV;
    	ProjectionMatrix = glm::perspective(glm::radians(FoV), (float)windowWidth /(float) windowHeight, 0.1f, 100.0f);
    	ViewMatrix = glm::lookAt(
    		position,
    		position + direction,
    		up
    	);
    	ModelMatrix = glm::mat4(1.0);
    	MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
    	glutPostRedisplay();//设置窗口重绘
    }
    
    //传递鼠标事件
    void mouseCB(int button, int state, int x, int y)
    { 
    	if (button == GLUT_LEFT_BUTTON)
    	{
    		if (state == GLUT_DOWN)
    		{
    			mouseLeftDown = true;
    			mouseX = x;
    			mouseY = y; 
    		} 
    		else if (state == GLUT_UP)
    		{
    			mouseLeftDown = false;
    		}
    	}  
    }
    
    //传递鼠标位置
    static void mouseMotionCB(int x, int y)
    {
    	if (mouseLeftDown == true)
    	{
    		horizontalAngle += mouseSpeed * float(x - mouseX);
    		verticalAngle += mouseSpeed * float(y - mouseY);
    		mouseX = x;
    		mouseY = y;
    		SpecialKeyboardCB(0, 0, 0);
    	}
    }
    
    
    //渲染回调函数 
    void RenderScenceCB() {
    	// 清空颜色缓存 
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    	glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]); 
    	glEnableVertexAttribArray(0);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
    	glDrawArrays(GL_LINES, 0, 40*4);
    	glDisableVertexAttribArray(0);
    	//交换前后缓存
    	glutSwapBuffers();
    }
    
    //创建顶点
    static void CreateVertexBuffer()
    { 
    	vertices = new GLfloat[40*3];
    	for (size_t i = 0; i < 10; i++)
    	{  
    		vertices[i * 12] = 0;
    		vertices[i * 12 + 1] = 0;
    		vertices[i * 12 + 2] = i;
    
    		vertices[i * 12 + 3] = 9;
    		vertices[i * 12 + 4] = 0;
    		vertices[i * 12 + 5] = i;
    
    		vertices[i * 12 + 6] = i;
    		vertices[i * 12 + 7] = 0;
    		vertices[i * 12 + 8] = 0;
    
    		vertices[i * 12 + 9] = i;
    		vertices[i * 12 + 10] = 0;
    		vertices[i * 12 + 11] = 9;
    	}
    	glGenBuffers(1, &VBO);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);  
    	glBufferData(GL_ARRAY_BUFFER, 40*3* sizeof(GLfloat), vertices, GL_STATIC_DRAW); 
    } 
     
    static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
    {
    	// 根据shader类型参数定义两个shader对象
    	GLuint ShaderObj = glCreateShader(ShaderType);
    	// 检查是否定义成功
    	if (ShaderObj == 0) {
    		fprintf(stderr, "Error creating shader type %d
    ", ShaderType);
    		exit(0);
    	}
    	// 定义shader的代码源
    	const GLchar* p[1];
    	p[0] = pShaderText;
    	GLint Lengths[1];
    	Lengths[0] = strlen(pShaderText);
    	glShaderSource(ShaderObj, 1, p, Lengths);
    	glCompileShader(ShaderObj);// 编译shader对象 
    							   // 检查和shader相关的错误
    	GLint success;
    	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
    	if (!success) {
    		GLchar InfoLog[1024];
    		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
    		fprintf(stderr, "Error compiling shader type %d: '%s'
    ", ShaderType, InfoLog);
    		exit(1);
    	}
    	// 将编译好的shader对象绑定到program object程序对象上
    	glAttachShader(ShaderProgram, ShaderObj);
    }
    
    // 编译着色器函数
    static void CompileShaders()
    {
    	// 创建着色器程序
    	ShaderProgram = glCreateProgram();
    	// 检查是否创建成功
    	if (ShaderProgram == 0) {
    		fprintf(stderr, "Error creating shader program
    ");
    		exit(1);
    	}
    	// 存储着色器文本的字符串
    	string vs, fs;
    	// 分别读取着色器文件中的文本到字符串
    	std::ifstream VertexShaderStream(vsShaderName, std::ios::in);
    	if (VertexShaderStream.is_open()) {
    		std::stringstream sstr;
    		sstr << VertexShaderStream.rdbuf();
    		vs = sstr.str();
    		VertexShaderStream.close();
    	}
    	else {
    		printf("Error to open %s
    ", vsShaderName);
    		getchar();
    		exit(0);
    	}
    	std::ifstream FragmentShaderStream(fsShaderName, std::ios::in);
    	if (FragmentShaderStream.is_open()) {
    		std::stringstream sstr;
    		sstr << FragmentShaderStream.rdbuf();
    		fs = sstr.str();
    		FragmentShaderStream.close();
    	}
    
    	// 添加顶点着色器和片段着色器
    	AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
    	AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
    	// 链接shader着色器程序,并检查程序相关错误
    	GLint Success = 0;
    	GLchar ErrorLog[1024] = { 0 };
    	glLinkProgram(ShaderProgram);
    	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
    	if (Success == 0) {
    		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
    		fprintf(stderr, "Error linking shader program: '%s'
    ", ErrorLog);
    		exit(1);
    	}
    	// 检查验证在当前的管线状态程序是否可以被执行
    	glValidateProgram(ShaderProgram);
    	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
    	if (!Success) {
    		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
    		fprintf(stderr, "Invalid shader program: '%s'
    ", ErrorLog);
    		exit(1);
    	}
    	// 设置到管线声明中来使用上面成功建立的shader程序
    	glUseProgram(ShaderProgram);
    	MatrixID = glGetUniformLocation(ShaderProgram, "gWVP");
    }
    
    int main(int argc, char ** argv) {
    	// 初始化GLUT
    	glutInit(&argc, argv);
    	// 显示模式:双缓冲、RGBA
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    	glutInitWindowSize(windowWidth, windowHeight);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("CameraTest");
    	GLenum res = glewInit();
    	if (res != GLEW_OK) {
    		fprintf(stderr, "Error: '%s'
    ", glewGetErrorString(res));
    		return 1;
    	}
    	// 开始渲染
    	glutDisplayFunc(RenderScenceCB);
    	// 注册键盘事件 
    	glutKeyboardFunc(SpecialKeyboardCB);
    	//注册鼠标事件
    	glutMouseFunc(mouseCB);
    	glutMotionFunc(mouseMotionCB);
    	mouseX = windowWidth / 2;
    	mouseY = windowHeight / 2;
    	// 缓存清空后的颜色值
    	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    	//创建顶点
    	CreateVertexBuffer(); 
    	// 编译着色器
    	CompileShaders();
    	//开启深度测试
    	glEnable(GL_DEPTH_TEST);
    	// 通知开始GLUT的内部循环
    	glutMainLoop();
    	delete vertices;
    	return 0;
    }
    
    #version 330 
    layout (location = 0) in vec3 Position;  
    uniform mat4 gWVP;  
    out vec3 Color; 
    void main()
    {
        gl_Position = gWVP * vec4(Position, 1.0); 
    	Color = Position/10;
    }
    
    #version 330 
    out vec3 FragColor;   
    in vec3 Color; 
    void main()
    {
        FragColor = Color;
    }
    

    本文链接https://www.cnblogs.com/gucheng/p/10139299.html

  • 相关阅读:
    PAT 甲级 1027 Colors in Mars
    PAT 甲级 1026 Table Tennis(模拟)
    PAT 甲级 1025 PAT Ranking
    PAT 甲级 1024 Palindromic Number
    PAT 甲级 1023 Have Fun with Numbers
    PAT 甲级 1021 Deepest Root (并查集,树的遍历)
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯 算法提高 抽卡游戏
    Java实现 蓝桥杯 算法提高 抽卡游戏
  • 原文地址:https://www.cnblogs.com/gucheng/p/10139299.html
Copyright © 2011-2022 走看看