准备第三方库 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\n");
break;
case GLUT_KEY_RIGHT:
position += right * speed;
fprintf(stderr, "right key\n");
break;
case GLUT_KEY_DOWN:
position -= direction * speed;
fprintf(stderr, "down key\n");
break;
case GLUT_KEY_LEFT:
position -= right * speed;
fprintf(stderr, "left key\n");
break;
case GLUT_KEY_F4:
exit(1);
default:
fprintf(stderr, "Unimplemented GLUT key\n");
//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\n", 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\n", 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'\n", ShaderType, InfoLog);
exit(1);
}
// 将编译好的shader对象绑定到program object程序对象上
glAttachShader(ShaderProgram, ShaderObj);
} // 编译着色器函数
static void CompileShaders()
{
// 创建着色器程序
ShaderProgram = glCreateProgram();
// 检查是否创建成功
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
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\n", 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'\n", 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'\n", 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'\n", 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

opengl读取灰度图生成三维地形的更多相关文章

  1. opengl读取灰度图生成三维地形并添加光照

    转自:https://www.cnblogs.com/gucheng/p/10152889.html 准备第三方库 glew.freeglut.glm.opencv 准备一张灰度图 最终效果 代码如下 ...

  2. unity读取灰度图生成三维地形mesh

    准备灰度图 IGray.png及草地贴图 IGrass.jpg ,放入Assets下StreamingAssets文件夹中.     创建空材质,用作参数传入脚本.   脚本如下,挂载并传入材质球即可 ...

  3. ue4读取灰度图生成三维地形mesh

    转自:https://www.cnblogs.com/gucheng/p/10116857.html 新建ue c++工程. 在Build.cs中添加"ProceduralMeshCompo ...

  4. unity 读取灰度图生成三维地形并贴图卫星影像

    从 https://earthexplorer.usgs.gov/ 下载高程数据 从谷歌地球上保存对应地区卫星图像 从灰度图创建地形模型,并将卫星影像作为贴图 using System.Collect ...

  5. unity 读取灰度图生成按高程分层设色地形模型

    准备灰度图 1.高程按比例对应hue色相(hsv)生成mesh效果 o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0 ...

  6. unity读取灰度图生成等值线图

    准备灰度图 grayTest.png,放置于Assets下StreamingAssets文件夹中.   在场景中添加RawImage用于显示最后的等值线图.   生成等值线的过程,使用Marching ...

  7. blender导入灰度图生成地形模型

    安装软件 在此处下载blender并安装. 添加平面 1.打开blender,右键删除初始的立方体. 2.shift+a选择平面添加进场景: 3.按下s键鼠标拖动调节平面大小确定后按下鼠标左键: 4. ...

  8. (二)GameMaker:Studio ——使用等高图生成3D地形

    上一篇,我们讲解了GM中导入模型的方法,这节我们来讲地形. 源文件地址:http://pan.baidu.com/share/link?shareid=685772423&uk=2466343 ...

  9. c语言实现灰度图转换为二值图

    将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置为255,为得到更好的效果不同图片应采用不同的值 /* 2015年6月2日11:16:22 灰度图转换为二值图 blog:http ...

随机推荐

  1. tomcat配置CA证书后,https的接口url请求很慢,大概率会超时

    背景:项目需要使用websocket长连接,走nginx反向代理会断开,所以决定要直连项目 [websocket连接https需要使用wss] 项目端口: 项目名:biubiu https证书端口: ...

  2. ASP.NET Core 2.0身份和角色管理入门

    见  https://blog.csdn.net/mzl87/article/details/84892916 https://www.codeproject.com/Articles/1235077 ...

  3. 《流畅的Python》 Sequence Hacking, Hashing and Slicing(没完成)

    序列修改,散列和切片 基本序列协议:Basic sequence protocol: __len__ and __getitem__ 本章通过代码讨论一个概念: 把protocol当成一个正式接口.协 ...

  4. Selenium(七)多窗口切换、等待方法、alert对话框处理

    一.多窗口切换 1.打开百度首页 2.在百度中搜索博客园 3.从搜索结果中跳转到博客园 4.博客园首页和百度搜索页面切换 handle:句柄 二.等待方法 time.sleep(5) 先导入方法 参数 ...

  5. Python+request 测试结果结合unittest生成测试报告《四》

    测试报告示例图:      目录结构介绍: 主要涉及更改的地方: 1.导入 Common.HTMLTestRunner2文件 2.run_test.py文件中新增测试报告相关的代码 具体代码实现: 1 ...

  6. Java集合--Map总结

    转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311126 第1部分 Map概括 (01) Map ...

  7. ajax向后台传递数组参数并将后台响应的数据赋值给一个变量供其它插件使用

    1.在js中封装ajax向后台传递数组参数函数 //combogrid * * @Description 封装ajax向后台传递数组参数并将后台响应的数据赋值给一个变量方便其他插件使用该数据函数 * ...

  8. 二进制文件方式安装kubernetes集群

    所有操作全部用root使用者进行,高可用一般建议大于等于3台的奇数,我们使用3台master来做高可用 练习环境说明: 参考GitHub master: kube-apiserver,kube-con ...

  9. Java中堆内存和栈内存有什么区别

    本文链接:https://blog.csdn.net/wangbo1998/article/details/80379016Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基 ...

  10. 【线性代数】6-2:对角化(Diagonalizing a Matrix)

    title: [线性代数]6-2:对角化(Diagonalizing a Matrix) categories: Mathematic Linear Algebra keywords: Eigenva ...