Unity Shader 顶点程序 实现漫反射与法向量的非等比转换

Shader "Custom/MyShader_Diffuse" {
    SubShader {
    Pass
        {
        CGPROGRAM
        #include "lighting.cginc"     //引入_WorldSpaceLightPos0 
        #pragma vertex vert
        #pragma fragment frag
        #pragma target 3.0

        struct output{                     //顶点输出
            float4 Pos:POSITION;
            float4 Col:COLOR;
        };

        output vert(in float4 ver:POSITION,in float3 verNormal:NORMAL)   //输入顶点位置和 法向量
        {
            output op;  
            op.Pos = mul(UNITY_MATRIX_MVP,ver);     //MVP变换

            float3 N = normalize(verNormal);          //规范化法向量  变为单位向量
            float3 L = normalize(_WorldSpaceLightPos0);    //规范化光照向量

            //① L = mul(_World2Object,float4(L,0)).xyz;   //重要:由于输入的顶点法向量为模型坐标不变,而光照向量为世界坐标也不变
            //② N=mul(_Object2World,float4(N,0)).xyz;     //故旋转时会光照异常,顶点坐标固定颜色不随光照变化
                                                        //解决方案: ①:将光照向量由世界坐标转换到模型坐标
                                                        //          ②:将顶点法向量由模型坐标变换到世界坐标

            N = mul(float4(N,0),_World2Object).xyz;     //以上两种方案解决了顶点随光照位置变化的问题
                                                        //但是还有一个问题待解决  "若将模型非等比缩放,法向量转换到世界坐标会异常,变化后的法向量将不再垂直于对应的表面"
                                                        //解决方案: 将模型法向量 * (((模型到世界变换矩阵)的逆矩阵)的转置矩阵)
                                                        // (模型到世界变换矩阵)的逆矩阵  ==>  世界到模型
                                                        //(世界到模型)的 转置矩阵 ==> 将CG中 mul()方法的2个参数换位置
                                                        //最终得到左边的N

            float dot_NL = saturate(dot(N,L));

            op.Col = _LightColor0 * dot_NL; 

            return op;
        }
        float4 frag(output ipt):COLOR
        {
             return ipt.Col + UNITY_LIGHTMODEL_AMBIENT;
        }
        ENDCG
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值