openGL使用高度贴图模拟地球表面凹凸效果

网友投稿 1557 2022-11-20

openGL使用高度贴图模拟地球表面凹凸效果

openGL使用高度贴图模拟地球表面凹凸效果

openGL系列文章目录

文章目录

​​openGL系列文章目录​​​​前言​​​​一、高度贴图是什么​​​​二、代码​​

​​1.c++主程序​​​​2.着色器程序​​

​​运行效果​​​​源码-​​

前言

一、高度贴图是什么

现在我们扩展法线贴图的概念——从纹理图像用于扰动法向量到扰乱顶点位置本身。实 际上,以这种方式修改对象的几何体具有一定的优势,例如使表面特征沿着对象的边缘可 见,并使特征能够响应阴影贴图。我们将会看到,它还可以帮助构建地形。 一种实用的方法是使用纹理图像来存储高度值,然后使用该高度值来提升(或降低)顶 点位置。含有高度信息的图像称为高度图,使用高度图更改对象的顶点的方法称为高度贴 图①。高度图通常将高度信息编码为灰度颜色:(0,0,0)(黑色)=低高度,(1,1,1)(白色)= 高高度。这样一来通过算法或使用“画图”程序就可以轻松创建高度图。图像的对比度越 高,其表示的高度变化越大。这些概念将在图10.12(显示随机生成的地图)和图10.13(显 示有组织的模式的地图)中说明。

二、代码

1.c++主程序

