์ƒˆ์†Œ์‹

๊ณต๋ถ€/OpenGL ์ž๋ฃŒ ๋ฒˆ์—ญ

[๋ฒˆ์—ญ] Tutorial 16 : Shadow mapping

  • -
728x90

์›๋ณธ : http://www.opengl-tutorial.org/kr/intermediate-tutorials/tutorial-16-shadow-mapping/

 

ํŠœํ† ๋ฆฌ์–ผ 15์—์„œ๋Š” ์ •์  ์กฐ๋ช…์„ ํฌํ•จํ•˜๋Š” ๋ผ์ดํŠธ ๋งต์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

์•„์ฃผ ๋ฉ‹์ง„ ๊ทธ๋ฆผ์ž๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ชจ๋ธ์€ ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

Shadow Map์€ ํ˜„์žฌ(2016๋…„ ๊ธฐ์ค€) ๋™์  Shadow๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์˜ ์ข‹์€ ์ ์€ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ธฐ์— ๊ฝค ์‰ฝ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜์œ์ ์€ ์ œ๋Œ€๋กœ ์ž‘์—… ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ต๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋จผ์ € ๊ธฐ๋ณธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์†Œ๊ฐœํ•˜๊ณ  ๋‹จ์ ์„ ํ™•์ธํ•œ ๋‹ค์Œ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ์ˆ ์„ ๊ตฌํ˜„ํ•˜์—ฌ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Shadow Map์„ ์ž‘์„ฑํ•  ๋‹น์‹œ(2012๋…„)์—๋Š” ์—ฌ์ „ํžˆ ๋งŽ์€ ์—ฐ๊ตฌ๊ฐ€ ์ง„ํ–‰ ์ค‘์ธ ์ฃผ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”์— ๋”ฐ๋ผ ์ž์ฒด Shadow Map์„ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ธฐ๋ณธ Shadowmap

๊ธฐ๋ณธ Shadow Map ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‘ ๊ฐœ์˜ ํŒจ์Šค๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋จผ์ €, ์žฅ๋ฉด์€ ๋น›์˜ ๊ด€์ ์—์„œ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค. ๊ฐ fragment์˜ ๊นŠ์ด๋งŒ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์”ฌ(scene)์ด ํ‰์†Œ์™€ ๊ฐ™์ด ๋ Œ๋”๋ง๋˜์ง€๋งŒ ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ์กฐ๊ฐ์ด ๊ทธ๋ฆผ์ž์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

"๊ทธ๋ฆผ์ž ์†์— ์žˆ๋Š” ๋ฌผ์ฒด" ํ…Œ์ŠคํŠธ๋Š” ์‚ฌ์‹ค ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ƒ˜ํ”Œ์ด ๋™์ผํ•œ ์ ์—์„œ ๊ทธ๋ฆผ์ž ๋งต๋ณด๋‹ค ๋น›์—์„œ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์œผ๋ฉด ์”ฌ(scene)์— ๋น›์— ๋” ๊ฐ€๊นŒ์šด ๊ฐœ์ฒด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ํ˜„์žฌ fragment๋Š” ๊ทธ๋ฆผ์ž์— ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋‹ค์Œ ์ด๋ฏธ์ง€๋Š” ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Shadowmap ๋ Œ๋”๋งํ•˜๊ธฐ

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” directional lights(๋ชจ๋“  ๊ด‘์„ ์ด ํ‰ํ–‰ํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ๋Š” ์กฐ๋ช…)๋งŒ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Shadow Map ๋ Œ๋”๋ง์€ ์ง๊ต ํˆฌ์˜ ํ–‰๋ ฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ง๊ต ํ–‰๋ ฌ์€ ์›๊ทผ๋ฒ•์ด ๊ณ ๋ ค๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์ผ๋ฐ˜์ ์ธ ์›๊ทผ๋ฒ• ํˆฌ์˜ ํ–‰๋ ฌ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฌผ์ฒด๋Š” ์นด๋ฉ”๋ผ ๊ฐ€๊นŒ์ด์— ์žˆ๋Š” ๋ฉ€๋ฆฌ์žˆ๋“  ๋™์ผํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.

 

๋ Œ๋” ๋Œ€์ƒ ๋ฐ MVP ๋งคํŠธ๋ฆญ์Šค ์„ค์ •

ํŠœํ† ๋ฆฌ์–ผ 14๋ถ€ํ„ฐ๋Š” ์‰์ด๋”์—์„œ ๋‚˜์ค‘์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ์žฅ๋ฉด์„ ํ…์Šค์ฒ˜๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ๋Š” Shadow Map์„ ํฌํ•จํ•˜๊ธฐ ์œ„ํ•ด 1024x1024 16๋น„ํŠธ depth ํ…์Šค์ฒ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Shadow Map์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 16๋น„ํŠธ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’๋“ค์„ ์ž์œ ๋กญ๊ฒŒ ์‹œํ—˜ํ•ด๋ณด์„ธ์š”. ๋‚˜์ค‘์— ์ƒ˜ํ”Œ๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ depth ๋ Œ๋” ๋ฒ„ํผ๊ฐ€ ์•„๋‹Œ depth ํ…์Šค์ฒ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
 GLuint FramebufferName = 0;
 glGenFramebuffers(1, &FramebufferName);
 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);

 // Depth texture. Slower than a depth buffer, but you can sample it later in your shader
 GLuint depthTexture;
 glGenTextures(1, &depthTexture);
 glBindTexture(GL_TEXTURE_2D, depthTexture);
 glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);

 glDrawBuffer(GL_NONE); // No color buffer is drawn to.

 // Always check that our framebuffer is ok
 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
 return false;

