본문 바로가기
공허의 유산/표현의 자유

[opengl].[#2.GLSL] 15. Spot light

by 바른생활머시마 2023. 2. 9.
728x90
반응형

Directional light를 살펴보다가 Positional light, 즉, 점광원을 살펴봤습니다.

https://learn-and-give.tistory.com/62

 

[opengl].[#2.GLSL] 14. Positional light

앞에서 Ambient+Specular light의 구현을 해보았습니다. https://learn-and-give.tistory.com/61 [opengl].[#2.GLSL] 13. ambient 조명과 specular 조명 앞에서 Diffuse 조명과 재질을 쉐이더로 구현하는 방법을 살펴봤습니다. [

learn-and-give.tistory.com

 

대충 이해하기

 

이번에는 점광원 중에서 빛이 방사되는 범위가 한정되는 spot light를 구현 해 보겠습니다. 

spot light는 방사되는 각도에 제한이 있는 것이므로, 계산하는 시점에 조명에서 그 지점으로 향하는 벡터와 조명의 방향 벡터 사이의 각도를 구하여 일정한 범위를 넘어가면 그려주지 않으면 됩니다. 다시 말해서, 조명의 방향 벡터와 조명 위치에서 조사되는 위치를 향하는 벡터 사이 각도가 지정 된 범위 내에 있는 경우에만 조명 계산을 해주면 됩니다.

 

 

조사 범위 내외부 판정

다른 항목들은 다 앞의 내용을 그대로 사용하도록 하고, 각도에 의한 조사 여부 판정만 한번 적용 해 보도록 하겠습니다. 조사 범위 내부인지 외부인지 판단하는 방법을 알아보겠습니다.

 

 앞선 point light에서 조명에서 해당 조사 지점을 향하는 벡터를 Vertex shader에서 구했었습니다.

 

...
	ecPos = gl_ModelViewMatrix * gl_Vertex;
	aux = vec3(gl_LightSource[0].position-ecPos);
	lightDir = normalize(aux);
...

 

spot light는 positional light? directional light? 

 

이 벡터와 조명의 방향을 나타내는 벡터와 내적을 구하면 됩니다. 

 혹시, 점광원에서 무슨 조명의 방향???? 이런 생각이 드시는 것이라면 아주 좋습니다. 실제 광원은 점광원이지만, spot light는 조사되는 범위를 어떤 방향으로부터 설정을 합니다. 즉, spot light는 점광원이지만 direction이 있습니다. positional light와 directional light는 광원의 위치가 있느냐, 조사되는 방향이 있느냐에 대한 특성을 나타내는 것이라서 정확히 반대 개념은 아닙니다. spot light의 경우, 조명의 위치가 있으므로 positional light이며, 또한 방향이 있으므로 directional light이기도 합니다. 그러나, directional light의 경우, 방향의 여부를 나타내기도 하지만, 경우에 따라서는 모든 빛이 평행하게 한 방향을 향하는 빛을 나타낼 때도 쓰입니다. 오히려 평행광이라고 표현하는 것이 덕 접할 할 수도 있겠네요.

 아무튼, spot light는 이러한 특성이 있는 조명이라는 것을 잘 이해하도록 합니다

 

내외부 판정 기준

조명의 방향이나, 조명의 방향으로부터 몇 도까지 조명 계산을 할 것인가도, 다른 속성들처럼 uniform으로 전달 할 수도 있지만, 이미 fixed pipeline에서도 spot light가 지원 되었었기 때문에, 이 역시도 관련 정보를 얻을 수 있는 예약 된 변수 이름이 있으니, 그것을 쓰면 됩니다.

	...
    ...
    if (NdotL > 0.0) {
	
	  spotEffect = dot(normalize(gl_LightSource[0].spotDirection), normalize(-lightDir));
		if (spotEffect > gl_LightSource[0].spotCosCutoff) {
			spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent);
    ...
    ...

여기서 spotCosCutoff는 유효 범위를 의미하는 것처럼 보이는데, spotExponent는 뭔지 잘 감이 오지 않는데요, 이것은 조명의 방향에서 멀어질 수록 어두워지는 효과를 내기 위한 것으로, 거리가 멀어지면 조명의 효과가 줄어드는 attenuation처럼 조명 방향에서 멀어질 수록 어두워지는 효과를 내는 항 입니다. 거리에 따른 감쇄 효과는 모든 범위 내에도 동일한 수식으로 계산되지만, 이 cut off의 경우, 일정 범위 내에서는 그대로 유지되다가 지정 된 각도를 넘어서면 급격히 어두워지도록 하는 효과 입니다. 수식은 아래와 같습니다.

 

이렇게 해서 작성되는 Fragment shader는 아래와 같습니다.

varying vec4 diffuse,ambientGlobal, ambient;
varying vec3 normal,lightDir,halfVector;
varying float dist;
void main()
{
	vec3 n,halfV;
	float NdotL,NdotHV;
	vec4 color = ambientGlobal;
	float att,spotEffect;
	
	n = normalize(normal);
	NdotL = max(dot(n,normalize(lightDir)),0.0);

	if (NdotL > 0.0) {
	
	  spotEffect = dot(normalize(gl_LightSource[0].spotDirection), normalize(-lightDir));
		if (spotEffect > gl_LightSource[0].spotCosCutoff) {
			spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent);
			att = spotEffect / (gl_LightSource[0].constantAttenuation +
					gl_LightSource[0].linearAttenuation * dist +
					gl_LightSource[0].quadraticAttenuation * dist * dist);
				
			color += att * (diffuse * NdotL + ambient);
		
			
			halfV = normalize(halfVector);
			NdotHV = max(dot(n,halfV),0.0);
			color += att * gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV,gl_FrontMaterial.shininess);
		}
	}
	gl_FragColor = color;
}

 

 

 

 

자, 이제 이 코드에서 spot light와 관련 된 항들이 영향을 미치려면, 관련 된 값들을 설정 해야 합니다. OpenGL 코드에 이 값을 설정 해 주는 코드도 반영해 보겠습니다.

 

관련 된 매개변수들은 아래와 같습니다.

매개변수 기본값 설명
GL_SPOT_DIRECTION 0,0,-1 방향
GL_SPOT_EXPONENT 0 스포트라이트 지수
GL_SPOT_CUTOFF 180 스포트라이트 절단각

이때 절단각이 180도라는 것은 전방향을 의미하며, 실제 사용 시 0~90도를 사용할 수 있습니다.

 

이제 이 조명들이 사용되는 것을 테스트 해 볼텐데, 조명은 정면에서 화면 안쪽을 향하면서 좌우로 움직이도록 해보겠습니다.

 

테스트 조건을 만들면서 테스트 하다보니, 조명을 구에 가깝게 뒀더니 point light의 감쇄 효과가 좀 더 눈에 잘 띄는 것 같네요.

 

 

아래는 결과 영상입니다. 구에 적용 할때 조명이 구와 가까우면 조사 되는 면적이 매우 작고, 구에서 멀어지면 면적이 넒어집니다. 주전자처럼 표현이 울툴불퉁한 경우, specular에 의해서 입체감이 느껴지네요. exponential에 의한 감쇄 효과는 조명이 설정 된 cut-off 범위 내에서 발생합니다. 즉, 0이면 cufoff 범위까지 감쇄 없는 빛이 비춰지고, 이 값이 커지면 감쇄가 일찍 시작되므로 조명이 더 어두워지면서 윤곽이 흐릿하게 됩니다.

 

 

이제 조명은 알아보았고, 다음 시간부터는 텍스쳐링에 대해서 살펴보겠습니다.

https://learn-and-give.tistory.com/64

 

[opengl].[#2.GLSL] 16. Texturing 기초

제법 멋진 Spot light까지 쉐이더로 구현 해 보았습니다. https://learn-and-give.tistory.com/63 [opengl].[#2.GLSL] 15. Spot light Directional light를 살펴보다가 Positional light, 즉, 점광원을 살펴봤습니다. https://learn-and-g

learn-and-give.tistory.com

 

728x90
반응형

댓글