#include "glew/glew.h"#include "glfw/glfw3.h"#include "glm/glm.hpp"#include "glm/gtc/matrix_transform.hpp"#include "glm/gtc/type_ptr.hpp"#include "camera.h"#include "Utils.h"#include "Sphere.h"#include #include #include using namespace std;static const int screenWidth = 1920;static const int screenHeight = 1080;int width = 0, height = 0;static const float pai = 3.1415926f;float toRadians(float degrees) { return degrees * 2.f * pai / (float)360.f; }static const int numVAOs = 1;static const int numVBOs = 4;float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;float sphereX = 0.f, sphereY = 0.f, sphereZ = 0.f;float lightLocX = 0.f, lightLocY = 0.f, lightLocZ = 0.f;GLuint renderingProgram = 0;GLuint vao[numVAOs] = { 0 };GLuint vbo[numVBOs] = { 0 };// variable allocation for displayGLuint mvLoc = 0, projLoc = 0, nLoc = 0;GLuint globalAmbLoc = 0, ambLoc = 0, diffLoc = 0, specLoc = 0, posLoc = 0, mAmbLoc = 0, mDiffLoc = 0, mSpecLoc = 0, mShinLoc = 0;float aspect = 0;glm::mat4 mMat(1.f), vMat(1.f), pMat(1.f), mvMat(1.f), invTrMat(1.f);glm::vec3 currentLightPos(0.f);float lightPos[3] = { 0.f };float rotAmb = 0.f;Sphere mySphere(96);int numSphereVertices = 0;int numSphereIndices = 0;GLuint colorTexture = 0;GLuint normalTexture = 0;GLuint heightTexture = 0;// white lightfloat globalAmbient[4] = { 0.1f, 0.1f, 0.1f, 1.f };float lightAmbient[4] = { 0.f, 0.f, 0.f, 1.f };float lightDiffuse[4] = { 1.0f, 1.0f, 1.f, 1.f };float lightSpecular[4] = { 1.f, 1.f, 1.f, 1.f };// silver materialfloat* matAmbi = Utils::silverAmbient();float* matDiff = Utils::silverDiffuse();float* matSpec = Utils::silverSpecular();float matShin = Utils::silverShininess();Camera camera(glm::vec3(0.f, 0.f, 1.f));//float cameraX = 0.f, cameraY = 0.f, cameraZ = 5.f;GLboolean keys[1024] = { GL_FALSE };GLboolean b_firstMouse = GL_TRUE;float deltaTime = 0.f;float lastFrame = 0.f;float lastLocX = 0.f;float lastLocY = 0.f;void do_movement(){ if (keys[GLFW_KEY_W]) { camera.ProcessKeyboard(FORWARD, deltaTime); } if (keys[GLFW_KEY_S]) { camera.ProcessKeyboard(BACKWARD, deltaTime); } if (keys[GLFW_KEY_A]) { camera.ProcessKeyboard(LEFT, deltaTime); } if (keys[GLFW_KEY_D]) { camera.ProcessKeyboard(RIGHT, deltaTime); } /*if (keys[GLFW_KEY_ESCAPE]) { glfwSetWindowShouldClose(window, GL_TRUE); }*/}void key_press_callback(GLFWwindow* window, int key, int scancode, int action, int mode){ if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS)) { glfwSetWindowShouldClose(window, GL_TRUE); } if (action == GLFW_PRESS) { keys[key] = GLFW_TRUE; //这里一定一定不能写成“==“,否则 按键WSAD按键失效!!!!!!! } else if (action == GLFW_RELEASE) { keys[key] = GLFW_FALSE; //这里一定一定不能写成“==“,否则 按键WSAD按键失效!!!!!!! }}void mouse_move_callback(GLFWwindow* window, double xPos, double yPos){ if (b_firstMouse) { lastLocX = xPos; lastLocY = yPos; b_firstMouse = GL_FALSE; } float xOffset = xPos - lastLocX; float yOffset = lastLocY - yPos; lastLocX = xPos; lastLocY = yPos; camera.ProcessMouseMovement(xOffset, yOffset);}void mouse_scroll_callback(GLFWwindow* window, double xPos, double yPos){ camera.ProcessMouseScroll(yPos);}void setupVertices(){ int numSphereVertices = mySphere.getNumVertices(); numSphereIndices = mySphere.getNumIndices(); vector ind = mySphere.getIndices(); vector vert = mySphere.getVertices(); vector text = mySphere.getTexCoords(); vector norm = mySphere.getNormals(); vector tang = mySphere.getTangents(); vector pValuse; vector tValues; vector nValues; vector tanValues; for (int i = 0; i< mySphere.getNumIndices(); i++) { //pValuse.push_back(vert[ind[i]].x); pValuse.push_back(vert[ind[i]].x); pValuse.push_back(vert[ind[i]].y); pValuse.push_back(vert[ind[i]].z); tValues.push_back(text[ind[i]].s); tValues.push_back(text[ind[i]].t); nValues.push_back(norm[ind[i]].x); nValues.push_back(norm[ind[i]].y); nValues.push_back(norm[ind[i]].z); tanValues.push_back(tang[ind[i]].x); tanValues.push_back(tang[ind[i]].y); tanValues.push_back(tang[ind[i]].z); } glGenVertexArrays(numVAOs, vao); glBindVertexArray(vao[0]); glGenBuffers(numVBOs, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, pValuse.size() * sizeof(float), &pValuse[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferData(GL_ARRAY_BUFFER, tValues.size() * sizeof(float), &tValues[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo[2]); glBufferData(GL_ARRAY_BUFFER, nValues.size() * sizeof(float), &nValues[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo[3]); glBufferData(GL_ARRAY_BUFFER, tanValues.size() * sizeof(float), &tanValues[0], GL_STATIC_DRAW);}void installLights(glm::mat4 vMatrix){ glm::vec3 transformed = glm::vec3(vMatrix * glm::vec4(currentLightPos, 1.f)); lightPos[0] = transformed.x; lightPos[1] = transformed.y; lightPos[2] = transformed.z; // get the locations of the light and material fields in the shader globalAmbLoc = glGetUniformLocation(renderingProgram, "globalAmbient"); ambLoc = glGetUniformLocation(renderingProgram, "light.ambient"); diffLoc = glGetUniformLocation(renderingProgram, "light.diffuse"); specLoc = glGetUniformLocation(renderingProgram, "light.specular"); posLoc = glGetUniformLocation(renderingProgram, "light.position"); mAmbLoc = glGetUniformLocation(renderingProgram, "material.ambient"); mDiffLoc = glGetUniformLocation(renderingProgram, "material.diffuse"); mSpecLoc = glGetUniformLocation(renderingProgram, "material.specular"); mShinLoc = glGetUniformLocation(renderingProgram, "material.shininess"); // set the uniform light and material values in the shader glUniformMatrix4fv(globalAmbLoc, 1, GL_FALSE, globalAmbient); glUniformMatrix4fv(ambLoc, 1, GL_FALSE, lightAmbient); glUniformMatrix4fv(diffLoc, 1, GL_FALSE, lightDiffuse); glUniformMatrix4fv(specLoc, 1, GL_FALSE, lightSpecular); glUniformMatrix3fv(posLoc, 1, GL_FALSE, lightPos); glUniformMatrix4fv(mAmbLoc, 1, GL_FALSE, matAmbi); glUniformMatrix4fv(mDiffLoc, 1, GL_FALSE, matDiff); glUniformMatrix4fv(mSpecLoc, 1, GL_FALSE, matSpec); glUniform1f(mShinLoc, matShin); /*glProgramUniform4fv(renderingProgram, globalAmbLoc, 1, globalAmbient); glProgramUniform4fv(renderingProgram, ambLoc, 1, lightAmbient); glProgramUniform4fv(renderingProgram, diffLoc, 1, lightDiffuse); glProgramUniform4fv(renderingProgram, specLoc, 1, lightSpecular); glProgramUniform3fv(renderingProgram, posLoc, 1, lightPos); glProgramUniform4fv(renderingProgram, mAmbLoc, 1, matAmbi); glProgramUniform4fv(renderingProgram, mDiffLoc, 1, matDiff); glProgramUniform4fv(renderingProgram, mSpecLoc, 1, matSpec); glProgramUniform1f(renderingProgram, mShinLoc, matShin);*/}void init(GLFWwindow* window){ renderingProgram = Utils::createShaderProgram("vertShader.vert", "fragShader.frag"); cameraX = 0.f, cameraY = 0.f, cameraZ = 2.f; sphereX = 0.f, sphereY = 0.f, sphereZ = -1.f; lightLocX = 3.f, lightLocY = 2.f, lightLocZ = 3.f; //试着改变光源位置,看变化效果 glfwGetFramebufferSize(window, &width, &height); aspect = (float)width / (float)height; pMat = glm::perspective(toRadians(45.f), aspect, 0.01f, 1000.f); setupVertices(); colorTexture = Utils::loadTexture("earthspec1kBLUE.jpg"); normalTexture = Utils::loadTexture("earthspec1kNORMAL.jpg"); heightTexture = Utils::loadTexture("earthspec1kNEG.jpg");}void display(GLFWwindow* window, double currentTime){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.1f, 0.2f, 0.5f, 1.f); glUseProgram(renderingProgram); deltaTime = currentTime - lastFrame; lastFrame = currentTime; do_movement(); //这句必须要有,否则鼠标中键失效 pMat = glm::perspective(camera.Zoom, aspect, 0.1f, 1000.f); //没有这句,背景就没在相机视点上了,把圆环移到相机的位置 //mMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, 4.5f)); vMat = camera.GetViewMatrix(); mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix"); projLoc = glGetUniformLocation(renderingProgram, "proj_matrix"); nLoc = glGetUniformLocation(renderingProgram, "norm_matrix"); glfwGetFramebufferSize(window, &width, &height); aspect = (float)width / (float)height; pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f); //vMat = glm::translate(glm::mat4(1.f), glm::vec3(-cameraX, -cameraY, -cameraZ)); mMat = glm::translate(glm::mat4(1.f), glm::vec3(sphereX, sphereY, sphereZ)); mMat = glm::rotate(mMat, toRadians(35.f), glm::vec3(0.f, 1.f, 0.f)); mMat = glm::rotate(mMat, rotAmb, glm::vec3(0.f, 1.f, 0.f)); rotAmb += 0.002f; mvMat = vMat * mMat; invTrMat = glm::transpose(glm::inverse(mvMat)); currentLightPos = glm::vec3(lightLocX, lightLocY, lightLocZ); installLights(mvMat); //vMat glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat)); glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat)); glUniformMatrix4fv(nLoc, 1, GL_FALSE, glm::value_ptr(invTrMat)); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, vbo[2]); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, vbo[3]); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(3); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, colorTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, normalTexture); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, heightTexture); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());}void window_size_callback(GLFWwindow* window, int newWidth, int newHeight){ aspect = (float)newWidth / (float)newHeight; glViewport(0, 0, newWidth, newHeight); pMat = glm::perspective(toRadians(45.f), aspect, 0.01f, 1000.f);}int main(int argc, char** argv){ int glfwState = glfwInit(); if (GLFW_FALSE == glfwState) { cout << "GLFW initialize failed, invoke glfwInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl; glfwTerminate(); exit(EXIT_FAILURE); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "Sphere vertex height map", nullptr, nullptr); if (!window) { cout << "GLFW create window failed, invoke glfwCreateWindow()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl; glfwTerminate(); exit(EXIT_FAILURE); } glfwMakeContextCurrent(window); int glewState = glewInit(); if (GLEW_OK != glewState) { cout << "GLEW initialize failed, invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl; glfwTerminate(); exit(EXIT_FAILURE); } glfwSetWindowSizeCallback(window, window_size_callback); glfwSetCursorPosCallback(window, mouse_move_callback); glfwSetScrollCallback(window, mouse_scroll_callback); glfwSetKeyCallback(window, key_press_callback); glfwSwapInterval(1); init(window); while (!glfwWindowShouldClose(window)) { display(window, glfwGetTime()); glfwSwapBuffers(window); glfwPollEvents(); } glfwDestroyWindow(window); glfwTerminate(); exit(EXIT_SUCCESS); return 0;}

