헤더파일

셰이더 공부 - 환경매핑 본문

DirectX

셰이더 공부 - 환경매핑

헤더파일 2018. 2. 27. 19:29

주위환경이 표면에 반사되는 걸 재현하는 기법입니다. 매끄러운 자동차표면에 주위 환경이 반사되는 것 같은 멋진 효과를 줄 수 있습니다. 사실 이건 표면이 입사광을 전혀 흡수하지 않고 그 모두를 정반사하는 원리입니다. 하지만 다른 물체에서 나온 정반사, 난반사광을 끝없이 따라가며 구하는 것은 실시간렌더링에서 많이 어려운 작업입니다. 따라서 여기에 약간의 트릭을 씁니다.

미리 반사될 주위 환경을 큐브형태의 텍스쳐를 만들어 놓습니다.  그 다음에 카메라벡터의 반사벡터를 구해 큐브형태의 텍스쳐에서 텍셀을 얻어옵니다.


정점 셰이더는 법선매핑 때와 다를게 없습니다. 


픽셀 셰이더


struct PS_INPUT

{

   float2 mUV : TEXCOORD0;

   float3 mLightDir : TEXCOORD1;

   float3 mViewDir: TEXCOORD2;

   float3 T:TEXCOORD3;

   float3 B:TEXCOORD4;

   float3 N:TEXCOORD5;

};


sampler2D DiffuseSampler;

sampler2D SpecularSampler;

sampler2D NormalSampler;

samplerCUBE EnvironmentSampler;


float3 gLightColor;


float4 ps_main(PS_INPUT Input) : COLOR

{

   float3 tangentNormal = tex2D(NormalSampler, Input.mUV).xyz;

   tangentNormal = float3(0,0,1);

   

   float3x3 TBN = float3x3(normalize(Input.T),normalize(Input.B),normalize(Input.N));

   TBN = transpose(TBN);

   

   float3 worldNormal = mul(TBN, tangentNormal);

   

   float3 lightDir = normalize(Input.mLightDir);

   float3 diffuse = saturate(dot(worldNormal, -lightDir));

   

   float4 albedo = tex2D(DiffuseSampler, Input.mUV);

   diffuse = gLightColor*albedo.rgb*diffuse;

   

   float3 specular = 0;

   float3 viewDir = normalize(Input.mViewDir);

   

   if(diffuse.x>0)

   {

      float3 reflection = reflect(lightDir,worldNormal);

         

      specular = saturate(dot(reflection,-viewDir));

      specular = pow(specular,20.0f);

      

      float4 specularIntensity = tex2D(SpecularSampler, Input.mUV);

      specular *=specularIntensity.rgb * gLightColor;

   }

   

   float3 reflectView = reflect(viewDir, worldNormal);

   float3 environment = texCUBE(EnvironmentSampler,reflectView).rgb;

   

   float3 ambient = float3(0.1f,0.1f,0.1f)*albedo;

   

   return float4(ambient + diffuse + specular + (environment*0.5f), 1);

}


   float3 tangentNormal = tex2D(NormalSampler, Input.mUV).xyz;

   tangentNormal = float3(0,0,1);


이 부분은 원래는 필요없지만 현재의 노멀맵이 환경매핑을 고려하지 않은 울퉁불퉁해서 반사를 잘 못 나타내기 때문에 넣은 것입니다. x,y 방향의 값은 없애고 표면의 바깥쪽만 향하게 합니다.


   float3 reflectView = reflect(viewDir, worldNormal);

   float3 environment = texCUBE(EnvironmentSampler,reflectView).rgb;


카메라 벡터인 viewDir의 반사벡터를 reflect 함수로 구해줍니다. texCUBE함수는 벡터값으로 텍셀을 찾게해주는 함수입니다.


   return float4(ambient + diffuse + specular + (environment*0.5f), 1);


이렇게 얻은 텍셀을 조명결과와 합치는데 환경매핑의 결과가 너무 강해 0.5를 곱했습니다.



Comments