光照基础之颜色
- 主要使用颜色叠加效果,
最终输出颜色 = 物体颜色* 光照颜色- 使用已有的VBO绘制光源立方体。
被光照影响的物体使用的Shader
顶点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); }主要变化在片元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); }传递颜色值
cpp objectShader.use(); objectShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f); objectShader.setVec3("lightColor", lightColor);调用渲染指令,则会渲染出叠加颜色的物体。
渲染光源物体,(不是必须的,渲染出光源物体方便调试光源参数) > 作为普通物体的渲染,颜色、变换、等 > 位置注意要在
视椎体内完整代码
#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; }