OpenGL:光照、模型视图投影变换
来源:互联网 发布:linux kernel delay 编辑:程序博客网 时间:2024/04/29 19:19
OpenGL:光照、模型视图投影变换
- OpenGL光照模型视图投影变换
- 数学基础
- 程序
- 库配置
- 程序图示
- 代码
- shaderwrapperh
- vertex shadermvp_testvs
- fragment shadermvp_testfrag
- references
数学基础
矩阵与线性变换
坐标系变换
深入探索透视投影变换
OpenGL Normal Vector Transformation
程序
太阳系,为简化内容,所以使用正方体代替球体,模拟太阳系中的太阳,地球和月亮。主要目的是展示OpenGL中用到的几个坐标系变换以及光照处理。
库配置
Creating a window
GLM
程序图示
代码
#include <iostream>#include <cmath>// GLEW#define GLEW_STATIC#include <GL/glew.h>// GLFW#include <GLFW/glfw3.h>// GLM Mathematics#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <glm/gtc/type_ptr.hpp>// Other includes#include "shaderwrapper.h"// Function prototypesstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);static void init();static void initBuffer();// Window dimensionsstatic const GLuint WIDTH = 800, HEIGHT = 600;static GLFWwindow* window;static GLuint VBO, VAO;// The MAIN function, from here we start the application and run the game loopint main(){ init(); initBuffer(); //light position in world space glm::vec3 lightPos(8.0f,8.0f,8.0f); //eye position in world space glm::vec3 eyePos(-12.0f, 12.0f, 12.0f); //local positions glm::vec3 cubePositions[] = { glm::vec3(8.0f,0.0f,0.0f), glm::vec3(3.0f,0.0f,0.0f) }; //sun GLfloat Sun_angle = 0.0f; GLfloat Sun_angle_step = 1.0f; glm::vec3 Sun_color(1.0f,0.0f,0.0f); //earth GLfloat Earth_self_angle = 0.0f; GLfloat Earth_angle_step = 1.0f; GLfloat Earth_sun_angle = 0.0f; GLfloat Earth_sun_step = 2.0f; glm::vec3 Earth_color(0.0f, 1.0f, 0.0f); //moon GLfloat Moon_self_angle = 0.0f; GLfloat Moon_angle_step = 2.0f; GLfloat Moon_earth_angle = 0.0f; GLfloat Moon_earth_step = 3.0f; glm::vec3 Moon_color(1.0f, 1.0f, 1.0f); // Build and compile our shader program Shader ourShader("shaders/mvp_test.vs", "shaders/mvp_test.frag"); //get locations of uniform variables GLint viewLoc = glGetUniformLocation(ourShader.Program, "view"); GLint projLoc = glGetUniformLocation(ourShader.Program, "projection"); GLint lightPosLoc = glGetUniformLocation(ourShader.Program, "lightPos"); GLint colorLoc = glGetUniformLocation(ourShader.Program, "objectColor"); GLint viewPosLoc = glGetUniformLocation(ourShader.Program, "viewPos"); // Camera/View transformation glm::mat4 view; view = glm::lookAt(eyePos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); // Projection glm::mat4 projection; projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f); // Activate shader ourShader.Use(); // Pass the matrices to the shader glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z); glUniform3fv(viewPosLoc, 1, glm::value_ptr(eyePos)); // loop GLfloat startTime = glfwGetTime(); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // Render // Clear the color buffer and depth buffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Calculate delta time of current frame GLfloat deltaTime = glfwGetTime() - startTime; //sun Sun_angle = Sun_angle_step * deltaTime; //earth Earth_self_angle = Earth_angle_step * deltaTime; Earth_sun_angle = Earth_sun_step*deltaTime; //moon Moon_self_angle = Moon_angle_step * deltaTime; Moon_earth_angle = Moon_earth_step * deltaTime; // Get the uniform locations GLint modelLoc = glGetUniformLocation(ourShader.Program, "model"); GLint normalTransformLoc = glGetUniformLocation(ourShader.Program, "normalTransform"); glBindVertexArray(VAO); //### sun ### glm::mat4 sun_model; sun_model = glm::scale(sun_model,glm::vec3(1.6f,1.6f,1.6f)); //放大坐标系 sun_model = glm::rotate(sun_model, Sun_angle, glm::vec3(0.0f, 1.0f, 0.0f)); //绕坐标系y轴旋转 glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(sun_model)); //normal transform glm::mat4 sun_normalTransform; sun_normalTransform = glm::inverse(sun_model); sun_normalTransform = glm::transpose(sun_normalTransform); glUniformMatrix4fv(normalTransformLoc, 1, GL_FALSE, glm::value_ptr(sun_normalTransform)); glUniform3fv(colorLoc, 1, glm::value_ptr(Sun_color)); glDrawArrays(GL_TRIANGLES, 0, 36); //### earth ### glm::mat4 earth_model; //绕y轴旋转坐标系W得到新坐标系W1 earth_model = glm::rotate(earth_model, Earth_sun_angle, glm::vec3(0.0f, 1.0f, 0.0f)); //平移坐标系W1得到新坐标系W2 earth_model = glm::translate(earth_model, cubePositions[0]); //绕y轴旋转坐标系W2得到新坐标系W3 earth_model = glm::rotate(earth_model, Earth_self_angle, glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(earth_model)); //normal transform glm::mat4 earth_normalTransform; earth_normalTransform = glm::inverse(earth_model); earth_normalTransform = glm::transpose(earth_normalTransform); glUniformMatrix4fv(normalTransformLoc, 1, GL_FALSE, glm::value_ptr(earth_normalTransform)); glUniform3fv(colorLoc, 1, glm::value_ptr(Earth_color)); glDrawArrays(GL_TRIANGLES, 0, 36); //### moon ### glm::mat4 moon_model; //start from earth's coordinate moon_model = earth_model; moon_model = glm::scale(moon_model, glm::vec3(0.5f, 0.5f, 0.5f)); moon_model = glm::rotate(moon_model, Moon_earth_angle, glm::vec3(0.0f, 1.0f, 0.0f)); moon_model = glm::translate(moon_model, cubePositions[1]); moon_model = glm::rotate(moon_model, Moon_self_angle, glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(moon_model)); //normal transform glm::mat4 moon_normalTransform; moon_normalTransform = glm::inverse(moon_model); moon_normalTransform = glm::transpose(moon_normalTransform); glUniformMatrix4fv(normalTransformLoc, 1, GL_FALSE, glm::value_ptr(moon_normalTransform)); glUniform3fv(colorLoc, 1, glm::value_ptr(Moon_color)); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); // Swap the screen buffers glfwSwapBuffers(window); } // Properly de-allocate all resources once they've outlived their purpose glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // Terminate GLFW, clearing any resources allocated by GLFW. glfwTerminate(); return 0;}// Is called whenever a key is pressed/released via GLFWstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode){ if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE);}static void init(){ // Init GLFW glfwInit(); // Set all the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Create a GLFWwindow object that we can use for GLFW's functions window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions glewExperimental = GL_TRUE; // Initialize GLEW to setup the OpenGL Function pointers glewInit(); // Define the viewport dimensions glViewport(0, 0, WIDTH, HEIGHT); glEnable(GL_DEPTH_TEST);}static void initBuffer(){ // Set up vertex data (and buffer(s)) and attribute pointers GLfloat vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // Normal attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Unbind VAO}
shaderwrapper.h:
#ifndef SHADER_H#define SHADER_H#include <string>#include <fstream>#include <sstream>#include <iostream>#include <GL/glew.h>class Shader{public: GLuint Program; // Constructor generates the shader on the fly Shader(const GLchar* vertexPath, const GLchar* fragmentPath) { // 1. Retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::ifstream vShaderFile; std::ifstream fShaderFile; // ensures ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::badbit); try { // Open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // Read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // Convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } const GLchar* vShaderCode = vertexCode.c_str(); const GLchar * fShaderCode = fragmentCode.c_str(); // 2. Compile shaders GLuint vertex, fragment; GLint success; GLchar infoLog[512]; // Vertex Shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); // Print compile errors if any glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } // Fragment Shader fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); // Print compile errors if any glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } // Shader Program this->Program = glCreateProgram(); glAttachShader(this->Program, vertex); glAttachShader(this->Program, fragment); glLinkProgram(this->Program); // Print linking errors if any glGetProgramiv(this->Program, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(this->Program, 512, NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } // Delete the shaders as they're linked into our program now and no longer necessery glDeleteShader(vertex); glDeleteShader(fragment); } // Uses the current shader void Use() { glUseProgram(this->Program); }};#endif
vertex shader(mvp_test.vs):
#version 330 corelayout (location = 0) in vec3 position;layout (location = 1) in vec3 normal;out vec3 Normal;out vec3 FragPos;uniform mat4 model;uniform mat4 view;uniform mat4 projection;uniform mat4 normalTransform;void main(){ gl_Position = projection * view * model * vec4(position, 1.0f); Normal = vec3(normalTransform*vec4(normal,1.0f)); FragPos = vec3(model * vec4(position, 1.0f));}
fragment shader(mvp_test.frag):
#version 330 corein vec3 Normal; in vec3 FragPos; out vec4 color;uniform vec3 lightPos;uniform vec3 viewPos;uniform vec3 objectColor;void main(){ vec3 lightColor = vec3(1.0f,1.0f,1.0f); vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); // ambient component float ambientStrength = 0.28f; vec3 ambient = ambientStrength * lightColor; // diffuse component float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor; // specular component float specularStrength = 0.5f; int shininess = 256; vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess); vec3 specular = specularStrength * spec * lightColor; // together vec3 result = (ambient + diffuse + specular) * objectColor; color = vec4(result, 1.0f);}
references:
Basic Lighting
深入探索透视投影变换
OpenGL Projection Matrix
OpenGL Normal Vector Transformation
0 0
- OpenGL:光照、模型视图投影变换
- OpenGL模型视图变换,投影变换及视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL 模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换总结
- OpenGL 视图变换和投影变换
- OpenGL光照模型
- OpenGL-光照模型
- OpenGL-光照模型
- opengl光照模型
- OpenGL.光照模型
- opengl光照模型
- opengl 关于 投影变换,模型视图变换,视口变换 和多视口 的综合例子
- OpenGL--3D世界(视图变换,模型变换,投影变换,视口变换)
- HttpClient 之get请求
- OkHttp3源码分析(三)
- 数据类型转换
- Linphone-Manager封装类(三)
- IReport问题的整理
- OpenGL:光照、模型视图投影变换
- iOS9-Contacts本地电话本框架
- 【C语言训练】角谷猜想
- python-9-如何对迭代器做切片操作?
- LeetCode 227. Basic Calculator II
- 设计模式之中介者模式
- c# 底层算法 冒泡排序 选择排序
- 一份代码的运行顺序分析
- 字符串字符分割代码