OpenGL——实现几何着色器,法向量可视化

整体思路:

在几何着色其中,对每个图元的三个顶点分别做法向线向量。先采用不用几何着色器渲染模型,然后再用含有几何着色器的渲染法向线。

其中:几何着色器接受的位置向量是剪裁空间坐标,所以应该将法向量变换到相同的空间中 ,即裁剪坐标中,通过顶点着色器实现:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal; out VS_OUT { vec3 normal; } vs_out; uniform mat4 projection; uniform mat4 view; uniform mat4 model; void main() { mat3 normalMatrix = mat3(transpose(inverse(view * model))); vs_out.normal = vec3(projection * vec4(normalMatrix * aNormal, 0.0)); gl_Position = projection * view * model * vec4(aPos, 1.0); }

几何着色器:

#version 330 core
layout (triangles) in;
layout (line_strip, max_vertices = 6) out; in VS_OUT { vec3 normal; } gs_in[]; const float MAGNITUDE = 0.2; void GenerateLine(int index) { gl_Position = gl_in[index].gl_Position; EmitVertex(); gl_Position = gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE; EmitVertex(); EndPrimitive(); } void main() { GenerateLine(0);  GenerateLine(1);  GenerateLine(2);  }

片段着色器:

#version 330 core
out vec4 FragColor;

void main() { FragColor = vec4(1.0, 1.0, 0.0, 1.0); } 

主程序:

#pragma once
#include<glad/glad.h> #include<GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include "CShader.h" #include "Camera.h" #include "CModel.h" #include <iostream> void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow* window); void mouse_callback(GLFWwindow* window, double xpos, double ypos); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); unsigned int loadTexture(char const* texturePath); const unsigned int WINDOW_WIDTH = 800; const unsigned int WINDOW_HEIGHT = 600; glm::vec3 cameraPos = glm::vec3(-1.0f, -1.0f, 1.5f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); Camera camera(glm::vec3(0.0f, 0.0f, 50.0f)); glm::vec3 lightDiretion(1.2f, 1.0f, 2.0f); bool firstMouse = true; double lastX = WINDOW_WIDTH / 2; double lastY = WINDOW_HEIGHT / 2; float yaw = -90.0f; float pitch = 0.0f; float fov = 45.0f; float lastTime = 0.0f; float deltaTime = 0.0f; int OpenGL_GeometryShader() { //1实例化GLFW窗户 glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //创建窗口对象 GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "TestWindows", NULL, NULL); if (!window) { std::cout << "Failed to create Windows" << std::endl; //释放资源 glfwTerminate(); return -1; } //保留上下文 glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); //初始化GLAD if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } //开启深度测试、 glEnable(GL_DEPTH_TEST); //3.创建着色器 CShader NormalShader("openGL_Geometry_Shader.vs", "openGL_Geometry_Shader.fs", "openGL_Geometry_Shader.gs"); CShader ModelShader("openGL_Model.vs", "openGL_Model.fs"); //模型 CModel Model("F:/C++项目/LibsInclude/src/nanosuit/nanosuit.obj"); //循环渲染 while (!glfwWindowShouldClose(window)) { float currentTime = glfwGetTime(); deltaTime = currentTime - lastTime; lastTime = currentTime; //input processInput(window); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); //清除颜色缓冲和深度缓冲 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 model = glm::mat4(1.0f); glm::mat4 projection = glm::mat4(1.0f); glm::mat4 view = camera.GetViewMatrix(); projection = glm::perspective(glm::radians(camera.Zoom), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f); ModelShader.use(); ModelShader.setMat4("view", view); ModelShader.setMat4("projection", projection); ModelShader.setMat4("model", model); Model.Draw(ModelShader); //激活着色器程序 NormalShader.use(); NormalShader.setMat4("view", view); NormalShader.setMat4("projection", projection); NormalShader.setMat4("model", model); NormalShader.setFloat("time", glfwGetTime()); Model.Draw(NormalShader); //交换颜色缓冲 glfwSwapBuffers(window); //检查是否触发事件 glfwPollEvents(); } //删除程序对象 NormalShader.deleteProgram(); ModelShader.deleteProgram(); //释放资源 glfwTerminate(); return 0; } //回调函数,窗口改变时视口改变 void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } //输入控制 void processInput(GLFWwindow* window) { float moveSpeed = 0.5f * deltaTime; if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); } if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { cameraPos += cameraFront * moveSpeed; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { cameraPos -= cameraFront * moveSpeed; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp))* moveSpeed; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp))* moveSpeed; } } //鼠标回调 void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; lastX = xpos; lastY = ypos; camera.ProcessMouseMovement(xoffset, yoffset); } //定义光标回调函数 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset); } 

结果:

推荐:滨州SEO

猜你喜欢

转载自www.cnblogs.com/1994jinnan/p/12891480.html