환경매핑이란, 주위의 환경을 미리 텍스처 안에 저장하고
실시간으로 그 텍스처를 입히는 것이다.
간접광을 재현하며 거울같은 표면을 표현하는 기법이다.
유니티에서 hdri를 적용하거나 스카이박스를 만들어 적용하듯이
똑같이 D3D환경에서 환경 매핑을 하는 것이다.
김포프님의 책에서는 상하, 좌우, 전후로 6개 텍스쳐로 주위를 감싸는
스카이박스 형식으로 구현하였다. 입방체 맵이라고 한다.
위 그림은 카메라부터 면을 반사해 부딪히는
입방체 텍스쳐를 얻어내는 그림이다.
Hlsl 내장함수로 쉽게 reflect() 함수를 이용해서
카메라 벡터의 반사벡터를 얻어낼 수 있다.
그리고 texCUBE()로 텍스쳐샘플러와 반사벡터를 인자로 받아
환경매핑을 얻어 올 수 있다.
VS 버텍스 셰이더는 앞에 했던 포스팅과 내용이 같아서 생략한다.
PS 픽셀셰이더
입방체 텍스쳐는 samplerCUBE 변수를 쓴다.
반사 벡터를 구하고 샘플러와 반사벡터를 사용해 환경매핑벡터를 구한다.
출력확인을 위해 기존 법선매핑을 0,0,1로 덮어씌우고
환경맵만 리턴하였다.
확인했으면 기존 법선매핑, 난반사광, 정반사광도 리턴해준다.
환경맵이 너무 강해서 강도도 절반으로 줄였다.
결과
간접광을 재현하며 거울같은 표면을 표현하는 기법으로
빛나는 벽돌 텍스쳐의 주전자를 볼 수 있다.
더보기
더보기
//vs
float4x4 gWorldMatrix;
float4x4 gWorldViewProjMatrix;
float4 gWorldLightPos;
float4 gWorldCamPos;
struct VS_INPUT
{
float4 mPosition : POSITION;
float3 mNormal : NORMAL;
float3 mTangent : TANGENT;
float3 mBinormal : BINORMAL;
float2 mUV : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 mPosition : POSITION;
float2 mUV : TEXCOORD0;
//float3 mDiffuse : TEXCOORD1; 정점법선이 아닌 텍셀법선
float3 mLightDir : TEXCOORD1;
float3 mViewDir : TEXCOORD2;
float3 mT : TEXCOORD3;
float3 mB : TEXCOORD4;
float3 mN : TEXCOORD5;
};
VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;
Output.mPosition = mul( Input.mPosition, gWorldViewProjMatrix );
Output.mUV = Input.mUV;
float4 worldPos = mul(Input.mPosition, gWorldMatrix);
float3 lightDir = worldPos.xyz - gWorldLightPos.xyz;
Output.mLightDir = normalize(lightDir);
float3 viewDir = normalize(worldPos.xyz-gWorldCamPos.xyz);
Output.mViewDir = viewDir;
float3 worldNormal = mul(Input.mNormal, (float3x3)gWorldMatrix);
Output.mN=normalize(worldNormal);
float3 worldTangent = mul(Input.mTangent, (float3x3)gWorldMatrix);
Output.mT=normalize(worldTangent);
float3 worldBinormal = mul(Input.mBinormal, (float3x3)gWorldMatrix);
Output.mB=normalize(worldBinormal);
return Output;
}
//ps
struct PS_INPUT
{
float2 mUV : TEXCOORD0;
float3 mLightDir : TEXCOORD1;
float3 mViewDir : TEXCOORD2;
float3 mT : TEXCOORD3;
float3 mB : TEXCOORD4;
float3 mN : 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 = normalize(tangentNormal*2-1);
//tangentNormal = float3(0,0,1);
float3x3 TBN = float3x3(normalize(Input.mT), normalize(Input.mB),normalize(Input.mN));
TBN = transpose(TBN);
float3 worldNormal = mul(TBN, tangentNormal);
float4 albedo = tex2D(DiffuseSampler, Input.mUV);
float3 lightDir = normalize(Input.mLightDir);
float3 diffuse = saturate(dot(worldNormal, -lightDir));
diffuse = gLightColor * albedo.rgb*diffuse;
float3 viewDir = normalize(Input.mViewDir);
float3 specular = 0;
if(diffuse.x > 0.0f)
{
float3 reflection = reflect(lightDir, worldNormal);
specular = saturate(dot(reflection, -viewDir));
specular = pow(specular,20.0f);
float4 specularInten=tex2D(SpecularSampler, Input.mUV);
specular*=specularInten.rgb*gLightColor;
}
float3 viewReflect = reflect(viewDir, worldNormal);
float3 environment = texCUBE(EnvironmentSampler, viewReflect).rgb;
float3 ambient = float3(0.1f, 0.1f, 0.1f)*albedo;
return float4(ambient+diffuse+specular+(environment*0.5f),1);
}
'STUDY > Shader Programming' 카테고리의 다른 글
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자8 (그림자 매핑) (0) | 2021.12.21 |
---|---|
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자7 (UV 애니메이션 Animation & 울렁효과) (0) | 2021.12.20 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자5 (법선 매핑) (0) | 2021.12.20 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자4 (툰셰이더) (0) | 2021.12.17 |
셰이더 프로그래밍 - AMD RenderMonkey 사용해서 쉐이더 공부를 해보자3 (디퓨즈/ 스페큘러 매핑) (0) | 2021.12.17 |