zoukankan      html  css  js  c++  java
  • opengl读取灰度图生成三维地形

    准备第三方库 glew、freeglut、glm、opencv
    准备灰度图片和草地贴图
    最终效果
    代码包括主程序源文件mainApp.cpp、顶点着色器shader.vs、片元着色器shader.fs
    mainApp.cpp如下
    #include <stdio.h>
    #include <string.h> 
    #include <iostream>
    #include <fstream> 
    #include <sstream>
    #include <GL/glew.h>  
    #include <GL/freeglut.h>   
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp> 
    
    using namespace std; 
    using namespace cv;
    using namespace glm;
    
    //shader文件
    const char* vsShaderName = "shader.vs";//顶点着色器
    const char* fsShaderName = "shader.fs";//片元着色器
    
    GLuint VBO;//顶点缓冲对象
    GLuint IBO;//索引缓冲对象
    GLuint UVBO;//uv缓冲对象
    GLuint TexBO;//贴图对象
    static  GLfloat *vertices;
    static unsigned int *indices;
    static  GLfloat *uvs;
    
    GLuint ShaderProgram;
    GLuint MatrixID;
    GLuint TextureID;
    
    int windowWidth = 800;
    int windowHeight=800;
    int imgWidth;
    int imgHeihgt;
    float verticeScale = 0.1f;
    float ZScale = 5.0f;
    //相机参数
    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;//鼠标位置 窗口坐标
    
    
    // 传递键盘事件
    static void SpecialKeyboardCB(int 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 GLUT_KEY_UP:
    		position += direction  * speed;
    		fprintf(stderr, "up key
    ");
    		break;
    	case GLUT_KEY_RIGHT:
    		position += right  * speed;
    		fprintf(stderr, "right key
    ");
    		break;
    	case GLUT_KEY_DOWN:
    		position -= direction  * speed;
    		fprintf(stderr, "down key
    ");
    		break;
    	case GLUT_KEY_LEFT:
    		position -= right  * speed;
    		fprintf(stderr, "left key
    ");
    		break;
    	case GLUT_KEY_F4:
    		exit(1);
    	default:
    		fprintf(stderr, "Unimplemented GLUT key
    ");
    		//exit(1); 
    	}
    
    	float FoV = initialFoV;
    	ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
    	ViewMatrix = glm::lookAt(
    		position,          
    		position + direction, 
    		up                
    	);
    	ModelMatrix = glm::mat4(1.0);
    	MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;  
    	glutPostRedisplay();//设置窗口重绘
    } 
    //传递鼠标事件
    static void PassiveMouseCB(int x, int y)
    {  
    	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);
    	//传递mvp
    	glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);   
    	//传递顶点、索引、UV
    	glEnableVertexAttribArray(0); //开启顶点属性
    	glBindBuffer(GL_ARRAY_BUFFER, VBO); //绑定GL_ARRAY_BUFFER缓冲器 
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); //告诉管线怎样解析bufer中的数据  
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    	glEnableVertexAttribArray(1);
    	glBindBuffer(GL_ARRAY_BUFFER, UVBO); 
    	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);   
    	//传递贴图纹理
    	glActiveTexture(GL_TEXTURE0);
    	glBindTexture(GL_TEXTURE_2D, TexBO);
    	glUniform1i(TextureID, 0);  
    	//绘制
    	glDrawElements(GL_TRIANGLES, (imgWidth - 1)*(imgHeihgt - 1) * 6*4, GL_UNSIGNED_SHORT, 0); 
    	glDisableVertexAttribArray(0);
    	glDisableVertexAttribArray(1);
    	 //交换前后缓存
    	glutSwapBuffers();
    } 
    
    //创建顶点
    static void CreateVertexBuffer()
    {   
    	//读取图片
    	Mat img = imread("T2.png"); 
    	int imgType = img.type();
    #pragma region  灰度图信息
    	//  C1  C2 	C3 	C4
    	//CV_8U 	0 	8 	16 	24
    	//CV_8S 	1 	9 	17 	25
    	//CV_16U 	2 	10 	18 	26
    	//CV_16S 	3 	11 	19 	27
    	//CV_32S 	4 	12 	20 	28
    	//CV_32F 	5 	13 	21 	29
    	//CV_64F 	6 	14 	22 	30 
    	//fprintf(stderr, "Gray img type %d
    ", imgType);  //16 即是CV_8UC3
    	//imshow("grayImgTestShow",img); 
    #pragma endregion  
    	Mat resImg = Mat(img.rows, img.cols, imgType);
    	resize(img, resImg, resImg.size(), 0, 0, INTER_LINEAR);
    	Mat gImg = Mat(img.rows,img.cols,CV_8UC1); //灰度图
    	cv::cvtColor(resImg, gImg, CV_BGR2GRAY);//bgr转灰度
    	imgWidth = resImg.rows;
    	imgHeihgt = resImg.cols; 
    	//fprintf(stderr,"image gray type %d",resImg.type());
    	vertices = new GLfloat[imgWidth*imgHeihgt*3];
    	int k = 0; 
    	for (int i = 0; i < imgWidth; i++)
    	{
    		for (int j = 0; j < imgHeihgt; j++)
    		{
    			vertices[k++] = verticeScale* (float)i;
    			vertices[k++] = verticeScale*(float)j;  
    			int c = (int)gImg.at<uchar>(i, j);
    			//fprintf(stderr,"gray color %d  %d %d",i,j ,(int)gImg.at<uchar>(i, j));
    			vertices[k++] = ZScale*(float)c / 255.0f;
    		}
    	}      
    	glGenBuffers(1, &VBO);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glBufferData(GL_ARRAY_BUFFER, imgWidth*imgHeihgt * 3*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
    }
    //创建索引
    static void CreateIndexBuffer()
    { 
    	indices = new unsigned int[(imgWidth-1)*(imgHeihgt-1) * 6];
    	int k = 0; 
    
    	for (int i = 0; i < imgWidth - 1; i++)
    	{
    		for (int j = 0; j < imgHeihgt - 1; j++)
    		{
    			indices[k++] = i*imgHeihgt + j;
    			indices[k++] = i*imgHeihgt + j + 1;
    			indices[k++] = i*imgHeihgt + j + imgHeihgt;
    			indices[k++] = i*imgHeihgt + j + imgHeihgt;
    			indices[k++] = i*imgHeihgt + j + 1;
    			indices[k++] = i*imgHeihgt + j + imgHeihgt + 1;
    		}
    	}
    	glGenBuffers(1, &IBO);
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    	glBufferData(GL_ELEMENT_ARRAY_BUFFER, (imgWidth - 1)*(imgHeihgt - 1) * 6*sizeof(unsigned int), indices, GL_STATIC_DRAW);
    
     
    }
    //创建uv
    static void CreateUVBuffer()
    {
    	uvs=new  GLfloat[imgWidth*imgHeihgt * 2];
    	int k = 0;
    	for (int i = 0; i < imgWidth; i++)
    	{
    		for (int j = 0; j < imgHeihgt; j++)
    		{
    			uvs[k++] = (float)i / (float)(imgWidth);
    			uvs[k++] = (float)j / (float)(imgHeihgt);  
    		}
    	} 
    	glGenBuffers(1, &UVBO);
    	glBindBuffer(GL_ARRAY_BUFFER, UVBO);
    	glBufferData(GL_ARRAY_BUFFER, imgWidth*imgHeihgt * 2 * sizeof(GLfloat), uvs, GL_STATIC_DRAW); 
    }
     
    //创建贴图
    static void CreateTexture()
    {   
    	Mat img = imread("grass.jpg");
    	Mat resImg = Mat(256, 256, img.type());
    	resize(img, resImg, resImg.size(), 0, 0, INTER_LINEAR);
    	cv::cvtColor(resImg, resImg, CV_BGR2RGB);
    	glGenTextures(1, &TexBO);
    	glBindTexture(GL_TEXTURE_2D, TexBO); 
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, resImg.data);//设定纹理 
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//重复纹理
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//滤波
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
    	glGenerateMipmap(GL_TEXTURE_2D);
    	glBindTexture(GL_TEXTURE_2D, 0);   
    	TextureID = glGetUniformLocation(ShaderProgram, "myTexture");  
    }
    // 使用shader文本编译shader对象,并绑定shader到着色器程序中
    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("terrainTest1");   // 窗口标题 
    								 
    	GLenum res = glewInit();
    	if (res != GLEW_OK) {
    		fprintf(stderr, "Error: '%s'
    ", glewGetErrorString(res));
    		return 1;
    	}
    
    	// 开始渲染
    	glutDisplayFunc(RenderScenceCB); 
    	// 注册键盘事件
    	glutSpecialFunc(SpecialKeyboardCB);
    	//注册鼠标事件
    	glutPassiveMotionFunc(PassiveMouseCB);
    	mouseX = windowWidth / 2;
    	mouseY = windowHeight / 2;
    	// 缓存清空后的颜色值
    	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
    	//创建顶点
    	CreateVertexBuffer();
    	//创建索引
    	CreateIndexBuffer();
    	//创建uv
    	CreateUVBuffer();
    	//创建贴图
    	CreateTexture();
    	// 编译着色器
    	CompileShaders();   
    	//开启深度测试
    	glEnable(GL_DEPTH_TEST);
    	// 通知开始GLUT的内部循环
    	glutMainLoop();   
    	delete vertices;
    	return 0;
    }
    
    shader.vs 如下
    #version 330 
    layout (location = 0) in vec3 Position;
    layout(location = 1) in vec2 vertexUV; 
    // WVP标准
    uniform mat4 gWVP; 
    out vec2 UV; 
    void main()
    {
        gl_Position = gWVP * vec4(Position, 1.0);
        UV = vertexUV;
    }
    
    shader.fs如下
    #version 330 
    in vec2 UV; 
    out vec3 FragColor; 
    uniform sampler2D myTexture; 
    void main()
    {
        FragColor = texture( myTexture, UV ).rgb;  
    }
    
    参考链接

    本文链接

    https://www.cnblogs.com/gucheng/p/10125162.html

  • 相关阅读:
    2017.5.8下午
    2017.5.8上午
    2017.5.5下午
    2017.5.5上午
    2017.5.4下午
    WPF DataGrid LoadingRow style 滚动失效
    centos nginx 环境变量
    Kettle-03-定时转换
    Kettle-02-转换
    Kettle-01-安装(CentOS 7 离线)
  • 原文地址:https://www.cnblogs.com/gucheng/p/10125162.html
Copyright © 2011-2022 走看看