์ƒˆ์†Œ์‹

ํฌํŠธํด๋ฆฌ์˜ค ํ”„๋กœ์ ํŠธ/NewRo

[NewRo] Shadow ์‹œ์Šคํ…œ(23.05.04)

  • -
728x90

 

NewRo์— Shadow ์‹œ์Šคํ…œ์„ ์ ์šฉ

 

 

 

1. ShadowMap

๋น›์˜ ๊ด€์ ์—์„œ ์žฅ๋ฉด์„ ๋ Œ๋”๋งํ•˜๊ณ , ๋น›์˜ ๊ด€์ ์—์„œ ๋ณด์ด๋Š” ๋ชจ๋“  ๊ฒƒ์€ ํ™˜ํ•˜๊ฒŒ ํ‘œ์‹œํ•˜๊ณ  ๋ณผ์ˆ˜ ์—†๋Š” ๊ฒƒ๋“ค์€ ๊ทธ๋ฆผ์ž๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋…ธ๋ž€์ƒ‰ ๋ถ€๋ถ„๋“ค์ด ๋น›์˜ ์‹œ์•ผ์—์„œ ๋ณด์ด๋Š” ๋ถ€๋ถ„๋“ค์ด๊ณ  ๊ฒ€์ •์ƒ‰ ๋ถ€๋ถ„๋“ค์ด ๋น›์˜ ์‹œ์•ผ์—์„œ ๋ณด์ด์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด๋‹ค.

์ˆ˜์ฒœ๊ฐœ์˜ ๋น› ๋ฐฉํ–ฅ Ray๋ฅผ ํ†ตํ•ด ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์€ ์‹ค์‹œ๊ฐ„ ๋ Œ๋”๋ง์—์„œ ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ๋Œ€์•ˆ์œผ๋กœ ์ƒ๊ฐํ•œ ๊ฒƒ์ด ๊นŠ์ด ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

Shadow Map์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘๊ฐœ์˜ ํŒจ์Šค๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.

  1. ๋น›์˜ ๊ด€์ ์—์„œ ๊นŠ์ด ๋ฒ„ํผ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊นŠ์ด ๊ฐ’์˜ ์ƒ˜ํ”Œ์„ ์ถ”์ถœ ํ•œ๋‹ค. (๊นŠ์ด ๋งต or ์‰๋„์šฐ ๋งต)
  2. ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ fragment๊ฐ€ ๊ทธ๋ฆผ์ž๋กœ ํ‘œ์‹œ๋ ์ง€ ์•„๋‹์ง€ ํŒ๋‹จํ•˜์—ฌ ๊ทธ๋ฆฐ๋‹ค.

 

๋จผ์ € ๋น›์˜ ๊ด€์ ์—์„œ ๊นŠ์ด ๋ฒ„ํผ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊นŠ์ด ๊ฐ’์˜ ์ƒ˜ํ”Œ์„ ์ถ”์ถœํ•œ๋‹ค.

//shadowMap vert
#version 430

layout(location=0) in vec3 coord3d;

out vec4 position;

uniform mat4 lightSpaceMatrix;
uniform mat4 Model;


void main(void)
{
   gl_Position = lightSpaceMatrix* Model * vec4( coord3d,1.0);
   position = gl_Position;
}

 

๋น› ๊ณต๊ฐ„์˜ ์œ„์น˜ ๊ฐ’์„ position์„ ํ†ตํ•ด fragment ์‰์ด๋”๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ฒ˜์Œ์—๋Š” fragment ์‰์ด๋”์— ์•„๋ฌด๋Ÿฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋นˆ fragment ์‰์ด๋”๋Š” ์•„๋ฌด๋Ÿฐ ์ฒ˜๋ฆฌ ์—†์ด ๋๋‚˜๋ฉด ๊นŠ์ด ๋ฒ„ํผ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ๋‹ค.

 

์•„ํฌ๋„ค ํ˜„์ƒ

 

bias ๊ฐ’์„ ๊ฐ€์ง€์ง€ ์•Š๊ณ  ๊ทธ๋ฆฌ๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ ์•„ํฌ๋„ค ํ˜„์ƒ์ด ์ผ์–ด๋‚œ๋‹ค.

 

bias = 0.005

 

ํ•˜์ง€๋งŒ bias๋ฅผ 0.005๋กœ ์„ค์ •์„ ํ•˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์›์— ๊ทธ๋ฆผ์ž๊ฐ€ ์ž…ํ˜€์ง€๋Š” ๋Š๋‚Œ์€ ์•„๋‹ˆ๋‹ค.

 

bias ๋ฒ”์œ„๋ฅผ 0.005~0.05

 

๋ฒ•์„ ๊ณผ ๋น›์˜ ๋ฐฉํ–ฅ์— ๊ธฐ์ดˆํ•˜์—ฌ bias ๋ฒ”์œ„๋ฅผ ์ˆ˜์ •ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜์˜€๋‹ค.

