opengl读取灰度图生成三维地形并添加光照
转自:https://www.cnblogs.com/gucheng/p/10152889.html
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;//贴图对象
GLuint NormalBO;//法线对象
//光照定义
struct {
GLuint Color;//颜色
GLuint AmbientIntensity;//环境光强度
GLuint Direction;//方向
GLuint DiffuseIntensity;//漫反射强度
} m_dirLightLocation;
static GLfloat *vertices;
static unsigned int *indices;
static GLfloat *uvs;
static GLfloat *normals; GLuint ShaderProgram;
GLuint MatrixID;
GLuint MatrixID2;
GLuint TextureID; int windowWidth = ;
int windowHeight = ;
int imgWidth;
int imgHeihgt;
float verticeScale = 0.1f;
float yScale = 5.0f;
//相机参数
glm::mat4 ViewMatrix;//视图矩阵
glm::mat4 ProjectionMatrix; //投影矩阵
glm::mat4 MVP;//模型视图矩阵
glm::mat4 ModelMatrix;//模型矩阵
glm::vec3 position = glm::vec3(, , ); //相机位置
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),
,
cos(horizontalAngle - 3.14f / 2.0f)
);
glm::vec3 up = glm::cross(right, direction); switch (Key) {
case 'w':
position += direction * speed;
//fprintf(stderr, "up \n");
break;
case 'd':
position += right * speed;
//fprintf(stderr, "right \n");
break;
case 's':
position -= direction * speed;
//fprintf(stderr, "down \n");
break;
case 'a':
position -= right * speed;
//fprintf(stderr, "left \n");
break;
case :
exit();
break;
default:
break;
//fprintf(stderr, "Unimplemented GLUT key\n");
//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(, , );
}
} //渲染回调函数
void RenderScenceCB() {
// 清空颜色缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br> //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//线框模式
//传递矩阵数据
glUniformMatrix4fv(MatrixID, , GL_FALSE, &MVP[][]);
glUniformMatrix4fv(MatrixID2,, GL_FALSE,&ModelMatrix[][]);
//传递光照
glUniform3f(m_dirLightLocation.Color, , , );
glUniform1f(m_dirLightLocation.AmbientIntensity, 0.5);
glUniform3f(m_dirLightLocation.Direction,,,);
glUniform1f(m_dirLightLocation.DiffuseIntensity,0.7);
//传递顶点、索引、UV、法线
glEnableVertexAttribArray(); //开启顶点属性
glBindBuffer(GL_ARRAY_BUFFER, VBO); //绑定GL_ARRAY_BUFFER缓冲器
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , ); //告诉管线怎样解析bufer中的数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glEnableVertexAttribArray();
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
glEnableVertexAttribArray();
glBindBuffer(GL_ARRAY_BUFFER, NormalBO);
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
//传递贴图纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TexBO);
glUniform1i(TextureID, );
//绘制
glDrawElements(GL_TRIANGLES_ADJACENCY, (imgWidth - )*(imgHeihgt - ) * * , GL_UNSIGNED_SHORT, );
glDisableVertexAttribArray();
glDisableVertexAttribArray();
glDisableVertexAttribArray();
//交换前后缓存
glutSwapBuffers();
} //创建顶点
static void CreateVertexBuffer()
{
//读取图片
Mat img = imread("T2.png");
int imgType = img.type();
Mat resImg = Mat(img.rows, img.cols, imgType);
resize(img, resImg, resImg.size(), , , INTER_LINEAR);
Mat gImg = Mat(img.rows, img.cols, CV_8UC1); //灰度图
cv::cvtColor(resImg, gImg, CV_BGR2GRAY);//bgr转灰度
imgWidth = resImg.rows;
imgHeihgt = resImg.cols;
vertices = new GLfloat[imgWidth*imgHeihgt * ];
int k = ;
for (int i = ; i < imgHeihgt; i++)
{
for (int j = ; j < imgWidth; j++)
{
vertices[k++] = verticeScale* (float)i;
int c = (int)gImg.at<uchar>(j, i);
vertices[k++] = yScale*(float)c / 255.0f;
vertices[k++] = verticeScale*(float)j;
}
}
glGenBuffers(, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, imgWidth*imgHeihgt * * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
}
//创建索引
static void CreateIndexBuffer()
{
indices = new unsigned int[(imgWidth - )*(imgHeihgt - ) * ];
int k = ; for (int i = ; i < imgHeihgt - ; i++)
{
for (int j = ; j < imgWidth - ; j++)
{
indices[k++] = i*imgWidth + j;
indices[k++] = i*imgWidth + j + ;
indices[k++] = i*imgWidth + j + imgWidth;
indices[k++] = i*imgWidth + j + imgWidth;
indices[k++] = i*imgWidth + j + ;
indices[k++] = i*imgWidth + j + imgWidth + ;
}
}
glGenBuffers(, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (imgWidth - )*(imgHeihgt - ) * * sizeof(unsigned int), indices, GL_STATIC_DRAW); }
//创建uv
static void CreateUVBuffer()
{
uvs = new GLfloat[imgWidth*imgHeihgt * ];
int k = ;
for (int i = ; i < imgHeihgt; i++)
{
for (int j = ; j < imgWidth; j++)
{
uvs[k++] = (float)i / (float)(imgHeihgt);
uvs[k++] = (float)j / (float)(imgWidth);
}
}
glGenBuffers(, &UVBO);
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glBufferData(GL_ARRAY_BUFFER, imgWidth*imgHeihgt * * sizeof(GLfloat), uvs, GL_STATIC_DRAW);
} //创建贴图
static void CreateTexture()
{
Mat img = imread("T2.png");
Mat resImg = Mat(, , img.type());
resize(img, resImg, resImg.size(), , , INTER_LINEAR);
cv::cvtColor(resImg, resImg, CV_BGR2RGB);
glGenTextures(, &TexBO);
glBindTexture(GL_TEXTURE_2D, TexBO);
glTexImage2D(GL_TEXTURE_2D, , GL_RGB, , , , 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, );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, );
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, );
TextureID = glGetUniformLocation(ShaderProgram, "myTexture");
} //创建法线
static void CreateNormal()
{
normals= new GLfloat[imgWidth*imgHeihgt*];
int k = ;
//遍历索引三角
for (size_t i = ; i < (imgWidth - )*(imgHeihgt - ) * ; i+=)
{
static unsigned int pIndex1 = indices[i];
static unsigned int pIndex2 = indices[i + ];
static unsigned int pIndex3 = indices[i + ];
static float x1 = vertices[pIndex1];
static float y1 = vertices[pIndex1 + ];
static float z1 = vertices[pIndex1 + ];
static float x2 = vertices[pIndex2];
static float y2 = vertices[pIndex2 + ];
static float z2 = vertices[pIndex2 + ];
static float x3 = vertices[pIndex3];
static float y3 = vertices[pIndex3 + ];
static float z3 = vertices[pIndex3 + ];
//求边
static float vx1 = x2 - x1;
static float vy1 = y2 - y1;
static float vz1 = z2 - z1;
static float vx2 = x3 - x1;
static float vy2 = y3 - y1;
static float vz2 = z3 - z1;
//叉乘求三角形法线
static float xN = vy1 * vz2 - vz1 *vy2;
static float yN = vz1 * vx2 - vx1 * vz2;
static float zN = vx1 * vy2 - vy1 * vx2;
static float Length = sqrtf(xN * xN + yN * yN + zN * zN);
xN /= Length;
yN /= Length;
zN /= Length;
//顶点法线更新
normals[pIndex1] += xN;
normals[pIndex1 + ] += yN;
normals[pIndex1 + ] += zN;
normals[pIndex2] += xN;
normals[pIndex2 + ] += yN;
normals[pIndex2 + ] += zN;
normals[pIndex3] += xN;
normals[pIndex3 + ] += yN;
normals[pIndex3 + ] += zN;
}
glGenBuffers(, &NormalBO);
glBindBuffer(GL_ARRAY_BUFFER, NormalBO);
glBufferData(GL_ARRAY_BUFFER, imgWidth*imgHeihgt * * sizeof(GLfloat), normals, GL_STATIC_DRAW);
} // 使用shader文本编译shader对象,并绑定shader到着色器程序中
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
// 根据shader类型参数定义两个shader对象
GLuint ShaderObj = glCreateShader(ShaderType);
// 检查是否定义成功
if (ShaderObj == ) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit();
}
// 定义shader的代码源
const GLchar* p[];
p[] = pShaderText;
GLint Lengths[];
Lengths[] = strlen(pShaderText);
glShaderSource(ShaderObj, , p, Lengths);
glCompileShader(ShaderObj);// 编译shader对象
// 检查和shader相关的错误
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[];
glGetShaderInfoLog(ShaderObj, , NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit();
}
// 将编译好的shader对象绑定到program object程序对象上
glAttachShader(ShaderProgram, ShaderObj);
} // 编译着色器函数
static void CompileShaders()
{
// 创建着色器程序
ShaderProgram = glCreateProgram();
// 检查是否创建成功
if (ShaderProgram == ) {
fprintf(stderr, "Error creating shader program\n");
exit();
}
// 存储着色器文本的字符串
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();
}
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 = ;
GLchar ErrorLog[] = { };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == ) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit();
}
// 检查验证在当前的管线状态程序是否可以被执行
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();
}
glUseProgram(ShaderProgram);
//统一变量位置
MatrixID = glGetUniformLocation(ShaderProgram, "gWVP");
MatrixID2= glGetUniformLocation(ShaderProgram, "gWorld");
m_dirLightLocation.Color = glGetUniformLocation(ShaderProgram,"gDirectionalLight.Color");
m_dirLightLocation.AmbientIntensity = glGetUniformLocation(ShaderProgram,"gDirectionalLight.AmbientIntensity");
m_dirLightLocation.Direction = glGetUniformLocation(ShaderProgram,"gDirectionalLight.Direction");
m_dirLightLocation.DiffuseIntensity = glGetUniformLocation(ShaderProgram,"gDirectionalLight.DiffuseIntensity");
} int main(int argc, char ** argv) {
// 初始化GLUT
glutInit(&argc, argv);
// 显示模式:双缓冲、RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// 窗口设置
glutInitWindowSize(windowWidth, windowHeight); // 窗口尺寸
glutInitWindowPosition(, ); // 窗口位置
glutCreateWindow("terrainTest2"); // 窗口标题 GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return ;
} // 开始渲染
glutDisplayFunc(RenderScenceCB);
// 注册键盘事件
glutKeyboardFunc(SpecialKeyboardCB);
//注册鼠标事件
glutMouseFunc(mouseCB);
glutMotionFunc(mouseMotionCB);
mouseX = windowWidth / ;
mouseY = windowHeight / ;
// 缓存清空后的颜色值
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//创建顶点
CreateVertexBuffer();
//创建索引
CreateIndexBuffer();
//创建uv
CreateUVBuffer();
//创建贴图
CreateTexture();
//创建法线
CreateNormal();
// 编译着色器
CompileShaders();
//开启深度测试
glEnable(GL_DEPTH_TEST);
// 通知开始GLUT的内部循环
glutMainLoop();
delete vertices;
return ;
}
shader.vs
#version
layout (location = ) in vec3 Position;
layout (location = ) in vec2 vertexUV;
layout (location = ) in vec3 Normal;
uniform mat4 gWVP;
uniform mat4 gWorld;
out vec2 UV;
out vec3 Normal0;
void main()
{
gl_Position = gWVP * vec4(Position, 1.0);
UV = vertexUV;
Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
}
shader.fs
#version
in vec2 UV;
in vec3 Normal0;
out vec4 FragColor;
//光照
struct DirectionalLight
{
vec3 Color;
float AmbientIntensity;
float DiffuseIntensity;
vec3 Direction;
};
uniform DirectionalLight gDirectionalLight;
uniform sampler2D myTexture;
void main()
{
//环境光
vec4 AmbientColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.AmbientIntensity;
//漫反射
float DiffuseFactor = dot(normalize(Normal0), -gDirectionalLight.Direction);
vec4 DiffuseColor;
if (DiffuseFactor > ) {
DiffuseColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.DiffuseIntensity *
DiffuseFactor;
}
else {
DiffuseColor = vec4(, , , );
}
FragColor = texture2D(myTexture, UV.xy) *
(AmbientColor + DiffuseColor); }
opengl读取灰度图生成三维地形并添加光照的更多相关文章
- opengl读取灰度图生成三维地形
准备第三方库 glew.freeglut.glm.opencv 准备灰度图片和草地贴图 最终效果 代码包括主程序源文件mainApp.cpp.顶点着色器shader.vs.片元着色器shader.fs ...
- unity读取灰度图生成三维地形mesh
准备灰度图 IGray.png及草地贴图 IGrass.jpg ,放入Assets下StreamingAssets文件夹中. 创建空材质,用作参数传入脚本. 脚本如下,挂载并传入材质球即可 ...
- ue4读取灰度图生成三维地形mesh
转自:https://www.cnblogs.com/gucheng/p/10116857.html 新建ue c++工程. 在Build.cs中添加"ProceduralMeshCompo ...
- unity 读取灰度图生成三维地形并贴图卫星影像
从 https://earthexplorer.usgs.gov/ 下载高程数据 从谷歌地球上保存对应地区卫星图像 从灰度图创建地形模型,并将卫星影像作为贴图 using System.Collect ...
- unity 读取灰度图生成按高程分层设色地形模型
准备灰度图 1.高程按比例对应hue色相(hsv)生成mesh效果 o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0 ...
- unity读取灰度图生成等值线图
准备灰度图 grayTest.png,放置于Assets下StreamingAssets文件夹中. 在场景中添加RawImage用于显示最后的等值线图. 生成等值线的过程,使用Marching ...
- blender导入灰度图生成地形模型
安装软件 在此处下载blender并安装. 添加平面 1.打开blender,右键删除初始的立方体. 2.shift+a选择平面添加进场景: 3.按下s键鼠标拖动调节平面大小确定后按下鼠标左键: 4. ...
- (二)GameMaker:Studio ——使用等高图生成3D地形
上一篇,我们讲解了GM中导入模型的方法,这节我们来讲地形. 源文件地址:http://pan.baidu.com/share/link?shareid=685772423&uk=2466343 ...
- c语言实现灰度图转换为二值图
将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置为255,为得到更好的效果不同图片应采用不同的值 /* 2015年6月2日11:16:22 灰度图转换为二值图 blog:http ...
随机推荐
- unix域套接字
对于本地通信,unix域套接字通信是internet通信速度的2倍
- 牛客1024B 石头游戏
题目描述 石头游戏在一个 \(n\) 行 \(m\) 列 \((1\leq n,m \leq 8)(1≤n,m≤8)\) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这1 ...
- docker-compose更新image命令
docker-compose stop docker-compose up -d --build
- php导出表格两种方法 ——PhpExcel的列子
php常用的导出表格有两种方法,第一种是输出表格,这种方法打开的时候有警告提示,一般导出表格会用phpexcel,这个导出比较灵活,而且还可以设置表格的样式. 第一种导出例子 /** * 执行导出 * ...
- 一. python 安装
1. 下载安装包 1 2 3 https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi # 2.7安装包 https: ...
- 微信H5中禁止分享好友及分享到朋友圈的方法
我们可以直接把以下代码加入到页面中,即可限制住各类分享. <script> function onBridgeReady() { WeixinJSBridge.call('hideOpti ...
- 关于System.BadImageFormatException
什么是BadImageFormatException BadImageFormatException是当动态链接库 (DLL) 或可执行程序的文件映像无效时引发的异常. 可能的原因 如果动态链接库 ( ...
- C# 读取Excel 单元格是日期格式
原文地址:https://www.cnblogs.com/liu-xia/p/5230768.html DateTime.FromOADate(double.Parse(range.Value2.To ...
- 通过三层交换机实现不同VLAN间的通信
主机的IP地址以及子网掩码已列出,下面将讲解如何配置利用三层交换机来实现不同VLAN间的相互通信 SW1的命令: en //进入特权模式 conf t //全局模式 vlan 10 // ...
- AGC028 E - High Elements
AGC028 E - High Elements 有一个排列\(p\),你要分成两个子序列\(A,B\),满足\(A,B\)的LIS长度相等.设\(S\)是一个\(01\)序列,\(S_i=0\)当且 ...