๋น›์˜ ๊ด€์ ์—์„œ ์žฅ๋ฉด์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” MVP ๋งคํŠธ๋ฆญ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค:

  • Projection ํ–‰๋ ฌ์€ X,Y ๋ฐ Z ์ถ•์—์„œ ๊ฐ๊ฐ ์ถ• ์ •๋ ฌ ์ƒ์ž(-10, 10), (-10,10), (-10, 20)์˜ ๋ชจ๋“  ๊ฒƒ์„ ํฌํ•จํ•˜๋Š” ์ง๊ต ํ–‰๋ ฌ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ’์€ ์ „์ฒด *๊ฐ€์‹œ์ ์ธ* ์žฅ๋ฉด์„ ํ•ญ์ƒ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์กŒ์œผ๋ฉฐ, ์ด์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ถ”๊ฐ€ ์ง„ํ–‰ ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
  • View ํ–‰๋ ฌ์€ ์นด๋ฉ”๋ผ ๊ณต๊ฐ„์—์„œ ์กฐ๋ช… ๋ฐฉํ–ฅ์ด -Z๊ฐ€ ๋˜๋„๋ก ์›”๋“œ๋ฅผ ํšŒ์ „์‹œํ‚ต๋‹ˆ๋‹ค(ํŠœํ† ๋ฆฌ์–ผ 3 ์ฐธ์กฐ)
  • Model ํ–‰๋ ฌ์€ ์›ํ•˜๋Š” ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
glm::vec3 lightInvDir = glm::vec3(0.5f,2,2);

 // Compute the MVP matrix from the light's point of view
 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20);
 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0,0,0), glm::vec3(0,1,0));
 glm::mat4 depthModelMatrix = glm::mat4(1.0);
 glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;

 // Send our transformation to the currently bound shader,
 // in the "MVP" uniform
 glUniformMatrix4fv(depthMatrixID, 1, GL_FALSE, &depthMVP[0][0])

์‰์ด๋”

์ด ํŒจ์Šค ๋™์•ˆ ์‚ฌ์šฉ๋˜๋Š” ์‰์ด๋”๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. vertex ์‰์ด๋”๋Š” ๊ท ์งˆ ์ขŒํ‘œ์—์„œ ์ •์ ์˜ ์œ„์น˜๋ฅผ ๊ฐ„๋‹จํžˆ ๊ณ„์‚ฐํ•˜๋Š” ํ†ต๊ณผ ์‰์ด๋”์ž…๋‹ˆ๋‹ค:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

// Values that stay constant for the whole mesh.
uniform mat4 depthMVP;

void main(){
 gl_Position =  depthMVP * vec4(vertexPosition_modelspace,1);
}

fragment ์‰์ด๋”๋Š” ๋‹จ์ˆœํ•˜๊ธฐ ๋•Œ๋ฌธ์— fragment์˜ ๊นŠ์ด๋ฅผ ์œ„์น˜ 0(์ฆ‰, ๊นŠ์ด ํ…์Šค์ฒ˜)์— ๊ธฐ๋กํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

#version 330 core

// Ouput data
layout(location = 0) out float fragmentdepth;

void main(){
    // Not really needed, OpenGL does it anyway
    fragmentdepth = gl_FragCoord.z;
}

Shadow Map์„ ๋ Œ๋”๋งํ•˜๋Š” ์†๋„๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ผ๋ฐ˜ ๋ Œ๋”๋ง๋ณด๋‹ค ๋‘ ๋ฐฐ ์ด์ƒ ๋น ๋ฆ…๋‹ˆ๋‹ค. ๊นŠ์ด์™€ ์ƒ‰์ƒ ๋Œ€์‹  ์ •๋ฐ€๋„๊ฐ€ ๋‚ฎ์€ ๊นŠ์ด๋งŒ ๊ธฐ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋Œ€์—ญํญ์€ GPU์—์„œ ๊ฐ€์žฅ ํฐ ์„ฑ๋Šฅ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

๊ฒฐ๊ณผ ํ…์Šค์ฒ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์–ด๋‘์šด ์ƒ‰์ƒ์€ ์ž‘์€ z๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฒฝ์˜ ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ ๋ชจ์„œ๋ฆฌ๊ฐ€ ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋Œ€๋กœ ํฐ์ƒ‰์€ z=1(๋™์ผํ•œ ์ขŒํ‘œ)์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ๋งค์šฐ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

Shadowmap ์‚ฌ์šฉํ•˜๊ธฐ

๊ธฐ๋ณธ ์‰์ด๋”

์ด์ œ ํ‰์†Œ์˜ ์‰์ด๋”๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๊ณ„์‚ฐํ•˜๋Š” ๊ฐ fragment์— ๋Œ€ํ•ด Shadow Map ๋’ค์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฅผ ์œ„ํ•ด Shadow Map์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•œ ๊ณต๊ฐ„๊ณผ ๋™์ผํ•œ ๊ณต๊ฐ„์—์„œ ํ˜„์žฌ fragment์˜ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ผ๋ฐ˜์ ์ธ MVP ํ–‰๋ ฌ๋กœ ํ•œ ๋ฒˆ ๋ณ€ํ™˜ํ•˜๊ณ  ๊นŠ์ด MVP ํ–‰๋ ฌ๋กœ ํ•œ ๋ฒˆ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ์•ฝ๊ฐ„์˜ ์†์ž„์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์  ์œ„์น˜์— ๊นŠ์ด๋ฅผ ๊ณฑํ•˜๋ฉด MVP๋Š” [-1,1]์— ์žˆ๋Š” ๊ท ์ผํ•œ ์ขŒํ‘œ๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ํ…์Šค์ฒ˜ ์ƒ˜ํ”Œ๋ง์€ [0,1]์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, ํ™”๋ฉด ์ค‘์•™์— ์žˆ๋Š” fragment๋Š” ๊ท ์ผํ•œ ์ขŒํ‘œ๋กœ (0,0)์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์งˆ๊ฐ ์ค‘๊ฐ„์€ ์ƒ˜ํ”Œ๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ UV๋Š” (0.5,05)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๊ฒƒ์€ fragment shader์—์„œ ์ง์ ‘ fetch ์ขŒํ‘œ๋ฅผ ์กฐ์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹จ์ˆœํžˆ ์ขŒํ‘œ๋ฅผ 2(๋Œ€๊ฐ์„  : [-1.1] -> [-0.5,0.5])๋กœ ๋‚˜๋ˆ„๊ณ  ๋ณ€ํ™˜ํ•˜๋Š” ํ–‰๋ ฌ(์•„๋ž˜ ํ–‰ : [-0.5,0.5]->[0,1])์„ ๊ณฑํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

