목록Season 1/OpenGL (26)
Graphics Programming
디퍼드 셰이딩을 구현하려고 오랜만에 프로젝트를 열었다. 그런데 렌더러 설계가 내가 왜 이렇게 했는지 도저히 이해할 수 없는 상태다. 왜 재질이 셰이더 프로그램을 생성하고, 두 물체가 같은 재질을 공유하는데 속성 설정이 다르면 매 프레임마다 셰이더를 다시 컴파일하는 거지... 그래서 디퍼드 셰이딩은 건드리지도 못하고 기존의 포워드 셰이딩 코드를 장기간 리팩토링하고 있다. 리팩토링하면 설계만 바뀌어야지 동작이 깨지면 안되는데 깨져버렸다. 방향광에 의한 섀도우 매핑을 리팩토링하다 렌더러가 그만... 원본 코드와 대조하며 하루를 꼬박 보냈지만 소용이 없었다. GLintercept를 써가며 모든 오류 메시지를 해결했지만 섀도우 매핑은 살아나지 않았다. 섀도우 매핑을 구현하려면 렌더 패스가 2단계 필요하다. 1. ..
큐브맵은 스카이박스와 환경 매핑(Environmental mapping)을 구현할 때 유용한 기능이다. 큐브맵을 샘플링할 때는 큐브맵 샘플러와 방향 벡터가 필요하다. #version 430 core layout (binding = 0) uniform samplerCube texCube; in VS_OUT { vec3 tc; } fs_in; layout (location = 0) out vec4 color; void main() { color = texture(texCube, fs_in.tc);} 원점에서 방향 벡터를 따라갈 때 도달하는 텍셀을 샘플링하는데, 이 벡터가 문제다. 모델의 기하 정보를 기술할 때 OpenGL은 오른손 좌표계를 사용한다. 즉 화면 오른쪽이 +x축, 위쪽이 +y축일 때 화면에서 나..
텍스처를 생성하면 크기와 포맷을 지정해야 한다. 그런데 두 가지 방법이 있다. // 텍스처 생성GLuint tex;glGenBuffers(1, &tex); // 바인딩glBindTexture(GL_TEXTURE_2D, tex); // 방법 1. glTexImage2D() 또는 glTexSubImage2D()// 타겟, 밉맵 레벨, 텍스처 포맷, 가로, 세로, 보더, 집어넣을 데이터의 포맷, 타입, 실제 데이터glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // 방법 2. glTexStorage2D()// 타겟, 밉맵 레벨, 텍스처 포맷, 가로, 세로glTexStorage2D(GL_TEXTURE_2D..
만들고 있는 렌더링 엔진에서 Wavefront OBJ 모델을 불러오기 위해 tinyobjloader를 사용한다. 오랫만에 확인해보니 tinyobjloader의 버전이 올라가서 교체했는데 컴파일이 안 된다. 소스 코드를 열어보니 명세가 바뀌어서 그런 거였다. 내 엔진의 코드도 고쳐야 해서 귀찮은 상황이 되었는데, 명세를 찬찬히 보니 이전에 못다 구현한 기능이 생각났다. tinyobjloader는 하나의 3D 개체를 shape로 표현한다. shape는 position buffer, normal buffer, texcoord buffer, index buffer 등을 포함한다. 그리고 shape는 face의 모음인데 face마다 다른 재질을 가질 수도 있다. 예를 들어 축구공이라는 개체는 하나지만 이 공의 흰..
http://codeonwort.tistory.com/235 평면 텍스처에 입체감을 주기 위해 가장 흔하게 사용하는 기법이며 튜토리얼도 수없이 많으나... 구현하는 것은 엄청 힘들었다. 셰이딩을 위해서는 법선, 탄젠트, 바이탄젠트, 광원 위치, 시선 벡터, 모델뷰 행렬 등 많은 매개변수가 필요한데, 각자 다른 좌표계에서 정의된 값들이고 이것들을 모두 탄젠트 공간으로 변환해서 계산하는 과정에서 엄청난 혼란을 겪었기 때문이다. 그렇다고 수많은 픽셀 중 하나의 값을 찍어볼 수도 없어서, C++ 코드로 똑같은 계산을 작성해서 콘솔에 찍어보며 디버깅을 했다. 철저히 검증했는데도 GPU와 CPU에서의 결과가 다르다면, 매개변수를 전달하는 과정에서 오류가 난 것이다. 실제로 프래그먼트 셰이더의 mat4 유니폼에 gl..
방향광(directional light)을 이용해 기초적인 그림자 매핑을 구현하고 나니 3년도 전에 본 그림이 생각났다. http://9gag.com/gag/1744243/lamp-level-asian 기본적인 그림자 매핑은 한 방향으로만 그림자를 그리기에 전방향으로 그릴 수가 없다. 점광원의 위치에서 여섯 방향으로 깊이 맵을 그리고 각각의 맵을 큐브맵의 여섯 면에 대응하면 되지 않을까 싶었고, 검색해보니 실제로 큐브맵을 이용해 전방향 그림자 매핑을 구현하는 것이 보편적이었다. 그림자 매핑을 여섯 번 하면 되는 아주 쉬운 작업이라고 생각하였으나 구현하는 과정에서 멘탈이 수없이 깨졌다. - 큐브맵 텍스처의 샘플링. 큐브맵 텍스처의 각 면(face)에 RGBA 텍스처가 아니라 깊이 텍스처를 붙이는 것이 가능..
※ 예제 코드들은 OpenGL Super Bible에서 가져온 것입니다. - 컴퓨트 셰이더 스테이지는 별개의 파이프라인. OpenGL의 다른 셰이더들과 단절되어 있다 - 고정된 입출력이 없다 - 프로그래밍 관점에서는 다른 셰이더들과 같다 - GLSL로 작성, 셰이더 개체로 표현, 프로그램 개체에 링크됨 - 컴퓨트 셰이더는 다른 셰이더들과 섞일 수 없다 - 이미 정점, 단편 셰이더가 있는 프로그램에 컴퓨트 셰이더를 붙일 수 없음 (링크 실패) - 링크된 프로그램은 컴퓨트 셰이더만 포함하거나 그래픽스 셰이더들(정점, 테셀레이션, 기하, 단편)만을 포함한다 // 아무것도 안 하는 컴퓨트 셰이더#version 430 corelayout(local_sizee_x = 32, local_size_y = 32) in;..
Transorm Feedback - 정점, 테셀레이션, 기하 셰이더의 결과를 하나 이상의 버퍼 개체에 저장하기 위한 기능 - front end의 마지막 단계 - 프로그래밍 불가능, 고정 기능 스테이지 - 현 파이프라인의 마지막 단계에서 출력된 attribute들 중 명시한 것들이 버퍼에 기록된다 - 기하 셰이더가 없을 경우: 정점/테셀레이션 출력 정점들이 기록됨 - 기하 셰이더가 있을 경우: EmitVertex()에 의해 생성된 정점들이 저장됨 => 데이터 양이 변함 - Transform Feedback Buffer: 셰이더들의 출력을 포착하기 위해 쓰이는 버퍼 data -> TFB -> glGetBufferSubData() -> glMapBuffer() 사용법: GL에게 우리가 기록하길 원하는 출력을 ..