2.着色器程序

1.顶点着色器

#version 460 corelayout(location = 0) in vec3 vertPos;layout(location = 1) in vec2 texCoord;layout(location = 2) in vec3 vertNormal;layout(location = 3) in vec3 vertTangent;out vec3 varyingLightDir;out vec3 varyingVertPos;out vec3 varyingNormal;out vec3 varyingTangent;out vec2 tc;layout(binding = 0) uniform sampler2D t;layout(binding = 1) uniform sampler2D n;layout(binding = 2) uniform sampler2D h;struct PositionalLight{ vec4 ambient; vec4 diffuse; vec4 specular; vec3 position;};struct Material{ vec4 ambient; vec4 diffuse; vec4 specular; float shininess;};uniform vec4 globalAmbient;uniform PositionalLight light;uniform Material material;uniform mat4 mv_matrix;uniform mat4 proj_matrix;uniform mat4 norm_matrix;void main(void){ varyingNormal = (norm_matrix * vec4(vertNormal, 1.f)).xyz; varyingTangent = (norm_matrix * vec4(vertTangent, 1.f)).xyz; vec4 P1 = vec4(vertPos, 1.f); vec4 P2 = vec4((vertNormal * ((texture(h, texCoord).r) / 15.f)), 1.f); vec4 P = vec4((P1.xyz + P2.xyz), 1.f); varyingVertPos = (mv_matrix * P).xyz; varyingLightDir = light.position - varyingVertPos; tc = texCoord; gl_Position = proj_matrix * mv_matrix * P; //MVP}