glm::mat4 biasMatrix(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasMVP = biasMatrix*depthMVP;

์ด์ œ vertex ์‰์ด๋”๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „๊ณผ ๋™์ผํ•˜์ง€๋งŒ 1:1์ด ์•„๋‹Œ 2๊ฐœ์˜ ์œ„์น˜๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค:

  • gl_Position ์€ ํ˜„์žฌ ์นด๋ฉ”๋ผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ •์ ์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค.
  • ShadowCoord๋Š” ๋งˆ์ง€๋ง‰ ์นด๋ฉ”๋ผ(๋น›)์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ •์ ์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค.
// Output position of the vertex, in clip space : MVP * position
gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

// Same, but with the light's view matrix
ShadowCoord = DepthBiasMVP * vec4(vertexPosition_modelspace,1);

๊ทธ๋Ÿฐ ๋‹ค์Œ fragment ์‰์ด๋”๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค:

  • texture(shadowMap, ShadowCoord.xy).z ๋Š” ๋น›๊ณผ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋น›์„ ์ฐจ๋‹จํ•˜๋Š” ํ์ƒ‰์ž ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • ShadowCoord.z๋Š” ๋น›๊ณผ ํ˜„์žฌ fragment ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

...๋”ฐ๋ผ์„œ ํ˜„์žฌ fragment๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํ์ƒ‰์ž๋ณด๋‹ค ๋ฉ€๋ฆฌ ์žˆ์œผ๋ฉด, ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ (ํ•ด๋‹น ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํ์ƒ‰์ž์˜) ๊ทธ๋ฆผ์ž์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

float visibility = 1.0;
if ( texture( shadowMap, ShadowCoord.xy ).z  <  ShadowCoord.z){
    visibility = 0.5;
}

์šฐ๋ฆฌ๋Š” ์ด ์ง€์‹์„ ์ด์šฉํ•˜์—ฌ ์Œ์˜์„ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ฃผ๋ณ€ ์ƒ‰์ƒ์€ ์ˆ˜์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒํ™œ ์†์˜ ๋ชฉ์ ์€ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆผ์ž ์†์— ์žˆ์„ ๋•Œ๋„ ๋“ค์–ด์˜ค๋Š” ๋น›์„ ๊ฐ€์งœ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋˜๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์ˆ˜ํ•œ ๊ฒ€์€์ƒ‰์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค)

color =
 // Ambient : simulates indirect lighting
 MaterialAmbientColor +
 // Diffuse : "color" of the object
 visibility * MaterialDiffuseColor * LightColor * LightPower * cosTheta+
 // Specular : reflective highlight, like a mirror
 visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5);

๊ฒฐ๊ณผ - ์‰๋„์šฐ ์•„ํฌ๋„ค

๋‹ค์Œ์€ ํ˜„์žฌ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ, ์•„์ด๋””์–ด๋Š” ๋›ฐ์–ด๋‚˜์ง€๋งŒ , ํ’ˆ์งˆ์€ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ์ด๋ฏธ์ง€์˜ ๊ฐ ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ์—๋Š” ShadowMap๊ณผ ShadowMap_simple์˜ ๋‘ ๊ฐ€์ง€ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ์œผ๋ฉฐ, ๋‘˜ ์ค‘ ๋” ๋งˆ์Œ์— ๋“œ๋Š” ๊ฒƒ์œผ๋กœ ์‹œ์ž‘ํ•˜์„ธ์š”.

๊ฐ„๋‹จํ•œ ๋ฒ„์ „์€ ์œ„์˜ ์ด๋ฏธ์ง€๋งŒํผ ํ’ˆ์งˆ์ด ์ข‹์ง€ ์•Š์ง€๋งŒ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์ ๋“ค

Shadow acne

๊ฐ€์žฅ ๋ช…๋ฐฑํ•œ ๋ฌธ์ œ์ ์€ shadow acne์ด๋‹ค:

์ด ํ˜„์ƒ์€ ๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€๋กœ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

์ด์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ "์ˆ˜์ •"์€ error margin์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ fragment์˜ depth(๋‹ค์‹œ๋งํ•ด, ๋น› ๊ณต๊ฐ„)๊ฐ€ ๋ผ์ดํŠธ๋งต ๊ฐ’์—์„œ ์ •๋ง ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์Œ์˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํŽธํ–ฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

float bias = 0.005;
float visibility = 1.0;
if ( texture( shadowMap, ShadowCoord.xy ).z  <  ShadowCoord.z-bias){
    visibility = 0.5;
}

๊ฒฐ๊ณผ๋ฌผ์€ ํ›จ์”ฌ ๋‚˜์•„์ง‘๋‹ˆ๋‹ค:

