OpenGL_09, Colors

김경주·2024년 12월 13일
0

OpenGL

목록 보기
10/10

실제로 색은 각 사물이 지니고 있는 고유의 색상과 어느 색상값을 가질 수 있다. 디지털 세계에서는 색상은 무한한 실제 색을 제한된 디지털 값으로 매핑해야하므로 모든 색은 디지털로 표현할 수 없다. 색상은 일반적으로 약어 RGB에서 Red, Green, Blue 원소를 사용하여 나타낸다. 이 세가지 값의 조합을 사용하여 0-1 사이의 범위안에서 어느 색을 표현할 수 있다.

glm::vec3 coral(1.0f, 0.5f, 0.31f);

우리가 보는 사물의 색은 실제 그 사물이 가진 색이 아니다. 사물로부터 반사된 색이다. 사물로부터 흡수된(absorbed)게 아니라 우리가 인지하고 있는 것. 한 예시로 태양의 빛은 다양한 색으로 결합된 하얀 빛으로 인지된다.

이 하얀 빛을 파란 물체에 비추면 파란색을 제외한 모든 하얀색을 구성하는 부수적인 색들을 흡수한다. 이 물체는 파란색을 흡수하지 못하기때문에 반사시킨다. 이 반사된 빛이 눈에 들어오고, 물체가 파란색을 가진 것처럼 보이게 한다. 위 이미지는 산호색의 물체에 관한 것.

하얀 태양빛은 모든 색의 집합체이고 물체는 그 색상들의 큰 부분을 흡수. 물체의 색을 나타내는 색상들을 비추며 그 색상들의 조합이 우리가 인지하는 것.

OpenGL에서 광원을 정의할 때 이 빛을 하나의 색으로 준다. 이 빛의 색상값과 사물의 색상값을 곱하면 결과 색상값은 사물의 반사된 색상이다.

glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (1.0f, 0.5f, 0.31f);

물체의 색이 하얀 빛의 큰 부분을 흡수하지만 물체가 가진 색을 토대로 몇가지 빨강, 초록, 파랑 값들을 반사한다. 이는 실제로 색상이 어떻게 작용하는지 표현. 물체가 빛으로부터 반사되는 각각의 색상의 원소의 양으로 물체의 색을 정의. 만약 초록빛을 사용하면?

glm::vec3 lightColor(0.0f, 1.0f, 0.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (0.0f, 0.5f, 0.0f);

물체는 흡수하거나 또는/그리고 반사할 수 있는 빨강과 파랑빛을 가지지 않는다. 이 물체는 또한 초록빛 값의 반을 흡수할뿐만아니라 반사한다. 이 물체의 색은 어두운 초록색이라 인지될 것. 초록빛을 사용하면 초록색의 원소만 반사되어 인식될 수 있다.

glm::vec3 lightColor(0.33f, 0.42f, 0.18f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (0.33f, 0.21f, 0.06f);

위 예시는 dark olive-green 빛이다.

A lighting scene

먼저 빛을 발하는 물체가 필요하고 이전 챕터의 큐브를 생성해 사용할 것. 빛 자원이 3D 배경에서 어디에 위치하는지 나타낼 빛 오브젝트 필요. 간단하게 표현하기 위해서 큐브를 사용하여 광원을 나타낸다.

vertex buffer objects 채우고 vertex attribute pointer들을 세팅한다.

첫번째로 큐브 컨테이너를 그릴 vertex shader가 필요. 컨테이너의 vertex position은 똑같으므로 코드는 그대로다.

#version 330 core
layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
}

vertex 데이터와 vertex attribute pointer 업데이트

unsigned int lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
// we only need to bind to the VBO, the container’s VBO’s data
// already contains the data.
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// set the vertex attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

광원과 컨테이너를 fragment shader 정의
#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{
	FragColor = vec4(lightColor * objectColor, 1.0);
}

Fragment shader는 컨테이너의 색과 광원의 색을 union변수로 받을 수 있다. 여기서 물체에 반사된 색과 광원의 색을 곱한다. 광원의 색과 물체의 색을 설정

lightingShader.use();
lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);

다음 챕터에서 lighting shaders를 업데이트 시작할 때 광원인 물체도 영향을 받을 것인데 이는 원치 않는 결과이다. 광원의 물체의 색이 빛을 계산하는 것으로부터 영향을 받지 않게 다른 것과 다르게 그대로 유지. 광원이 다른 색에 의해 영향을 받지 않고 상수 밝기의 색을 가지게 하게 한다.

위를 수행하기 위해서 다른 shader를 추가한다. 이는 광원을 그리고 lighting shader의 변화에 안전함을 위함이다.

광원의 fragment shader는 아래와 같이 생성

#version 330 core

out vec4 FragColor;

void main()
{
	FragColor = vec4(1.0); // set all 4 vector values to 1.0
}

light 쉐이더가 점더 실제적인 결과를 얻게 업데이트할 동안 광원은 광원 쉐이더의 정의에 따라 렌더링되고 그려지게 한다.

광원의 주 목적은 어디서 빛이 오는지 보여주는 것. 보통 광원의 위치를 scene의 어느 지점에 두는데 시각적 의미를 두지 않는다. scene의 빛의 상태에 상관없이 항상 하얀색으로 유지되게 광원 쉐이더에 정의된 컨테이너형태로 나타낸다.

world 공간 좌표에서의 광원의 위치를 전연벽수 vec3로 나타낸다.

glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

광원을 나타내는 물체를 광원의 지점으로 이동시키고 크기 조정을 하기 위해서 아래와 같이 코드 작성

model = glm::mat4(1.0f);
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f));

렌더링 하는 코드에서 광원의 물체에 관한 코드는 아래와 같이 작성할 수 있다.

lightCubeShader.use();
// set the model, view and projection matrix uniforms
[...]
// draw the light cube object
glBindVertexArray(lightCubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);

profile
Hello everyone

0개의 댓글