이제 만든 모델링의 쉐이더를 조정해서 여러 표현을 할 수 있도록 만들 생각이였다.
그런데 기본적으로.. 빛을 컨트롤 할 수 있어야 쉐이더가 유의미할것이다.
그래서 Light를 생성하고 조작할 수 있는 기능을 만들었다.
(이전까지는 빛이 특정위치에 하드코딩 되어있었다.)
텍스트박스 기능 추가
이번 글의 주제와 직접적인 연관이 있는 것은 아니지만
textbox에 새로운 기능을 추가했다!
원래는 키보드 입력으로만 텍스트의 내용을 조정할 수 있었는데
이젠 드래그로도 변경할 수 있다.
LightLayer
class LightLayer : public Layer
{
public:
LightLayer() {};
LightLayer(std::string name, glm::vec3 lightColor, glm::vec3 pos);
void SetPosition(glm::vec3 pos);
void SetRotation(glm::vec3 rot);
void SetScale(glm::vec3 scale);
void SetColor(glm::vec3 color);
void SetIndex(unsigned int i);
void Draw();
private:
glm::vec3 mLightColor;
unsigned int mLayerIndex;
};
LightLayer는 이름에서 알 수 있듯이
빛의 정보를 가지고 있는 Layer다.
일단 쉐이더를 제일 기본적인 쉐이더인 blinn-phong 으로 구현해놓았기에
현재는 위치와 색상 정보만 가지고있도록 구성했다.
LightLayer는 만들었는데..
그런데..
생각을 해보니
빛이라는 것은 전역적인 것이라서
모든 쉐이더가 빛 정보를 알고 있어야 할 것이다.
그래서 구현을 어떻게 할지 고민했는데,
glsl의 uniform을 전역적으로 쓸 수 있게 해주는
uniform buffer object라는 것이 있다는 것을 알았다.
https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
uniform buffer object는 실제로 쉐이더들이 공유하는 행렬이나 빛과 같은 데이터에 많이 쓰이는 것 같았다.
이번에도 learnOpenGL 따라서 만들었다.
struct BlinnPhongLight
{
vec3 lightColor;
vec3 lightPos;
};
layout (std140) uniform Lights
{
BlinnPhongLight lights[32];
};
glsl에 uniform block을 선언해주고..
glGenBuffers(1, &lightsUBO);
glBindBuffer(GL_UNIFORM_BUFFER, lightsUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4 * 2 * 32, NULL, GL_STATIC_DRAW);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, lightsUBO, 0, sizeof(float) * 4 * 2 * 32);
VBO, VAO 생성하는 것처럼 glGenBuffers로 생성해주고
필요한만큼 메모리를 할당해준다.
여기서...
vec3는 float가 3개로 이루어진 자료구조니깐
4(float 사이즈) * 3 이 아닌가 싶은데
std140의 규칙이 있어서
4*3 + 4(offset) 으로 이루어진다.
mUniformBlockIndex = glGetUniformBlockIndex(mShader.ID, "Lights");
glUniformBlockBinding(mShader.ID, mUniformBlockIndex, 0);
그리고 uniform block을 사용할 쉐이더를 바인딩한다.
이렇게 하면 uniform block을 사용할 준비 끝이다.
Collection
void Collection::Rendering(Layer *layer)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (layer->GetVisible() && layer->layerType == eLayerType::SHAPE)
{
static_cast<ShapeLayer *>(layer)->Draw();
}
if (layer->GetVisible() && layer->layerType == eLayerType::LIGHT)
{
glBindBuffer(GL_UNIFORM_BUFFER, lightsUBO);
static_cast<LightLayer *>(layer)->Draw();
}
if (layer->children.size() == 0)
return;
for (Layer *child : mRootLayer->children)
{
Rendering(child);
}
}
Collection의 Rendering()도 lightlayer의 Draw()를 호출하도록 수정했다.
lightLayer의 Draw()는...
void LightLayer::Draw()
{
unsigned int uniformOffset = mLayerIndex * LIGHT_SIZE;
glBufferSubData(GL_UNIFORM_BUFFER, uniformOffset + 16, sizeof(float) * 3, glm::value_ptr(GetPosition()));
glBufferSubData(GL_UNIFORM_BUFFER, uniformOffset, sizeof(float) * 3, glm::value_ptr(mLightColor));
}
uniform block의 내용물을 바꿔준다.
실행 결과
light도 상단에 버튼을 추가하여 빛을 추가할 수 있게 했다!
(당연히) ShapeLayer처럼 빛을 이동시키거나 빛의 색을 변경할 수도 있다.
빛은 (당연히) 중첩이 되므로 빛을 조정하여 여러 색을 연출할 수도 있다.
위에서도 언급했듯이 지금은 blinn-phong으로 쉐이더를 구현했고..
아마 다음에는 pointlight나 spotlight 구현하지 않을까?
이게 아니더라도 최소한 shininess나.. meterial 조절할 수 있도록 만들것 같다.
'컴퓨터 그래픽스 > OpenGL' 카테고리의 다른 글
#11 Tinylender 개발일지 : color 기능 추가 (1) | 2024.09.05 |
---|---|
#10 Tinylender 개발일지 : 곡선으로 메시만들기 (1) | 2024.09.05 |
#9 Tinylender 개발일지 : TextBox 개발 및 인스펙터 (3) | 2024.07.28 |
#8 Tinylender 개발일지 : 레이어 개발(1) (0) | 2024.07.25 |
#7 tinylender 개발일지 : extrude 기능 개발 (5) | 2024.05.31 |