ํ•˜์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์€ ์šฐ๋ฆฌ์˜ ํŽธ๊ฒฌ ๋•Œ๋ฌธ์— ๋•…๊ณผ ๋ฒฝ ์‚ฌ์ด์˜ ์ธ๊ณต๋ฌผ์ด ๋” ๋‚˜๋น ์กŒ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€, 0.005์˜ ํŽธํ–ฅ์€ ๋•…์—์„œ๋Š” ๋„ˆ๋ฌด ๋งŽ์ด ๋ณด์ด์ง€๋งŒ, ๊ณก๋ฉด์—์„œ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: ๋ช‡๋ช‡ ์ธ๊ณต๋ฌผ๋“ค์€ ์‹ค๋ฆฐ๋”์™€ ๊ตฌ์— ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ธฐ์šธ๊ธฐ์— ๋”ฐ๋ผ ์น˜์šฐ์นจ์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

float bias = 0.005*tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1
bias = clamp(bias, 0,0.01);

Shadow acne๋Š” ์ด์ œ, ๊ตฌ๋ถ€๋Ÿฌ์ง„ ํ‘œ๋ฉด์—์„œ๋„ ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค.

์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ์— ๋”ฐ๋ผ ์ž‘๋™ํ•˜๊ฑฐ๋‚˜ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ShadowMap์—์„œ ๋’ท๋ฉด๋งŒ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋‘๊บผ์šด ๋ฒฝ์„ ๊ฐ€์ง„ ํŠน๋ณ„ํ•œ ๊ธฐํ•˜ํ•™์  ๊ตฌ์กฐ(๋‹ค์Œ ์„น์…˜ - Peter Panning ์ฐธ์กฐ)๋ฅผ ๊ฐ–๋„๋ก ๊ฐ•์š”ํ•˜์ง€๋งŒ, ์ ์–ด๋„ acne๋Š” ๊ทธ๋ฆผ์ž์— ์žˆ๋Š” ํ‘œ๋ฉด์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ShadowMap์„ ๋ Œ๋”๋งํ•  ๋•Œ ์ „๋ฉด ์‚ผ๊ฐํ˜•์„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.

        // We don't use bias in the shader, but instead we draw back faces,
        // which are already separated from the front faces by a small distance
        // (if your geometry is made this way)
        glCullFace(GL_FRONT); // Cull front-facing triangles -> draw only back-facing triangles

๊ทธ๋ฆฌ๊ณ  ์”ฌ(scene)์„ ๋ Œ๋”๋งํ•  ๋•Œ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค(๋’ท๋ฉด ์ ˆ๋‹จ)

         glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles

์ด ๋ฐฉ๋ฒ•์€ ํŽธํ–ฅ ์™ธ์—๋„ ์ฝ”๋“œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Peter Panning

์šฐ๋ฆฌ๋Š” ๋” ์ด์ƒ Shadow acne๊ฐ€ ์—†์ง€๋งŒ, ์—ฌ์ „ํžˆ ์ž˜๋ชป๋œ ์Œ์˜์˜ ๋•…์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋ฒฝ์„ ๋‚ ์•„๋‹ค๋‹ˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค(์ดํ›„ "ํ”ผํ„ฐ ํŒจ๋‹"์ด๋ผ๋Š” ์šฉ์–ด). ์‚ฌ์‹ค, ํŽธํ–ฅ(bias)์„ ๋”ํ•˜๋Š” ๊ฒƒ์€ ์ƒํ™ฉ์„ ๋” ์•…ํ™”์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋งค์šฐ ์‰ฝ๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–‡์€ ๊ธฐํ•˜ํ•™์  ๊ตฌ์กฐ๋ฅผ ํ”ผํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋จผ์ €, ํ”ผํ„ฐ ํŒจ๋‹์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๊ธฐํ•˜ํ•™์ด ์—ฌ๋Ÿฌ๋ถ„์˜ ํŽธ๊ฒฌ๋ณด๋‹ค ๋” ๊นŠ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์ค€๋น„๊ฐ€ ๋‹ค ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๋‘ ๋ฒˆ์งธ๋กœ, ๋ผ์ดํŠธ๋งต์„ ๋ Œ๋”๋งํ•  ๋•Œ ํ›„๋ฉด ์ ˆ๋‹จ ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด์ œ ๋ฒฝ์˜ ๋‹ค๊ฐํ˜•์ด ๋น›์„ ํ–ฅํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๋‹ค๊ฐํ˜•์€ ๋’ท๋ฉด ์ ˆ๋‹จ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋ง๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ ์€ ๋ Œ๋”๋งํ•  ์‚ผ๊ฐํ˜•์ด ๋” ๋งŽ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(ํ”„๋ ˆ์ž„๋‹น ๋‘ ๋ฒˆ!)

Aliasing

์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์—ฌ๋Ÿฌ๋ถ„์€ ๊ทธ๋ฆผ์ž์˜ ๊ฒฝ๊ณ„์— ์—ฌ์ „ํžˆ ์•จ๋ฆฌ์–ด์‹ฑ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ํ•œ ํ”ฝ์…€์€ ํฐ์ƒ‰์ด๊ณ  ๋‹ค์Œ ํ”ฝ์…€์€ ๊ฒ€์€์ƒ‰์ž…๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ๋งค๋„๋Ÿฌ์šด ์ „ํ™˜์ด ์—†์Šต๋‹ˆ๋‹ค.

PCF

