정점셰이더
struct VS_INPUT //입력을 받는 곳
{
float4 mPosition : POSITION; //버텍스에서 위치 정보를 받기 위한 시맨틱(DirectX의 버텍스
로부터 위치 정보를 구하는 기능)
float3 mNormal : NORMAL; // 법선(노멀) 시맨틱
};
struct VS_OUTPUT // 정점셰이더가 위치변환 결과를 래스터라이저 하는 과정(이다음에 픽셀
//셰이더로 넘어간다.) 출력하는곳이다.
{
float4 mPosition : POSITION; //정점 좌표를 위한 시맨틱
float2 mUV : TEXCOORD0; // (TEXCOORD0) UV좌표 위한 시맨틱
float2 mDiffuse : TEXCOORD1;
float3 mViewDir: TEXCOORD2; //
float3 mReflection: TEXCOORD3; //정반사를 받기 위한 표면 시맨틱
};
float4x4 gWorldMatrix; // 월드 공간
float4x4 gViewMatrix; // 뷰공간(월드공간안에 카메라로 찍힌 공간)
float4x4 gProjectionMatrix; // 투영공간(카메라에 찍힌 물체의 거리가 인지되는것을
화면으로 그려지는 이미지?)
float4 gWorldLightPositon; //라이트 위치
float4 gWorldCameraPositon; // 카메라 위치(정반사를 구하기위함)
VS_OUTPUT vs_main( VS_INPUT Input ) // VS_OUTPUT로 보내기전에 함수를 작성하는 곳
{
VS_OUTPUT Output; //반환할 구조체 선언
Output.mPosition = mul( Input.mPosition, gWorldMatrix ); //mPosition을 공간으로 변환
float3 lightDir = Output.mPosition.xyz - gWorldLightPositon.xyz; //노멀의 위치값을 구한다.
//정점위치에서 빛위치을 빼주면 정점이 빛에서 어떤 위치에 있는지 알수 있다.
//난반사를 구하는 값이다.
lightDir = normalize(lightDir); // 벡터(vector)를 1로 만드는 과정.
float3 viewDir = normalize(Output.mPosition.xyz - gWorldCameraPositon.xyz);
//정점에서 카메라위치를 빼주면 마찬가지로 정점이 카메라에서 어떤 위치인지 알수 있다.
//정반사를 구하는 값이다.
Output.mViewDir = viewDir;
Output.mPosition = mul( Output.mPosition, gViewMatrix ); //mPosition을 뷰공간화
Output.mPosition = mul( Output.mPosition, gProjectionMatrix ); //mPosition을 투영공간화
float3 worldNormal = mul(Input.mNormal, (float3x3)gWorldMatrix); //법선(노멀)을 월드공간으로 변환
worldNormal = normalize(worldNormal); //난반사
Output.mDiffuse = dot(-lightDir, worldNormal); // 법선을 구할 내적(코사인을 간략한것)
Output.mReflection = reflect(lightDir, worldNormal); //정반사
Output.mUV = Input.mUV; //텍스쳐UV
return Output;
}
픽셀셰이더
struct PS_INPUT //화면에 출력될 픽셀정보에 필요로 하는 것을 넣는다.
//버텍스의 정보가 변화되는 내용이 없기 때문이다. mPosition만 없다.
{
float2 mUV : TEXCOORD0;
float3 mDiffuse : TEXCOORD1;
float3 mViewDir: TEXCOORD2;
float3 mReflection: TEXCOORD3;
};
float4 ps_main(PS_INPUT Input) : COLOR //ps_main함수
{
float4 albedo = tex2D(DiffuseSampler, Input.mUV); //텍스쳐
//float3 diffuse = saturate(Input.mDiffuse); //난반사
float3 diffuse = gLightColor * albedo.rgb * saturate(Input.mDiffuse);//난반사에 텍스쳐를 추가
float3 reflection = normalize(Input.mReflection);
float3 ViewDir = normalize(Input.mViewDir);
float3 specular = 0;
if(diffuse.x >0) //정반사 (빛이 닿지않는 부분은 필요없기때문에 0이상으로 설정)
{
specular = saturate(dot(reflection, -ViewDir));
specular = pow(specular, 20.0f); // 난반사보다 강해야 하므로,
//빛을 강하게 받아야하니 강제로 값을 올려준다.
}
float3 ambient = float3(0.1f, 0.1f, 0.1f); //물체의 어두운부분이 너무 어둡지 않게
//임의로 밝게 처리(환경광효과처럼 넣는다.)
//즉, 실제 반사가 되서 밝아진것이 아니라 강제로 밝게 한것이다.
return float4(ambient + diffuse + specular, 1);
}
참고서적: 셰이더 프로그래밍입문의 RenderMonkey기반
'Unity > Code base Shader' 카테고리의 다른 글
Fake Shine (0) | 2021.02.13 |
---|---|
Microsoft HLSL (0) | 2021.02.09 |
인위적 유리 셰이더 (0) | 2021.02.09 |
Z-Buffer, Render Queue, Tag, Blending (0) | 2021.01.01 |
Unity Shader에 대한 이해 (0) | 2021.01.01 |