# OpenGL foundation 17: color

Keywords: Attribute

### 1, RGB tricolor

Think back to junior high school physics:

1. 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
2. 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
3. The reason why we can see the colorful world is that there is a light source (luminous object), otherwise it will be completely dark
4. 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):

1. 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)
2. 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

``````#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);
}``````

``````#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<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);

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);
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);
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);
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);
model = glm::translate(glm::mat4(1.0f), lightPos);
model = glm::scale(model, glm::vec3(0.2f));
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);
}``````

Posted by Spreegem on Sat, 06 Jun 2020 22:14:39 -0700