์ด๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ShadowMap์˜ ์ƒ˜ํ”Œ๋Ÿฌ ์œ ํ˜•์„ Sampler2D ์‰์ด๋”๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ShadowMap์„ ํ•œ ๋ฒˆ ์ƒ˜ํ”Œ๋งํ•˜๋ฉด ํ•˜๋“œ์›จ์–ด๊ฐ€ ์‹ค์ œ๋กœ ์ธ์ ‘ํ•œ ํ…์…€๋„ ์ƒ˜ํ”Œ๋งํ•˜๊ณ  ๋ชจ๋“  ํ…์…€์— ๋Œ€ํ•ด ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ๋น„๊ต ๊ฒฐ๊ณผ์˜ ์ด์ค‘ ์„ ํ˜• ํ•„ํ„ฐ๋ง๊ณผ ํ•จ๊ป˜ [0,1]์˜ ๋ถ€๋™ ์†Œ์ˆ˜์ ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, 0.5๋Š” ๋‘ ๊ฐœ์˜ ํ‘œ๋ณธ์ด ๊ทธ๋ฆผ์ž์— ์žˆ๊ณ  ๋‘ ๊ฐœ์˜ ํ‘œ๋ณธ์ด ๋น›์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

ํ•„ํ„ฐ๋ง๋œ ๊นŠ์ด ๋งต์˜ ๋‹จ์ผ ์ƒ˜ํ”Œ๋ง๊ณผ ๋™์ผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๋น„๊ต๋Š” ํ•ญ์ƒ true ๋˜๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. PCF๋Š” 4 "true ๋˜๋Š” false"์˜ ๋ณด๊ฐ„๊ฐ’์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ณด์‹œ๋‹ค์‹œํ”ผ ๊ทธ๋ฆผ์ž ํ…Œ๋‘๋ฆฌ๋Š” ๋งค๋„๋Ÿฝ์ง€๋งŒ ๊ทธ๋ฆผ์ž ๋งต์˜ ํ…์Šค์ฒ˜๋Š” ์—ฌ์ „ํžˆ ๋ณด์ž…๋‹ˆ๋‹ค.

Poisson Sampling

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ์‰๋„์šฐ ๋งต์„ ํ•œ ๋ฒˆ์ด ์•„๋‹ˆ๋ผ N๋ฒˆ ์ƒ˜ํ”Œ๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. PCF์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด N์ด ์ž‘๋”๋ผ๋„ ๋งค์šฐ ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ˜ํ”Œ 4๊ฐœ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

for (int i=0;i<4;i++){
  if ( texture( shadowMap, ShadowCoord.xy + poissonDisk[i]/700.0 ).z  <  ShadowCoord.z-bias ){
    visibility-=0.2;
  }
}

poissonDisk๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋œ ์ƒ์ˆ˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค:

vec2 poissonDisk[4] = vec2[](
  vec2( -0.94201624, -0.39906216 ),
  vec2( 0.94558609, -0.76890725 ),
  vec2( -0.094184101, -0.92938870 ),
  vec2( 0.34495938, 0.29387760 )
);

์ด ๋ฐฉ๋ฒ•์€ ํ†ต๊ณผํ•  ์‰๋„์šฐ ๋งต ์ƒ˜ํ”Œ ์ˆ˜์— ๋”ฐ๋ผ ์ƒ์„ฑ๋œ fragment๊ฐ€ ๋‹ค์†Œ ์–ด๋‘์›Œ์ง‘๋‹ˆ๋‹ค.