2.片元着色器

#version 460 corein vec3 varyingLightDir;in vec3 varyingVertPos;in vec3 varyingNormal;in vec3 varyingTangent;in vec2 tc;out vec4 fragColor;layout(binding = 0) uniform sampler2D t;layout(binding = 1) uniform sampler2D n;layout(binding = 2) uniform sampler2D h;struct PositionalLight{ vec4 ambient; vec4 diffuse; vec4 specular; vec3 position;};struct Material{ vec4 ambient; vec4 diffuse; vec4 specular; float shininess;};uniform vec4 globalAmbient;uniform PositionalLight light;uniform Material material;uniform mat4 mv_matrix;uniform mat4 proj_matrix;uniform mat4 norm_matrix;vec3 CalcBumpedNormal(){ vec3 Normal = normalize(varyingNormal); vec3 Tangent = normalize(varyingTangent); Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal); vec3 bitangent = cross(Tangent, Normal); vec3 bumpMapNormal = texture(n, tc).xyz; bumpMapNormal = bumpMapNormal * 2.f - 1.f; mat3 TBN = mat3(Tangent, bitangent, Normal); vec3 newNormal = TBN * bumpMapNormal; newNormal = normalize(newNormal); return newNormal;}void main(void){ // normalize the light, normal, and view vectors: vec3 L = normalize(varyingLightDir); vec3 V = normalize(varyingVertPos); //vec3 N = CalcBumpedNormal();// vec3 N = normalize(varyingNormal);//vec3 N = CalcBumpedNormal(); vec3 N = CalcBumpedNormal(); // get the angle between the light and surface normal: float cosTheta = dot(L, N); // compute light reflection vector, with respect N: vec3 R = normalize(reflect(-L, N)); // angle between the view vector and reflected light: float cosPhi = dot(V, R); // compute ADS contributions (per pixel): fragColor = 0.5f * texture(t, tc) + 0.5f * (fragColor = globalAmbient * material.ambient + light.ambient * material.ambient + light.diffuse * material.diffuse * max(cosTheta, 0.0f) + light.specular * material.specular * pow(max(cosPhi, 0.f), material.shininess));}

运行效果

源码-

​​源码-​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:openGL推荐学习资料
下一篇:visual studio 2019恢复默认设置
相关文章

 发表评论

暂时没有评论,来抢沙发吧~