z
d
와 Perspective projection행렬을 사용하여 z
를 구할 수 있음z
를 구함d'
( d' = (d+1)/2 ) d
로 바꿔주는 과정 필요. . .
float n = 0.01; // near
float f = 1.0; // far
float LinearizeDepth(float dPri)
{
float d = dPri * 2 - 1; // d'[0,1] -> d[-1, 1]
return (2 * n * f) / (n + f + d * (n - f));
}
void main(void)
{
float depth = texture(depthTex, gl_FragCoord.xy / size).r; // [0,1] (가까울수록 0)
float z = LinearizeDepth(depth); // camera coord depth
. . .
out_Color = vec4(resColor/wSum, 1.0);
//out_Color = vec4(pow(vec3(z), vec3(4)), 1.0); // camera coord depth test
}
z
값을 사용하여 Gaussian blur kernel을 조절할 수 있게 됨(영상처리 강의노트)
gaussianFBO
는 rowGaussianFBO
로 이름을 변경하여 가로 블러 결과를 저장하고, 세로 블러 결과를 저장할 colGaussianFBO
를 새로 생성
. . .
FBO rowGaussianFBO;
FBO colGaussianFBO;
Program rowGaussianProgram;
Program colGaussianProgram;
rowGaussianProgram.loadShaders("gaussianBlur.vert", "colGaussianBlur.frag");
colGaussianProgram.loadShaders("gaussianBlur.vert", "rowGaussianBlur.frag");
// gaussian Frame Buffer Object
glGenFramebuffers(1, &rowGaussianFBO.frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, rowGaussianFBO.frameBuffer);
attachBuffers(&rowGaussianFBO);
glGenFramebuffers(1, &colGaussianFBO.frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, colGaussianFBO.frameBuffer);
attachBuffers(&colGaussianFBO);
. . .
void render(GLFWwindow* window)
{
. . .
// 2. draw on rowGaussianFBO
glBindFramebuffer(GL_FRAMEBUFFER, rowGaussianFBO.frameBuffer);
glViewport(0, 0, nowSize.x, nowSize.y);
glClearColor(0.1, 0.1, 0.1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(rowGaussianProgram.programID);
// diffFBO에 있는 텍스처 사용해서 가우시안 하기 위해 보내기
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffFBO.colorTexBuffer);
GLuint colorTexLocation = glGetUniformLocation(rowGaussianProgram.programID, "colorTex");
glUniform1i(colorTexLocation, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, diffFBO.depthBuffer);
GLuint depthTexLocation = glGetUniformLocation(rowGaussianProgram.programID, "depthTex");
glUniform1i(depthTexLocation, 1);
GLuint sizeLocation = glGetUniformLocation(rowGaussianProgram.programID, "size");
glUniform2f(sizeLocation, static_cast<float>(nowSize.x), static_cast<float>(nowSize.y));
// Draw a quad to apply Gaussian blur
glBindVertexArray(quadArrrayBuffer);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
// 3. draw on colGaussianFBO
glBindFramebuffer(GL_FRAMEBUFFER, colGaussianFBO.frameBuffer);
glViewport(0, 0, nowSize.x, nowSize.y);
glClearColor(0.1, 0.1, 0.1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(colGaussianProgram.programID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rowGaussianFBO.colorTexBuffer);
colorTexLocation = glGetUniformLocation(colGaussianProgram.programID, "colorTex");
glUniform1i(colorTexLocation, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, rowGaussianFBO.depthBuffer);
depthTexLocation = glGetUniformLocation(colGaussianProgram.programID, "depthTex");
glUniform1i(depthTexLocation, 1);
sizeLocation = glGetUniformLocation(colGaussianProgram.programID, "size");
glUniform2f(sizeLocation, static_cast<float>(nowSize.x), static_cast<float>(nowSize.y));
// Draw a quad to apply Gaussian blur
glBindVertexArray(quadArrrayBuffer);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
. . .
}
. . .
void main(void)
{
. . .
int wx = (int(kernel.x)-1)/2;
float wSum = 0;
for(int dx=-wx; dx<=wx; dx++)
{
float xx = gl_FragCoord.x / size.x + (dx * texelSize.x);
float w = exp(-(dx*dx)/(2.0 * sigma * sigma));
wSum += w;
resColor += w*texture(colorTex, vec2(xx, gl_FragCoord.y/size.y)).rgb;
}
resColor /= wSum;
out_Color = vec4(resColor, 1.0);
}
(▽가로 블러만 적용한 결과)
void main(void)
{
. . .
int wy = (int(kernel.y)-1)/2;
float wSum = 0;
for(int dy=-wy; dy<=wy; dy++)
{
float yy = gl_FragCoord.y / size.y + (dy * texelSize.y);
float w = exp(-(dy*dy)/(2.0 * sigma * sigma));
wSum += w;
resColor += w*texture(colorTex, vec2(gl_FragCoord.x/size.x, yy)).rgb;
}
resColor /= wSum;
out_Color = vec4(resColor, 1.0);
}
(▽세로 블러만 적용한 결과)
(▽가로/세로 블러 둘 다 적용한 결과)
z
를 출력해보는 과정에서 하얀색 또는 검정색 화면만 보이는 결과가 떴었음0.3
이었고, far는 1.0
, near은 0.01
로 설정해줌void main(void)
{
. . .
int wx = (int(kernel.x)-1)/2;
int wy = (int(kernel.y)-1)/2;
float wSum = 0;
// separable gaussian
vec3 rowColor, colColor = vec3(0);
for(int dx=-wx; dx<=wx; dx++)
{
float xx = gl_FragCoord.x / size.x + (dx * texelSize.x);
float w = exp(-(dx*dx)/(2.0 * sigma * sigma));
wSum += w;
rowColor += w*texture(colorTex, vec2(xx, gl_FragCoord.y/size.y)).rgb;
}
rowColor /= wSum;
wSum = 0;
for(int dy=-wy; dy<=wy; dy++)
{
float yy = gl_FragCoord.y / size.y + (dy * texelSize.y);
float w = exp(-(dy*dy)/(2.0 * sigma * sigma));
wSum += w;
colColor += w*texture(colorTex, vec2(gl_FragCoord.x/size.x, yy)).rgb;
}
colColor /= wSum;
resColor = vec3(rowColor[0]*colColor[0], rowColor[1]*colColor[1], rowColor[2]*colColor[2]);
out_Color = vec4(resColor, 1.0);
}
-> 각 픽셀별로 가로/세로 블러를 적용하는 것이 아닌, 전체 이미지에 가로 블러를 적용한 뒤 그 결과에 세로 블러를 적용해야하므로 새로운 버퍼 사용이 필수적임을 알았음