본문 바로가기

WebGL

[WebGL + ThreeJs] 램버시안 조명 (Lambertian Light)

 

 

 

본 글은 이전 ambient & hemi lighting에 대한 확장 글입니다.

 

Three.BasicMaterial의 성질을 갖는 Lambertian Lighting(램버시안 조명)을 구현해 보도록 하겠습니다.

 

varying vec3 vNormal;
varying vec3 vPosition;
uniform samplerCube specMap;

float inverseLerp(float v,float minValue,float maxValue){
  return(v-minValue)/(maxValue-minValue);
}

float remap(float v,float inMin,float inMax,float outMin,float outMax){
  float t=inverseLerp(v,inMin,inMax);
  return mix(outMin,outMax,t);
}

vec3 phongSpecular(vec3 viewDir , vec3 lightDir , vec3 lightColor , vec3 normal){
  vec3 reflectDir = normalize(reflect(-lightDir, normal));
  float phongValue = max(0.0, dot(viewDir, reflectDir));
  phongValue = pow(phongValue, 32.0);
  return lightColor * phongValue;
}

void main(){
  vec3 baseColor=vec3(.5);
  vec3 lighting=vec3(.1451,.1176,.1176);
  vec3 viewDir = normalize(cameraPosition - vPosition);
  
  vec3 normal=normalize(vNormal);
  vec3 ambient=vec3(.5);
  
  vec3 skycolor=vec3(0.,.3,.6);
  vec3 groundColor=vec3(.6,.3,.1);
  
  float hemiMix=remap(normal.y,-1.,1.,0.,1.);
  vec3 hemi=mix(groundColor,skycolor,hemiMix);
  
  lighting=ambient*0.+hemi*.5;
  vec3 color=baseColor*lighting;
  
  gl_FragColor=vec4(color,1.);
}

 

빛의 산란(diffuse)을 나타내기 위해, 먼저 빛의 방향을 구해야합니다.

 

임의값으로 설정해도 무방합니다.

 

저는 광원이 물체 위치 기준, (1,1,1) 방향에 있다 가정할 것이므로,

 

광원 기준 빛을 물체에 쏘는 방향은 다음과 같습니다.

 

 

vec3 lightDir = vec3(-1.0,-1.0,-1.0);

 

빛의 색상 또한 임의의 색상으로 지정합니다. 

vec3 lightColor = vec3(1.0,1.0,1.0);

 

물체의 법선벡터가 빛의 역방향과의 사잇각이 0에 가까울 수록 빛에 영향을 더 많이 받으므로, 사잇각에 의존하여 반사율로 삼습니다.

 

float dp = dot(lightDir, normal);

 

 

이때, 빛의 세기를 정의할 때, 음수값은 정의 하지 않으므로, 세기 값의 하한선을 0으로 삼습니다.

 

float dp = max(0.0, dot(lightDir, normal));

 

이제 빛의 색상과 빛의 세기를 곱하여, 산란광을 구합니다.

 

 vec3 diffuse = dp * lightColor;

 

 

최종적으로 fragmentColor에 혼합합니다.

 

  lighting=ambient*0.+hemi*.5 + diffuse * .5;
  vec3 color=baseColor*lighting;
  
  gl_FragColor=vec4(color,1.);