float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);

 

๊ฒฐ๊ณผ์ ์œผ๋กœ ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณด์ด์ง€๋งŒ ๋„ˆ๋ฌด ์›์˜ ๊ทธ๋ฆผ์ž๊ฐ€ ์‚ญ์ œ๋˜์–ด๋ฒ„๋ ธ๋‹ค.

์•„๋งˆ bias ๋ฒ”์œ„๊ฐ€ ์•ˆ๋งž์€ ๋“ฏํ•˜๋‹ค.

 

2. PCF ์ ์šฉ

pcf ์ ์šฉ ์ „

 

PCF๋Š” percentage-closer filtering ์˜ ์•ฝ์ž์ธ๋ฐ ์•ˆํ‹ฐ ์—์ผ๋ฆฌ์–ด์‹ฑ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

๊นŠ์ด ๋งต์˜ ์ฃผ๋ณ€ ํ…์…€์„ ์ƒ˜ํ”Œ๋งํ•˜๊ณ  ๊ฐ๊ฐ ๊ฐœ๋ณ„ ์ƒ˜ํ”Œ์— ๋Œ€ํ•ด ๊ทธ๋ฆผ์ž์ธ์ง€ ์•„๋‹Œ์ง€ ํŒ๋‹จํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ท ํ™”ํ•œ๋‹ค.

 

float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
for(int x = -1; x <= 1; ++x)
{
    for(int y = -1; y <= 1; ++y)
    {
        float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
        shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;        
    }    
}
shadow /= 9.0;

 

์ด ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ

 

float ShadowCalculationPCF(vec4 fragPosLightSpace,vec3 lightDir){
	vec2 size = textureSize(shadowMap,0);
	vec2 texelSize =  vec2(1.0,1.0)/size;

	vec3 projCoords = fragPosLightSpace.xyz/fragPosLightSpace.w;
	projCoords = projCoords*0.5+0.5;
	vec2 uv = projCoords.xy;
	float currentDepth = projCoords.z;
	float result = 0.0;

	vec2 textureSize = textureSize(shadowMap,0);
	float bias = 2.0/textureSize.x;
	
	//๋น›์— ๋Œ€ํ•œ ํ‘œ๋ฉด ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ๊ธฐ์šธ๊ธฐ์˜ ์–‘์„ ๋ณ€๊ฒฝ
	//bias = max(bias * (1.0 - dot(Normal, lightDir)), 0.005); 

	for(int x=-2;x<=2;x++)
	{
		for(int y=-2;y<=2;y++)
		{
			vec2 off = vec2(x,y)/size;
			result += InterpolatedCompare(shadowMap,uv+off,currentDepth,bias);
		}
	}

	return result/25.0;
}

 

PCF๋ฅผ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ์—์„œ๋Š” 4๋ฒˆ์˜ ์ƒ˜ํ”Œ๋ง์„ ๊ฑฐ์ณค์ง€๋งŒ NewRo๋Š” ์ด 8๋ฒˆ์˜ ์ƒ˜ํ”Œ๋ง์„ ํ•˜์˜€๊ณ  ๋Œ€์‹  bias๊ฐ’์„ ์กฐ๊ธˆ ํ‚ค์›Œ์ฃผ์—ˆ๋‹ค.

                                     PCF(์ขŒ)                                                                             ๋น›์— ๋Œ€ํ•œ ํ‘œ๋ฉด ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ๊ธฐ์šธ๊ธฐ์˜ ์–‘์„ ๋ณ€๊ฒฝ(์šฐ)
                             PCF ๋ณด๊ฐ„ (์ขŒ)                                                                      ๋น›์— ๋Œ€ํ•œ ํ‘œ๋ฉด ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ๊ธฐ์šธ๊ธฐ์˜ ์–‘์„ ๋ณ€๊ฒฝ(์šฐ)

 

 

3. VSM

VSM์€ Variance Shadow Mapping์˜ ์ค„์ž„๋ง์œผ๋กœ Shadow edge๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

PCF์˜ ๋ฌธ์ œ์ ์€ ๊นŠ์ด ๋ฒ„ํผ์—์„œ ์ƒ์„ฑ๋œ ๊ฐ’์„ ํ•˜๋“œ์›จ์–ด๋กœ ํ•„ํ„ฐ๋ง ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ฆ‰ ํ•˜๋“œ์›จ์–ด์—์„œ ์ž๋™์œผ๋กœ ์…‹ํŒ…ํ•ด์ฃผ๋˜ ๊นŠ์ด ๋ฒ„ํผ ๊ฐ’์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ๊ฐœ์„ ํ•˜๊ณ  ์‹ถ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

