Post Lists

2018년 12월 3일 월요일

glTexImage2D Deferred Rendering에서 사용시 주의할 점.

현재 Deferred Rendering을 만드는 중인데,

쉐이더에서 뭔가 요구하는 대로 안되어서 여러가지 명세서를 읽다가 이제 알아챘다.

First Pass에서 G-buffer를 입력하고, Second Pass에서
Lighting Calculation을 계산하는 쉐이더에서

다음과 같은 코드가 있었다.


if(MyBool.a == 1.0)
{
    // Light Map Material Calculation
}
else
{
    // Color Material Calculation
}

이렇게 했을 때, 오브젝트가 그려지지 않은 background pixel이 light map material calculation할 때, directional light의 색깔을 따라 갔다.

위의 코드에는 두 개의 문제점이 있는데 일단

가장 첫 번째는 floating point value의 comparison을 수행할 때 단순히 저렇게 하는 것은 precision으로 인해 올바른 비교가 되지 않을 가능성이 높다.

만약 다음의 세 가지 코드를 각각 사용했을 때


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

세 번째 파라미터는 internal format인데, shader에서 쓰이는 값의 format을 말한다.
첫 번째 것은 값들을 0 ~ 1로 clamp 시켜버린다.
두 번째 것은 값들을 어떤 범위 제한 없이 사용할 수 있다. 다만 floating point value가 16 bit precisino에서 표현된다.
세 번째 것은 값들을 어떤 범위 제한 없이 사용할 수 있다. 다만 floating point value가 32bit precision에서 표현된다.

첫 번째 파라미터의 RGBA는 unsigned normalized 형식으로 바꾼다고 한다.
두 번째 파라미터는 그대로 쓰는데 16bit precision으로 표현된다, 그리고 명세서에 의하면 8번째 파라미터가 gl_float인데, 값들이 gl_half_float로 내부적으로 바뀐다고 한다.
세 번째 파라미터는 그대로 쓴느데 32bit precision으로 표현된다.

그래서, 어쨋든 이 bit precision에 주의해서 비교를해야 한다.
만약 내가 MyBool.a 값을 0.5, 0.25, 0.125, 0.0625 이런식으로 2진수로 표현하기에 딱 떨어지는 수로 한다면, == 을 썼을 때 내가 원하는대로 작동할 확률이 높다.

GL_RGBA32F는 거의 대부분 == 에 대해서 성공하고
GL_RGBA16F는 저기 위에서 언급한 2진수로 딱 떨어지는 수가 좋다.
GL_RGBA도 0 ~ 1 사이의 2진수로 딱 떨어지는 수로 하여야 한다.

두 번째
두 번째는 내가 명세서를 찾아도 거의 나오지 않는 것들인데, first pass에서 g-buffer에 오브젝트를 그리지 않은 곳에서 MyBool을 texture 함수를 통해 값을 얻으려할 때,

(0, 0, 0, 1)

의 값이 들어가게 된다. 그래서 if (MyBool.a == 1) 일 때 background pixel value가 directional lights에 따라서 바뀌게 된 것이다.

그래서, 이걸 주의해서 MyBool 값을 설정해주면 문제가 없어진다.

왜 저 값이 있는지에 대한 것은

https://stackoverflow.com/questions/34497195/difference-between-format-and-internalformat#comment56736641_34497470

이 스택오버플로우 대화에서 볼 수 있는데,

https://gamedev.stackexchange.com/questions/66613/blank-texture-in-frame-buffer-object-in-deferred-rendering
https://www.opengl.org/discussion_boards/showthread.php/185819-How-to-render-few-objects-with-texture-and-other-without-%28Simple-deferred-shading%29
이 내용도 더 봐보자.

=================================================
알아버렸다. glClearColor(r, g, b, a) 시에
해당 framebuffer에 연결된 color buffer들은 해당 rgba 값으로 변경된다.

그래서 위에서 오브젝트가 그려지지 않은 곳의 텍스쳐 값은 모두 다 0, 0, 0, 1인 이유가
glClearColor(0, 0, 0, 1)로 했기 때문이다. 이로서 고민 해결 끝.

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearColor.xhtml
명세에서도, color buffer를 해당 값으로 clear하므로, deferred rendering에서
오브젝트가 그려지지 않는 background pixel을 참조할 시에 glClearColor 값들이
들어오게 될 것이다.






댓글 없음:

댓글 쓰기