700.0 ์ƒ์ˆ˜๋Š” ํ‘œ๋ณธ์ด "ํ™•์‚ฐ"๋˜๋Š” ์ •๋„๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ์ ๊ฒŒ ํผ๋œจ๋ฆฌ๋ฉด ๋‹ค์‹œ ์•จ๋ฆฌ์–ด์‹ฑ์ด ๋ฐœ์ƒํ•˜๊ณ , ๋„ˆ๋ฌด ๋งŽ์ด ํผ๋œจ๋ฆฌ๋ฉด ๋ฐด๋”ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.*(์ด ์Šคํฌ๋ฆฐ์ƒท์€ ๋” ๊ทน์ ์ธ ํšจ๊ณผ๋ฅผ ์œ„ํ•ด PCF๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  16๊ฐœ์˜ ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.*

Stratified Poisson Sampling

ํ”ฝ์…€๋งˆ๋‹ค ๋‹ค๋ฅธ ์ƒ˜ํ”Œ์„ ์„ ํƒํ•˜์—ฌ ์ด ๋ฐด๋”ฉ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค : Stratified Poisson ๋˜๋Š” Rotated Poisson

Stratified๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ‘œ๋ณธ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. Rotated๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋žœ๋ค ํšŒ์ „์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋กœ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Stratified ๋ฒ„์ „๋งŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ด์ „ ๋ฒ„์ „๊ณผ์˜ ์œ ์ผํ•œ ์ฐจ์ด์ ์€ ๋žœ๋ค ์ธ๋ฑ์Šค๋กœ poissonDisk๋ฅผ ์ธ๋ฑ์‹ฑํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

    for (int i=0;i<4;i++){
        int index = // A random number between 0 and 15, different for each pixel (and each i !)
        visibility -= 0.2*(1.0-texture( shadowMap, vec3(ShadowCoord.xy + poissonDisk[index]/700.0,  (ShadowCoord.z-bias)/ShadowCoord.w) ));
    }

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๋‚œ์ˆ˜๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ,[0,1]์—์„œ ๋‚œ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

    float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
    return fract(sin(dot_product) * 43758.5453);

์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ seed4๋Š” i(4๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์œ„์น˜์—์„œ ์ƒ˜ํ”Œ์„ ์ฑ„์ทจํ•  ์ˆ˜ ์žˆ๋„๋ก)์™€ ...์˜ ์กฐํ•ฉ์ด ๋ฉ๋‹ˆ๋‹ค.

gl_FragCord(ํ™”๋ฉด์˜ ํ”ฝ์…€ ์œ„์น˜)๋˜๋Š” Position_worldspace๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        //  - A random sample, based on the pixel's screen location.
        //    No banding, but the shadow moves with the camera, which looks weird.
        int index = int(16.0*random(gl_FragCoord.xyy, i))%16;
        //  - A random sample, based on the pixel's position in world space.
        //    The position is rounded to the millimeter to avoid too much aliasing
        //int index = int(16.0*random(floor(Position_worldspace.xyz*1000.0), i))%16;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ํŒจํ„ด์ด ์‚ฌ๋ผ์ง€๊ณ  ์‹œ๊ฐ์  ๋…ธ์ด์ฆˆ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ž˜ ์ˆ˜ํ–‰๋œ ๋…ธ์ด์ฆˆ๋Š” ์ข…์ข… ์ด๋Ÿฌํ•œ ํŒจํ„ด๋ณด๋‹ค ๋œ ๋ถˆ์พŒํ•ฉ๋‹ˆ๋‹ค.

์„ธ ๊ฐ€์ง€ ๊ตฌํ˜„์— ๋Œ€ํ•œ ์˜ˆ๋Š” tutorial16/ShadowMapping.fragmentshader ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋” ๋‚˜์•„๊ฐ€๊ธฐ

์ด ๋ชจ๋“  ๋ฐฉ๋ฒ•์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์šฐ๋ฆฌ์˜ ๊ทธ๋ฆผ์ž๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Early bailing

๊ฐ fragment์— ๋Œ€ํ•ด 16๊ฐœ์˜ ํ‘œ๋ณธ์„ ์ถ”์ถœํ•˜๋Š” ๋Œ€์‹ (๋‹ค์‹œ ๋งํ•˜๋ฉด ๋งŽ์€ ์–‘) 4๊ฐœ์˜ ๋ฉ€๋ฆฌ ์žˆ๋Š” ํ‘œ๋ณธ์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๊ทธ๋“ค ๋ชจ๋‘๊ฐ€ ๋น›์ด๋‚˜ ๊ทธ๋ฆผ์ž ์†์— ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ 16๊ฐœ์˜ ์ƒ˜ํ”Œ ๋ชจ๋‘๊ฐ€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ƒˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: Early bailing. ๋งŒ์•ฝ ์–ด๋–ค ๊ฒƒ๋“ค์ด ๋‹ค๋ฅด๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์•„๋งˆ๋„ ๊ทธ๋ฆผ์ž ๊ฒฝ๊ณ„์— ์žˆ์„ ๊ฒƒ์ด๊ธฐ ๋Œ€๋ฌธ์— 16๊ฐœ์˜ ์ƒ˜ํ”Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Spot lights

์ŠคํฌํŠธ๋ผ์ดํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐ๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ฑฐ์˜ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ํ™•์‹คํ•œ ๊ฒƒ์€ ์ง๊ต ํˆฌ์šฉ ํ–‰๋ ฌ์„ ์›๊ทผ ํˆฌ์˜ ํ–‰๋ ฌ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

glm::vec3 lightPos(5, 20, 20);
glm::mat4 depthProjectionMatrix = glm::perspective<float>(glm::radians(45.0f), 1.0f, 2.0f, 50.0f);
glm::mat4 depthViewMatrix = glm::lookAt(lightPos, lightPos-lightInvDir, glm::vec3(0,1,0));

๊ฐ™์€ ๊ฒƒ์ด์ง€๋งŒ, orthographic frustum ๋Œ€์‹ ์— perspective frustum์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

texture2Dproj ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ทผ ๋ถ„ํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.(์ž์Šต์„œ4- ํ–‰๋ ฌ์˜ ๊ฐ์ฃผ ์ฐธ์กฐ)

 

๋‘๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ์‰์ด๋”์˜ ๊ด€์ ์—์„œ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.(์ž์Šต์„œ 4- ํ–‰๋ ฌ์˜ ๊ฐ์ฃผ ์ฐธ์กฐ). ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ํˆฌ์‹œ ํˆฌ์˜ ํ–‰๋ ฌ์€ ์‹ค์ œ๋กœ ์–ด๋–ค ํˆฌ์‹œ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ํ•˜๋“œ์›จ์–ด์—์„œ ์˜ˆ์ƒ ์ขŒํ‘œ๋ฅผ w๋กœ ๋‚˜๋ˆ„์–ด ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ, ์šฐ๋ฆฌ๋Š” ์‰์ด๋”์˜ ๋ณ€ํ˜•์„ ๋ชจ๋ฐฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ ์ž์‹ ์„ ๋ถ„ํ• ํ•˜๋Š” ๊ด€์ ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ, orthographic ํ–‰๋ ฌ์€ ํ•ญ์ƒ w=1์˜ ๊ท ์งˆ ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ์›๊ทผ๋ฒ•์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).

 

GLSL์—์„œ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ์ค„์€ ๋‚ด์žฅ textureProj ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ ์ •ํ™•ํ•˜๊ฒŒ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

if ( texture( shadowMap, (ShadowCoord.xy/ShadowCoord.w) ).z  <  (ShadowCoord.z-bias)/ShadowCoord.w )
if ( textureProj( shadowMap, ShadowCoord.xyw ).z  <  (ShadowCoord.z-bias)/ShadowCoord.w )

Point lights

๋™์ผํ•˜์ง€๋งŒ depth ๊ทœ๋ธŒ ๋งต์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ๋ธŒ ๋งต์€ ํ๋ธŒ์˜ ๊ฐ ๋ฉด์— ํ•˜๋‚˜์”ฉ ์žˆ๋Š” 6๊ฐœ์˜ ํ…์Šค์ฒ˜ ์„ธํŠธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ํ‘œ์ค€ UV ์ขŒํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” 3D ๋ฒกํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊นŠ์ด๋Š” ๊ณต๊ฐ„์˜ ๋ชจ๋“  ๋ฐฉํ–ฅ์— ๋Œ€ํ•ด ์ €์žฅ๋˜๋ฏ€๋กœ ์ ๊ด‘ ์ฃผ์œ„์— ๊ทธ๋ฆผ์ž๊ฐ€ ๋“œ๋ฆฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๊ฐœ์˜ ๋น› ํ˜ผํ•ฉ

