OpenGL:光照、模型视图投影变换
2017-05-02 18:18
253 查看
OpenGL:光照、模型视图投影变换
OpenGL光照模型视图投影变换数学基础
程序
库配置
程序图示
代码
shaderwrapperh
vertex shadermvp_testvs
fragment shadermvp_testfrag
references
数学基础
矩阵与线性变换坐标系变换
深入探索透视投影变换
OpenGL Normal Vector Transformation
程序
太阳系,为简化内容,所以使用正方体代替球体,模拟太阳系中的太阳,地球和月亮。主要目的是展示OpenGL中用到的几个坐标系变换以及光照处理。库配置
Creating a windowGLM
程序图示
代码
#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 prototypes static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); static void init(); static void initBuffer(); // Window dimensions static 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 loop int 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 GLFW static 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 core layout (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 core in 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
相关文章推荐
- OpenGL--3D世界(视图变换,模型变换,投影变换,视口变换)
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(一)——模型变换和视图变换
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(二)——投影变换
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(完)——法线变换
- OpenGL 模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)
- OpenGL的视图变换、模型变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL模型视图变换、投影变换、视口变换
- opengl 关于 投影变换,模型视图变换,视口变换 和多视口 的综合例子
- OpenGl学习笔记3之模型变换、视图变换、投影变换、视口变换介绍
- OpenGL模型视图变换、投影变换、视口变换总结
- 5.OpenGL--3D世界(视图变换,模型变换,投影变换,视口变换)
- OpenGL模型视图变换、投影变换、视口变换(转载)
- OpenGL模型视图变换、投影变换、视口变换
- OpenGL中glMatrixMode()函数以及视图变换,模型变换,投影变换,视口变换的理解
- OpenGL--3D世界(视图变换,模型变换,投影变换,视口变换)
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(一)——模型变换和视图变换