프로젝션 텍스처 그림자를 제작해 보았습니다.
소개
이 기사의 작성은 「이케니에와 눈의 세츠나」그래픽 해설(제2회·그래픽 효과편) 를 참고하겠습니다
매우 공부되었습니다.
이번은 참고 기사 내용의 하나, 투영 텍스처 그림자에 대해 실작해 보고 싶습니다
그림자 맵 작성
우선, 그림자 카메라를 생성하여 광원과 같은 방향을 설치한다 (광시점으로 생각하면 좋다.
Culling Mask를 Fuck하고 피사체만 찍을 수 있도록
그 후 그림자 카메라의 targetTexture를 지정한다.
그 지정된 RenderTexture는 나중에 투영 텍스처 그림자가 참조하는 그림자 맵입니다.
SetReplacementShader
그림자 맵에 그려지는 색은 그림자의 색만으로
그 때문에, 일일 피사체의 material을 바꾸는 것도 번거로운 작업
뭔가 좋은 방법이 있습니까?
SetReplacementShader 정말 소원을 줄 수있을 것 같습니다.
SetReplacementShader
SetReplacementShader를 간단하게 생각하면, shader version의 override 같은 것
SetReplacementShader 제 2 인수가 지정한 태그를 판단 조건
바꾸는 Shader와 material 지정한 Shader 태그의 값이 같으면
그대로 교체
예를 들어, 장면에 Cube와 Sphere가 있습니다.
각각 다른 shader 사용
DemoForShaderReplace.cginc
#ifndef _DEMO_FOR_SHADERREPLACE
#define _DEMO_FOR_SHADERREPLACE
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
#endif //_DEMO_FOR_SHADERREPLACE
DemoSphere.shader
Shader "Unlit/DemoSphere"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "Name"="Sphere" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "DemoForShaderReplace.cginc"
ENDCG
}
}
DemoCube.shader
Shader "Unlit/DemoCube"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "Name"="Cube" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "DemoForShaderReplace.cginc"
ENDCG
}
}
}
두 shader는 거의 동일하지만 유일한 차별은 맞춤 태그 Name 값이 다릅니다.
다음은 교체 shader
DemoReplace.shader
Shader "Unlit/DemoReplace"
{
SubShader
{
Tags { "Name"="Cube" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag_Replace
#include "DemoForShaderReplace.cginc"
fixed4 frag_Replace (v2f i) : SV_Target
{
return fixed4(1,0,0,1);
}
ENDCG
}
}
SubShader
{
Tags { "Name"="Sphere" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag_Replace
#include "DemoForShaderReplace.cginc"
fixed4 frag_Replace (v2f i) : SV_Target
{
return fixed4(0,1,0,1);
}
ENDCG
}
}
}
바꾸는 shader는 커스텀 태그 Name 마다
별도의 교체하려는 그리기를 정의합니다.
예는 Cube를 빨간색으로 Sphere를 녹색으로
마지막은 camera.SetReplacementShader 호출한다
Camera.main.SetReplacementShader (Shader.Find("Unlit/DemoReplace"), "Name");
결과
그림자 맵 참조
바닥에 그림자를 비추기 때문에
먼저 그림자 맵의 어디를 참조해야 하는지 알 필요
그림자 맵은 그림자 카메라(광시점)로 찍을 수 있는 결과
그러면 바닥도 그림자 카메라(광시점)로 찍어 그 묘화된 위치를 참조하면 좋다
메인 카메라로 그림자 카메라에 그려진 위치를 찾으려면
그림자 카메라의 뷰 행렬과 프로젝션 행렬 필요
Matrix4x4 view = shadowCamera.worldToCameraMatrix;
Matrix4x4 proj = GL.GetGPUProjectionMatrix (shadowCamera.projectionMatrix, true);
Shader.SetGlobalMatrix("_ProjectionViewProj", proj*view);
두 행렬을 곱합니다. 그 결과를 shader에 알립니다.
마지막으로 shader로 계산
Shader "Shadow/ProjectionShadowGround"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 uv_shadow : TEXCOORD1;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _ProjectionShadowMap;
float4x4 _ProjectionViewProj;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
float4 world = mul (unity_ObjectToWorld, v.vertex);
float4 pos = mul (_ProjectionViewProj, world);
o.uv_shadow = ComputeScreenPos (pos);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
fixed4 shadow = tex2D(_ProjectionShadowMap, (i.uv_shadow/i.uv_shadow.w).xy);
return lerp(col, shadow, shadow.a);
}
ENDCG
}
}
}
결과
리포지토리
github
Reference
이 문제에 관하여(프로젝션 텍스처 그림자를 제작해 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Sigma_Sama/items/e55097982eb82f6ecb58텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)