Unity Shader:Projective Texture Mapping

Projective-Texture-Mapping是用于投影一个texture到一个物体上。

大概过程是,通过设置一个摄像机在投影点上,获取投影摄像机的 VP 矩阵。在shader中利用该VP矩阵,来计算相对于投影机的uv坐标,从而利用该uv值来采样投影texture。

具体描述见:GPU 编程与CG 语言之阳春白雪下里巴人 中的12.3节。

Shader "Custom/Projective-Texture-Mapping" {
    Properties {
        _Tex ("Proj Tex", 2D) = "white" {}
        _Color ("Main Color", Color) = (1, 1, 1, 1)
        _Ck ("Color Coef", float) = 1
    }
    SubShader {
        Pass {
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag

            sampler2D _Tex;
            float4 _Color;
            float _Ck;
            float4x4 _texProjMat;

            struct v2f {
                float4 pos : POSITION;
                float4 shadowUV : TEXCOORD0;
                float3 normal : TEXCOORD1;
                float3 light : TEXCOORD2;
            };

            v2f vert(appdata_base v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                float4 worldPos = mul(_Object2World, v.vertex);
                o.shadowUV = mul(_texProjMat, worldPos);
                o.normal = v.normal;
                o.light = ObjSpaceLightDir(v.vertex);
                
                return o;
            }

            float4 frag(v2f i) : COLOR {
                float nl = dot(i.normal, i.light);

                float2 uv = float2(i.shadowUV.x, i.shadowUV.y) / i.shadowUV.w * 0.5 + 0.5;
                if (uv.x < 0 || uv.x > 1 || uv.y < 0 || uv.y > 1)
                    return _Ck * _Color * max(0, nl);

                float4 t = tex2D(_Tex, uv);

                return _Ck * t * _Color * max(0, nl);
            }

            ENDCG
        }
    } 
    FallBack "Diffuse"
}

效果如下:

该代码并没有考虑到物体的遮挡:plane面上处在cube后面的区域应该是没有纹理的。要做到这个效果,要加上深度比较的过程。

原文地址:https://www.cnblogs.com/foxianmo/p/4732889.html