1, RGB tricolor
Think back to junior high school physics:
- Three primary colors: all colors in nature can be obtained by the combination of red, green and blue (RGB) color frequencies with different intensities. White includes all colors
- To see the color of an object is the color reflected by the object. In other words, it is the color that cannot be absorbed by the current object
- The reason why we can see the colorful world is that there is a light source (luminous object), otherwise it will be completely dark
- Combined with ② and ③, color from light source to our eyes is a process: light source emits light → shines on objects → objects reflect the color existing in all light sources, but can't be absorbed by them
How the computer represents color (it should be a very basic thing):
- RGBA: RGB represents 3 primary colors, generally within the range of (0, 255). The larger the corresponding color is, the darker the color is. A represents transparency, which can be converted into the corresponding floating-point number. For example, 0.5 is equal to 128 (HEX format: ාාFFB6C1FF → corresponding RGBA format: 255182193, 255)
- It can be seen from ① that the number of colors that the computer can display is actually limited, with a total of (256 * 256 * 256) different colors, which is also called 8-bit sampling. Now part of it supports 10 bit sampling, in this case, it can display a total of (1024 * 1024 * 1024) different colors
2, Lighting scene
Recollection OpenGL foundation 5: first square This chapter
In this chapter, I haven't touched the texture yet. In terms of color, I just gave him a color at will
After that, texture is used, which simply removes the attribute of color
Now reconsider the attribute of color. Instead of simply assigning colors to objects, start to simulate light directly! In order to give an object a real "color", before that, first use the previous knowledge to generate a scene like this:
The white cube is the light source, and the coral red cube is the object
The shader code of white light source is as follows( LightFShader.txt And LightVShader):
#version 330 core out vec4 color; void main() { color = vec4(1.0f); } ///////////////////////////////////////////////////// #version 330 core layout (location = 0) in vec3 position; uniform mat4 model; //Model matrix uniform mat4 view; //Observation matrix uniform mat4 projection; //Projection matrix void main() { gl_Position = projection * view * model * vec4(position, 1.0); }
The shaders for coral red objects are as follows( ObjFShader.txt And ObjVShader):
#version 330 core out vec4 color; uniform vec3 objectColor; uniform vec3 lightColor; in vec2 texIn; uniform sampler2D texOutA; void main() { color = vec4(lightColor * objectColor, 1.0f); } ///////////////////////////////////////////////////// #version 330 core layout (location = 0) in vec3 position; layout (location = 1) in vec2 texture; out vec2 texIn; uniform mat4 model; //Model matrix uniform mat4 view; //Observation matrix uniform mat4 projection; //Projection matrix void main() { gl_Position = projection * view * model * vec4(position, 1.0); //texIn = vec2(texture.x, 1.0f - texture.y); / / temporarily mask texture }
For vertex shaders of objects, we define two uniform variables, which represent object color and illumination color respectively
When we multiply the color of the light source by the color of the object, what we get is the color of the light source reflected by the object (that is, the color we perceive)
Next is the main code (Camera.h and Shader.h remain unchanged, which can be found in the previous chapter):
#include<iostream> #include<opengl/glew.h> #define GLEW_STATIC #include<GLFW/glfw3.h> #include"Camera.h" #include<glm/glm.hpp> #include<glm/gtc/matrix_transform.hpp> #include<glm/gtc/type_ptr.hpp> #include"Shader.h" #include<opengl/freeglut.h> #include<SOIL.h> bool keys[1024]; Camera camera; GLfloat lastX, lastY; bool firstMouse = true; void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); void mouse_callback(GLFWwindow* window, double xpos, double ypos); void cameraMove(); glm::vec3 lightPos(1.2f, 1.0f, 2.0f); const GLuint WIDTH = 800, HEIGHT = 600; int main() { glfwInit(); 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); GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glewExperimental = GL_TRUE; glewInit(); int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); Shader shaderObj("ObjVShader.txt", "ObjFShader.txt"); Shader shaderLight("LightVShader.txt", "LightFShader.txt"); GLfloat vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; GLuint VBO, VAO, texture; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenTextures(1, &texture); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindTexture(GL_TEXTURE_2D, texture); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); /*glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); int picWidth, picHeight; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); unsigned char* image = SOIL_load_image("Texture/wood.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0);*/ GLuint lightVAO; glGenVertexArrays(1, &lightVAO); glBindVertexArray(lightVAO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); //VBO data has been bound and we use the previous vertex data, so there is no need to manage VBO glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glEnable(GL_DEPTH_TEST); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); cameraMove(); //glBindTexture(GL_TEXTURE_2D, texture); shaderObj.Use(); GLint objectColorLoc = glGetUniformLocation(shaderObj.Program, "objectColor"); GLint lightColorLoc = glGetUniformLocation(shaderObj.Program, "lightColor"); glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f); //Object reflection color glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f); //Lights: white by default glm::mat4 model = glm::mat4(1.0f); glm::mat4 view = glm::mat4(1.0f); glm::mat4 projection = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(57.0f), glm::vec3(-0.5f, 1.0f, 0.0f)); view = camera.GetViewMatrix(); projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f); GLint modelLoc = glGetUniformLocation(shaderObj.Program, "model"); GLint viewLoc = glGetUniformLocation(shaderObj.Program, "view"); GLint projLoc = glGetUniformLocation(shaderObj.Program, "projection"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 36); //glBindTexture(GL_TEXTURE_2D, 0); shaderLight.Use(); model = glm::translate(glm::mat4(1.0f), lightPos); model = glm::scale(model, glm::vec3(0.2f)); modelLoc = glGetUniformLocation(shaderLight.Program, "model"); viewLoc = glGetUniformLocation(shaderLight.Program, "view"); projLoc = glGetUniformLocation(shaderLight.Program, "projection"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glBindVertexArray(lightVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return 0; } GLfloat deltaTime = 0.0f; GLfloat lastFrame = 0.0f; void cameraMove() { GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; GLfloat cameraSpeed = 1.0f * deltaTime; if (keys[GLFW_KEY_W]) camera.ProcessKeyboard(Camera_Movement(FORWARD), deltaTime); if (keys[GLFW_KEY_S]) camera.ProcessKeyboard(Camera_Movement(BACKWARD), deltaTime); if (keys[GLFW_KEY_A]) camera.ProcessKeyboard(Camera_Movement(LEFT), deltaTime); if (keys[GLFW_KEY_D]) camera.ProcessKeyboard(Camera_Movement(RIGHT), deltaTime); } 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); if (action == GLFW_PRESS) //If the current press operation keys[key] = true; else if (action == GLFW_RELEASE) //Release keyboard keys[key] = false; } void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset); } void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } GLfloat xoffset = xpos - lastX; GLfloat yoffset = lastY - ypos; lastX = xpos; lastY = ypos; GLfloat sensitivity = 0.05; xoffset *= sensitivity; yoffset *= sensitivity; camera.ProcessMouseMovement(xoffset, yoffset); }