chebyshev๋Š” PCF๋ฅผ ์ง„ํ–‰ํ•  ์˜์—ญ์˜ Shadowing ๋น„์œจ์„ ์–ป์œผ๋ ค๊ณ  ํ–ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋งŒ๋“  ๋ถ€๋“ฑ์‹์€ ๋ถ„์‚ฐ(Variance)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

  1. dpeth์™€ depth*depth ๊ฐ’์„ ์ƒ‰์ƒ fbo์— ์ €์žฅํ•˜๊ณ (32๋น„ํŠธ floating ์ •๋ฐ€๋„ ์‚ฌ์šฉ)
  2. chebyshev's ๊ณต์‹์„ ์ด์šฉํ•˜์—ฌ ์–ด๋–ค fragmet๊ฐ€ ๊ทธ๋ฆผ์ž์— ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ์•Œ์•„๋‚ด๊ณ , fragment๊ฐ€ ๊ทธ๋ฆผ์ž์— ๊ฐ€๋ ค์งˆ ํ™•๋ฅ ์„ ๊ณ„์‚ฐํ•œ๋‹ค.(์ž์œ ๋กœ์šด ๊ฒฝ๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ํŽธ๋ฆฌํ•จ)

์ž๊ฐ€ ์Œ์˜์ด ๊ณ„์† ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— 

glCullFace(GL_FRONT);

 

๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

glEnable(GL_DEPTH_TEST);

 

๊นŠ์ด ๋ฒ„ํผ ํ™œ์„ฑํ™” ์ฝ”๋“œ๋„ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.

 

//shadowMap frag
#version 430

out vec4 FragColors;
in vec4 position;

void main()
{

	float depth = position.z/position.w;
	depth = depth*0.5+0.5;

	float moment1 = depth;
	float moment2 = depth*depth;

	//return the partial derivative of an argument with respect to x or y
	//x ๋˜๋Š” y์— ๋Œ€ํ•œ ์ธ์ˆ˜์˜ ๋ถ€๋ถ„ ๋ฏธ๋ถ„์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
	//๋„ํ•จ์ˆ˜๋Š” ๋ธ”๋ก์˜ ํ”ฝ์…€ ๊ฐ’ ์‚ฌ์ด์˜ ์ฐจ์ด๋ฅผ ์ทจํ•˜์—ฌ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
	float dx = dFdx(depth);  
	float dy = dFdy(depth);
	moment2 += 0.25*(dx*dx+dy*dy);

   FragColors = vec4(moment1,moment2,0.0,0.0);
}

 

Shadow์˜ ๊ฒฝ๊ณ„๊ฐ€ ๋˜๋Š” ๋ถ€๋ถ„์„ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ๋ถ„์‚ฐ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ

ํŠน์ • Depth ๊ฐ’์˜ ์ฐจ์ด๊ฐ€ ํด์ˆ˜๋ก ๋ถ„์‚ฐ ๊ฐ’์ด ๋” ์ปค์ง€๋Š” ์ ์„ ์ด์šฉํ•˜์—ฌ Shadowing์˜ ๋น„์œจ์„ ๋„์ถœํ•ด๋‚ธ๋‹ค.

float ShadowCalculationVSM(vec4 fragPosLightSpace,vec3 projCoords){

	float p_max =0.0;
	projCoords = projCoords*0.5+0.5;
	float currentDepth = projCoords.z;

	vec2 moments = texture(shadowMap,projCoords.xy).rg;

	if(projCoords.z<=moments.x)
			return 1.0;
	float variance = max(moments.y-(moments.x*moments.x),0.0002);

	float d =  projCoords.z - moments.x;
	p_max=variance/(variance+d*d);

   return p_max;
}

 

 

๋งŽ์€ ์š”์ธ์— ๋”ฐ๋ผ ์ข‹์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š์„ ๊ฒฝ์šฐ max ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์ฃผ๋ฉด ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค.

์กฐ๊ธˆ๋” ์ž์—ฐ์Šค๋Ÿฌ์›Œ์ง„๋‹ค.

      max(moments.y-(moments.x*moments.x),0.00002);                                            max(moments.y-(moments.x*moments.x),0.002);

 

 

*ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๋ฌธ์ œ๋“ค*

  1.  ortho ๋ฅผ perspective๋กœ ๋ณ€๊ฒฝ → Directional Light๊ฐ€ ์•„๋‹Œ Spot Light ๊ตฌํ˜„

 

 

 

์ฐธ๊ณ ํ•œ ์‚ฌ์ดํŠธ

 

LearnOpenGL - Shadow Mapping

Shadow Mapping Advanced-Lighting/Shadows/Shadow-Mapping Shadows are a result of the absence of light due to occlusion. When a light source's light rays do not hit an object because it gets occluded by some other object, the object is in shadow. Shadows add

learnopengl.com

 

 

Tunnel Java oldschool

February 14th, 2009 Softshadow with GLUT,GLSL and VSM When I got started learning openGL Shading Language, the "Orange Book" was a great resource, but I thought it lacked code samples. Here is a modest cross platform implementation of Variance shadow mappi

fabiensanglard.net

 

 

๋ฐ˜์‘ํ˜•
Contents

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

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