์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์กฐ๋ช…์„ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ ๊ฐ ์กฐ๋ช…์€ ๊ทธ๋ฆผ์ž ๋งต์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์žฅ๋ฉด์„ ์ถ”๊ฐ€๋กœ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Shadow๋ฅผ ์ ์šฉํ•  ๋•Œ ์—„์ฒญ๋‚œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ๋Œ€์—ญํญ์ด ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ œํ•œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋™ ๋น› frustum

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์ „์ฒด ์žฅ๋ฉด์„ ํฌํ•จํ•˜๋„๋ก ์†์œผ๋กœ ๋งŒ๋“  ๋น› frustum์ž…๋‹ˆ๋‹ค. ์ด ์ œํ•œ๋œ ์˜ˆ์ œ์—์„œ๋Š” ์ด ์ž‘์—…์ด ์ž‘๋™ํ•˜์ง€๋งŒ ์ด ์ž‘์—…์€ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋‹น์‹ ์˜ ์ง€๋„๊ฐ€ 1Km x 1Km์ด๋ผ๋ฉด, ๋‹น์‹ ์˜ 1024x1024 ๊ทธ๋ฆผ์ž ์ง€๋„์˜ ๊ฐ ํ…์ŠคํŠธ๋Š” 1ํ‰๋ฐฉ๋ฏธํ„ฐ๋ฅผ ์ฐจ์ง€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ˜•ํŽธ ์—†์Šต๋‹ˆ๋‹ค. ์กฐ๋ช…์˜ ํˆฌ์˜ ํ–‰๋ ฌ์€ ๊ฐ€๋Šฅํ•œํ•œ ํƒ€์ดํŠธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

์ŠคํฌํŠธ๋ผ์ดํŠธ์˜ ๊ฒฝ์šฐ ๋ฒ”์œ„๋ฅผ ์กฐ์ •ํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํƒœ์–‘๊ณผ ๊ฐ™์€ ๋ฐฉํ–ฅ ์กฐ๋ช…์€ ๋” ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์ •๋ง๋กœ ์ „์ฒด ์žฅ๋ฉด์„ ๋น„์ถ”์ฃ . ๊ด‘๊ฒฉ์ž๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์ˆ˜์‹ ๊ธฐ ๋˜๋Š” ์ค„์—ฌ์„œ PSR์€ ๋น›์˜ frustum, view frustum ๋ฐ ์žฅ๋ฉด ๊ฒฝ๊ณ„ ์ƒ์ž์— ๋™์‹œ์— ์†ํ•˜๋Š” ๊ฐ์ฒด ์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์ด ๋ฌผ์ฒด๋“ค์€ ์Œ์˜์„ ๋ฐ›๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ์™€ ๋น›์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์บ์Šคํ„ฐ(PCF)๋Š” ๋ชจ๋‘ ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์ˆ˜์‹ ๊ธฐ์ด๋ฉฐ, ๊ทธ ์‚ฌ์ด์— ์žˆ๋Š” ๋ชจ๋“  ๋ฌผ์ฒด(๋ฌผ์ฒด๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ณด์ด๋Š” ๊ทธ๋ฆผ์ž๋ฅผ ๋“œ๋ฆฌ์šธ ์ˆ˜ ์žˆ์Œ)์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋น› ํˆฌ์˜ ํ–‰๋ ฌ์„ ๊ณ„์‚ฐํ•˜๋ ค๋ฉด ๋ณด์ด๋Š” ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋„ˆ๋ฌด ๋ฉ€๋ฆฌ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ๊ณ„ ์ƒ์ž์™€ ์กฐ๋ช… ์‚ฌ์ด์— ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ƒˆ ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฒˆ์—๋Š” ์กฐ๋ช… ๋ฐฉํ–ฅ์„ ๋”ฐ๋ผ ์ •๋ ฌ๋จ).

 

์ด๋Ÿฌํ•œ ์ง‘ํ•ฉ์˜ ์ •ํ™•ํ•œ ๊ณ„์‚ฐ์—๋Š” ๋ณผ๋ก ๊ป์งˆ ๊ต์ฐจ์  ๊ณ„์‚ฐ์ด ํฌํ•จ๋˜์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•์€ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค.

 

์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ฆผ์ž ๋งต ํ•ด์ƒ๋„๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌผ์น˜๊ฐ€ frustum์—์„œ ์‚ฌ๋ผ์ง€๋ฉด ํŒํ•‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ณ„๋‹จ์‹ Shadow Map์—๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ค์šฐ๋ฉฐ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ’์„ ๋งค๋„๋Ÿฝ๊ฒŒ ํ•˜์—ฌ ๋ณด์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง€์ˆ˜ shadow maps

์ง€์ˆ˜ ๊ทธ๋ฆผ์ž ๋งต์€ ๊ทธ๋ฆผ์ž์— ์žˆ์ง€๋งŒ ๋น› ํ‘œ๋ฉด ๊ทผ์ฒ˜์— ์žˆ๋Š” fragment๊ฐ€ ์‹ค์ œ๋กœ "๊ฐ€์šด๋ฐ ์–ด๋”˜๊ฐ€"๋ผ๊ณ  ๊ฐ€์ •ํ•˜์—ฌ ์•จ๋ฆฌ์–ด์‹ฑ์„ ์ œํ•œํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๊ฐ€ ๋”์ด์ƒ ์ด์ง„๋ฒ•์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ์ œ์™ธํ•˜๋ฉด ์ด๋Š” ํŽธํ–ฅ๊ณผ ๊ด€๋ จ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น›์ด ์žˆ๋Š” ํ‘œ๋ฉด๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ํ•˜๋ฉด fragment๊ฐ€ ์ ์  ์–ด๋‘์›Œ์ง‘๋‹ˆ๋‹ค.

 

