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

程序图示


0005-Light-MVP-001


0005-Light-MVP-001

代码

#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
原创粉丝点击