光照基础之颜色

  1. 主要使用颜色叠加效果,最终输出颜色 = 物体颜色* 光照颜色
  2. 使用已有的VBO绘制光源立方体。
  1. 被光照影响的物体使用的Shader

    1. 顶点Shader没有变化,只有transform cpp #version 330 core layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0 uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); }

    2. 主要变化在片元Shader cpp #version 330 core out vec4 FragColor; uniform vec3 objectColor; uniform vec3 lightColor; void main() { // 使用乘法颜色叠加, alpha先固定为 1.0 FragColor = vec4(lightColor * objectColor, 1.0); }

    3. 传递颜色值 cpp objectShader.use(); objectShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f); objectShader.setVec3("lightColor", lightColor);

    4. 调用渲染指令,则会渲染出叠加颜色的物体。

  2. 渲染光源物体,(不是必须的,渲染出光源物体方便调试光源参数) > 作为普通物体的渲染,颜色、变换、等 > 位置注意要在视椎体

  3. 完整代码

        #include "glad/glad.h"
        #include "GLFW/glfw3.h"
    
        //图片库
        #define STB_IMAGE_IMPLEMENTATION
        #include "stb_image.h"
    
        //glm OpenGL Math库
        #include "glm/glm.hpp"
        #include "glm/gtc/matrix_transform.hpp"
        #include "glm/gtc/type_ptr.hpp"
    
        #include "shader.h"
        #include <iostream>
    
        using namespace std;
    
        const int wWidth = 800, wHeight = 600;
        const char* wName = "LearnOpenGL";
    
        glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
        glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
        glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
        float cameraSpeed = 0.05f; // adjust accordingly
        float deltaTime = 0.0f; // 当前帧与上一帧的时间差
        float lastFrame = 0.0f; // 上一帧的时间
        float lastX = 400, lastY = 300;
        float yaw = 0, pitch = 0;
        bool firstMouse = true;
        float fov = 45.0f;
    
        //立方体顶点
        float vertices[] = {
             -0.5f, -0.5f, -0.5f,
                 0.5f, -0.5f, -0.5f,
                 0.5f,  0.5f, -0.5f,
                 0.5f,  0.5f, -0.5f,
                -0.5f,  0.5f, -0.5f,
                -0.5f, -0.5f, -0.5f,
    
                -0.5f, -0.5f,  0.5f,
                 0.5f, -0.5f,  0.5f,
                 0.5f,  0.5f,  0.5f,
                 0.5f,  0.5f,  0.5f,
                -0.5f,  0.5f,  0.5f,
                -0.5f, -0.5f,  0.5f,
    
                -0.5f,  0.5f,  0.5f,
                -0.5f,  0.5f, -0.5f,
                -0.5f, -0.5f, -0.5f,
                -0.5f, -0.5f, -0.5f,
                -0.5f, -0.5f,  0.5f,
                -0.5f,  0.5f,  0.5f,
    
                 0.5f,  0.5f,  0.5f,
                 0.5f,  0.5f, -0.5f,
                 0.5f, -0.5f, -0.5f,
                 0.5f, -0.5f, -0.5f,
                 0.5f, -0.5f,  0.5f,
                 0.5f,  0.5f,  0.5f,
    
                -0.5f, -0.5f, -0.5f,
                 0.5f, -0.5f, -0.5f,
                 0.5f, -0.5f,  0.5f,
                 0.5f, -0.5f,  0.5f,
                -0.5f, -0.5f,  0.5f,
                -0.5f, -0.5f, -0.5f,
    
                -0.5f,  0.5f, -0.5f,
                 0.5f,  0.5f, -0.5f,
                 0.5f,  0.5f,  0.5f,
                 0.5f,  0.5f,  0.5f,
                -0.5f,  0.5f,  0.5f,
                -0.5f,  0.5f, -0.5f,
        };
    
        void framebuffer_size_callback(GLFWwindow* window, int width, int height)
        {
            glViewport(0, 0, width, height);
        }
    
        void processInput(GLFWwindow *window)
        {
            if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
                glfwSetWindowShouldClose(window, true);
    
            float cameraSpeed = 2.5f * deltaTime;
            if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
                cameraPos += cameraSpeed * cameraFront;
            if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
                cameraPos -= cameraSpeed * cameraFront;
            if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
                cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
            if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
                cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    
        }
    
        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;
    
            float sensitivity = 0.05;
            xoffset *= sensitivity;
            yoffset *= sensitivity;
    
            yaw += xoffset;
            pitch += yoffset;
    
            if (pitch > 89.0f)
                pitch = 89.0f;
            if (pitch < -89.0f)
                pitch = -89.0f;
    
            glm::vec3 front;
            front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
            front.y = sin(glm::radians(pitch));
            front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
            cameraFront = glm::normalize(front);
        }
    
        void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
        {
            if (fov >= 1.0f && fov <= 45.0f)
                fov -= yoffset;
            if (fov <= 1.0f)
                fov = 1.0f;
            if (fov >= 45.0f)
                fov = 45.0f;
        }
        int main()
        {
            //1. 初始化
            if (glfwInit() == GLFW_FALSE)
            {
                cout << "init glfw fail";
                return 1;
            }
    
            //2. 基本设置
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
        #if __APPLE__
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
        #endif
    
            //3. 创建窗口
            GLFWwindow *window = glfwCreateWindow(wWidth, wHeight, wName, nullptr, nullptr);
            if (window == nullptr)
            {
                cout << "Failed to create GLFW window";
                goto TERMINATE;
                //return 1;
            }
    
            //4. 当前主线程上下文窗口
            glfwMakeContextCurrent(window);
    
            //5. 使用glad管理OpenGL指针。
            if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
            {
                std::cout << "Failed to initialize GLAD" << std::endl;
                goto TERMINATE;
                //return 1;
            }
    
            //6. 设置视口
            glViewport(0, 0, wWidth, wHeight);
            //7. 设置resize回调,对应刷新视口
            glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
            glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            glfwSetCursorPosCallback(window, mouse_callback);
            glfwSetScrollCallback(window, scroll_callback);
    
            Shader objectShader("res/shaders/sample_vertex_light_color.shader", "res/shaders/sample_fragment_light_color.shader");
            Shader lightCubeShader("res/shaders/sample_vertex_light_color.shader", "res/shaders/sample_fragment_light.shader");
    
    
            unsigned int VBO, VAO, lightVAO;
            glGenVertexArrays(1, &VAO);
            glBindVertexArray(VAO);
    
            glGenBuffers(1, &VBO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
            //1. 指定顶点的顶点属性的结构,顶点 3个float,从0开始,整体每一组数据8个。
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
            glEnableVertexAttribArray(0);
    
            glGenVertexArrays(1, &lightVAO);
            glBindVertexArray(lightVAO);
    
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (void*)(0));
            glEnableVertexAttribArray(0);
    
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            glBindVertexArray(0);
    
            /*glm::vec3 cubePositions[] = {
              glm::vec3(0.0f,  0.0f,  0.0f),
              glm::vec3(2.0f,  5.0f, -15.0f),
              glm::vec3(-1.5f, -2.2f, -2.5f),
              glm::vec3(-3.8f, -2.0f, -12.3f),
              glm::vec3(2.4f, -0.4f, -3.5f),
              glm::vec3(-1.7f,  3.0f, -7.5f),
              glm::vec3(1.3f, -2.0f, -2.5f),
              glm::vec3(1.5f,  2.0f, -2.5f),
              glm::vec3(1.5f,  0.2f, -1.5f),
              glm::vec3(-1.3f,  1.0f, -1.5f)
            };*/
    
            glm::vec3 lightPos(1.2f, 1.0f, -2.0f);
            int rgbmax = 0xffffff;
            int rgbmin = 0;
            int rgb = rgbmax;
            bool sub = true;
            glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
            while (!glfwWindowShouldClose(window))
            {
                processInput(window);
    
                glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    
                glm::mat4 view = glm::mat4(1.0f);
                glm::mat4 projection = glm::mat4(1.0f);
                view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
                projection = glm::perspective(glm::radians(fov), (float)wWidth / (float)wHeight, 0.1f, 100.0f);
    
                glm::mat4 model(1.0f);
    
                objectShader.use();
                objectShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
    
                if (rgb >= rgbmax)
                {
                    sub = true;
                }
    
                if (rgb < rgbmin)
                {
                    sub = false;
                }
    
                if (sub)
                {
                    rgb -= 4;
                }
                else
                {
                    rgb += 4;
                }
                int ir = (rgb & 0xff0000) >> 16;
                int ig = (rgb & 0x00ff00) >> 8;
                int ib = (rgb & 0x0000ff);
    
                //std::cout << rgb<<"\t"<<ir<< "\t" << ig << "\t" << ib <<std::endl;
    
                lightColor.r = ir / 255.0f;
                lightColor.b = ib / 255.0f;
                lightColor.g = ig / 255.0f;
    
                objectShader.setVec3("lightColor", lightColor);
    
                objectShader.setMat4("projection", projection);
                objectShader.setMat4("view", view);
    
                model = glm::translate(model, glm::vec3(0, 0, 0));
                model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
                objectShader.setMat4("model", model);
    
                glBindVertexArray(VAO);
                glDrawArrays(GL_TRIANGLES, 0, 36);
    
                model = glm::mat4(1.0f);
                model = glm::translate(model, lightPos);
                model = glm::scale(model, glm::vec3(0.2f));
    
                lightCubeShader.use();
                lightCubeShader.setMat4("projection", projection);
                lightCubeShader.setMat4("view", view);
                lightCubeShader.setMat4("model", model);
    
                glBindVertexArray(lightVAO);
                glDrawArrays(GL_TRIANGLES, 0, 36);
    
                glfwSwapBuffers(window);
                glfwPollEvents();
            }
    
            glDeleteVertexArrays(1, &VAO);
            glDeleteBuffers(1, &VBO);
            //glDeleteBuffers(1, &EBO);
    
        TERMINATE:
            glfwTerminate();
            return 0;
        }

文章作者: Yonggang Long
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yonggang Long !
 上一篇
2022-08-10 Yonggang Long
下一篇 
2022-08-10 Yonggang Long
  目录