์ด๊ฒƒ์€ ๋ช…๋ฐฑํžˆ ๋ถ€์ •ํ–‰์œ„์ด๋ฉฐ, ๋‘ ๋ฌผ์ฒด๊ฐ€ ๊ฒน์น  ๋•Œ ์ธ๊ณต๋ฌผ์ด ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น›-๊ณต๊ฐ„ ์›๊ทผ๋ฒ• shadow maps

LiSPSM์€ ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์—์„œ ๋” ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋น› ํˆฌ์˜ ํ–‰๋ ฌ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ "๋ถˆ์•ˆ์ •ํ•œ frustra"์˜ ๊ฒฝ์šฐ์—๋Š” ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ๋ฐฉํ–ฅ์„ ๋ฐ”๋ผ์ง€๋งŒ, ์Šคํฟ๋ผ์ดํŠธ๋Š” ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์„ ๋ฐ”๋ผ๋ด…๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋น› ๊ทผ์ฒ˜, ์ฆ‰ ๋‹น์‹ ์œผ๋กœ๋ถ€ํ„ฐ ๋ฉ€๋ฆฌ ๋–จ์–ด์ง„ ๊ณณ์— ๋งŽ์€ ๊ทธ๋ฆผ์ž ์ง€๋„ ์ •๋ฐ€๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋‹น์‹ ์ด ๊ฐ€์žฅ ํ•„์š”๋กœ ํ•˜๋Š” ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์— ๋‚ฎ์€ ํ•ด์ƒ๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ LiSPSM์€ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค. ๊ตฌํ˜„์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๊ณ„๋‹จ์‹ shadow maps

CSM์€ LiSPSM๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฃจ์ง€๋งŒ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ view frustum์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜(2-4) ํ‘œ์ค€ ๊ทธ๋ฆผ์ž ๋งต์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๊ฒƒ์€ ์ฒซ ๋ฒˆ์งธ ๋ฏธํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๊ฝค ์ž‘์€ ๊ตฌ์—ญ์— ๋Œ€ํ•ด์„œ๋Š” ํ›Œ๋ฅญํ•œ ํ•ด์ƒ๋„๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ทธ๋ฆผ์ž ์ง€๋„๋Š” ๋” ๋จผ ๋ฌผ์ฒด๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ shadow map์€ ์žฅ๋ฉด์˜ ํฐ ๋ถ€๋ถ„์„ ๋‹ค๋ฃจ์ง€๋งŒ, ๊ด€์  ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ตฌ์—ญ๋ณด๋‹ค ์‹œ๊ฐ์ ์œผ๋กœ ๋” ์ค‘์š”ํ•˜์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๊ณ„๋‹จ์‹ ์‰๋„์šฐ ๋งต์€ ์ž‘์„ฑ ๋‹น์‹œ(2012๋…„) ์ตœ๊ณ ์˜ ๋ณต์žก์„ฑ/ํ’ˆ์งˆ ๋น„์œจ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋งŽ์€ ๊ฒฝ์šฐ์— ์„ ํƒ์˜ ํ•ด๊ฒฐ์ฑ…์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

๋ณด์‹œ๋‹ค์‹œํ”ผ, ๊ทธ๋ฆผ์ž ์ง€๋„๋Š” ๋ณต์žกํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค. ๋งค๋…„ ์ƒˆ๋กœ์šด ๋ณ€ํ˜•๊ณผ ๊ฐœ์„ ์‚ฌํ•ญ์ด ๋ฐœํ‘œ๋˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ๋กœ์„œ๋Š” ์–ด๋–ค ์†”๋ฃจ์…˜๋„ ์™„๋ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๋‹คํ–‰ํžˆ, ์ œ์‹œ๋œ ๋Œ€๋ถ€๋ถ„์˜ ๋ฐฉ๋ฒ•์€ ํ•จ๊ป˜ ํ˜ผํ•ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น› ๊ณต๊ฐ„ ๊ด€์ ์—์„œ ๊ณ„์‚ฐ์‹ shadow map์„ PCF๋กœ ๋งค๋„๋Ÿฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์™„๋ฒฝํ•˜๊ฒŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.. ์ด ๋ชจ๋“  ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ—˜ํ•ด ๋ณด์‹ญ์‹œ์˜ค.

 

๊ฒฐ๋ก ์ ์œผ๋กœ, ์ €๋Š” ๋‹น์‹ ์ด ๊ฐ€๋Šฅํ•  ๋•Œ๋งˆ๋‹ค ๋ฏธ๋ฆฌ ๊ณ„์‚ฐ๋œ ๋ผ์ดํŠธ๋งต์„ ๊ณ ์ˆ˜ํ•˜๊ณ , ๋™์  ๊ฐ์ฒด์—๋งŒ shadowmap์„ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‘ ๊ฐ€์ง€์˜ ์‹œ์ž‘์  ํ’ˆ์งˆ์ด ๋™์ผํ•œ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ์™„๋ฒฝํ•œ ์ •์  ํ™˜๊ฒฝ๊ณผ ๋ชจ์–‘์ƒˆ๊ฐ€ ์ข‹์ง€ ์•Š์€ ๊ทธ๋ฆผ์ž๊ฐ€ ์žˆ๋Š” ๊ฒƒ๋„ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

 

 

๋ฐ˜์‘ํ˜•
Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.