Title: Color of OpenGL(10)
date: 2020-07-17 18:08
Category: graphics
tags: opengl
The colors of the OpenGL (10)
See 1. Colors for the project code
1. An overview of the
There are countless colors in the real world, and every object has its own color. We need to use finite values to simulate the infinite colors in the real world. Not all colors in the real world can be represented by numerical values, but we can still show a lot of colors through numerical values. Color is composed of digital Red, Green and Blue components, also known as RGB primary colors. You can combine any color with just these three values.
Get a Coral red color by defining a three-dimensional color vector:
glm::vec3 coral(1.0 f.0.5 f.0.31 f);
Copy the code
The color of an object seen in real life is not the color the object actually has, but the color it reflects. That is, the colors that cannot be absorbed by the object (rejected colors) are the colors that we perceive.
For example, if you shine a white light on a green toy, the blue toy will absorb all the subcolors of the white light except for green. The unabsorbed blue light is reflected back into our eyes, making the toy appear green.
In OpenGL, we create a light source. Given a white light source, when we multiply the color of the light source by the color value of the object, we get the color reflected by the object.
glm::vec3 lightColor(1.0 f.1.0 f.1.0 f);
glm::vec3 objectColor(0.0 f.1.0 f.0.0 f);
glm::vec3 result = lightColor * objectColor; / / = (0.0 f, f, 1.0 0.0 f);
Copy the code
You can see that the red and blue light is completely absorbed, but the green light is completely reflected off.
If the above example is too extreme, here’s an example of coral red:
glm::vec3 lightColor(0.0 f.1.0 f.0.0 f);
glm::vec3 objectColor(1.0 f.0.5 f.0.31 f);/ / coral red
glm::vec3 result = lightColor * objectColor;/ / = (0.0 f, f, 0.5 0.0 f);
Copy the code
With only a green light source and no red and blue components, the object still absorbs half of the green value in the light source and still reflects half of the green value. That is, if you shine a green light on a coral-red object, only the green component will be reflected and perceived, and the red and blue components will not be perceived, and the object will become a dark green object.
It can be seen that using different light colors can make objects appear different colors.
2. Create a lighting scene
First we need an object as the object to be illuminated (that is, the object to be illuminated by the light source) and an object to represent the position of the light source in the 3D scene.
Similarly, we need to fill a vertex shader object (VBO) to fill the vertex data of the object, and then draw the object, so, write the vertex shader code:
#version 330 core
layout (location = 0 )in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(a){
gl_Position = projection * view *model *vec4(aPos,1.0);
}
Copy the code
Create a cube that represents the light source, create a special VAO for it, and simply make some changes to its Model matrix. In the following sections, there will be frequent changes to the vertex data and property Pointers, so these changes may affect the light source (vertex position, etc.). So that’s why we created a VAO for it, so without further ado, let’s go;
unsigned int lightVAO;
glGenVertexArrays(1,&lightVAO);
glBindVertexArray(lightVAO);
// Just bind the VBO and you don't need to set the VBO data again. That is, don't use glBufferData because the light source uses the object's VBO data.
glBindBuffer(GL_ARRAY_BUFFER,VBO);
// Sets the vertex properties of the light source
glVertexAttribPointer(0.3,GL_FLOAT,GL_FLASE,3*sizeof(float), (void*)0);
// Activate the vertex property
glEnableVertexAttribArray(0);
Copy the code
With that done, you can define fragment shaders for shader operations;
#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main(a){
FragColor = vec4(lightColor * objectColor ,1.0);
}
Copy the code
As you can see from the fragment shader above, you need to accept the color of the object and the color of the light source from the Uniform variable. Post the code snippet as follows:
// Remember to use the shader before setting up uniFROM
lightShader.use();
lightShader.setVec3("objectColor".1.0 f.0.5 f.0.31 f);
lightShader.setVec3("lightColor".1.0 f.1.0 f.1.0 f);
Copy the code
Note that when you modify the vertex or fragment shader, the position or color of the light source will change, which is obviously not true, so we want the light source to remain bright white and not affected by other color changes.
The vertex shader is the same as the current vertex shader. The fragment shader for the light source is defined as a constant white color.
#version 330 core;
out vec4 FragColor;
void main(a){
FragColor =vec4(1.0); // All four components of the vector are 1.0
}
Copy the code
In order to highlight the lighting effect, a light cube is used to locate the exact position of the light source in the scene, so define the position of a light source in the scene and draw the light cube at the same position as the light source. Use the fragment shader defined above to keep it white all the time, not affected by the care in the scene (refer to the Feng lighting model in the basic Lighting section of OpenGL(9) for details);
Declare a global VEC3 variable to represent the position of the light source in the world space coordinates of the scene.
glm::vec3 ligthPosition(1.2 f.1.0 f.2.0 f);
Copy the code
The light source is shifted and scaled by transformation to form a point light source.
model = glm::mat4();
model = glm::translate(model,lightPos); // Convert local space coordinates to world space coordinates.
model = glm::scale(mode,glm::vec3(0.2 f));// The x,y, and z components are scaled to 0.2
Copy the code
The next step is to draw the light cube:
//....
// Draw the light cube
glBindVertexArray(lightVAO);
glDrawArrays(GL_TRIANGLES,0.36);
Copy the code
Ok, with the above operations, the following results can be obtained:
reference
LearnOpenGL