• 漫反射实现 - UnityShader


    漫反射分为两种实现

    • 逐顶点漫反射(主要依靠顶点着色器,计算顶点的光照)
    • 逐片元漫反射(主要依靠片元着色器,计算片元的光照)

    使用的公式是兰伯特定律
    c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) cos ⁡ θ (1) c_{diffuse} = (c_{light} \cdot m_{diffuse})\cos{\theta}\tag{1} cdiffuse=(clightmdiffuse)cosθ(1)
    c o s θ = n ^ ⋅ l ^ (2) cos{\theta} = \widehat{n} \cdot \widehat{l}\tag{2} cosθ=n l (2)

    在兰伯特的基础上增加亮光(添加两个偏移)
    c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) ( n ^ ⋅ l ^ ∗ 0.5 + 0.5 ) (3) c_{diffuse} = (c_{light} \cdot m_{diffuse})( \widehat{n} \cdot \widehat{l} * 0.5 + 0.5)\tag{3} cdiffuse=(clightmdiffuse)(n l 0.5+0.5)(3)

    c l i g h t c_{light} clight 是光线的颜色, m d i f f u s e m_{diffuse} mdiffuse 是材质的颜色, c o s θ cos{\theta} cosθ是指法线与光线方向的角度

    逐顶点漫反射

    Shader "Lit/DiffuseLitShader1"
    {
        Properties
        {
            _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
        }
        SubShader
        {
            Pass
            {
                Tags { "LightMode" = "ForwardBase" }
                
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include 
                #include 
                #include 
    
                struct a2v
                {
                    float4 vertex : POSITION;
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    fixed3 color : COLOR0;
                };
    
                fixed4 _Diffuse;
    
                //逐顶点漫反射
                v2f vert(a2v v)
                {
                    v2f o;
                    //设置裁剪空间
                    o.pos = UnityObjectToClipPos(v.vertex.xyz);
                    
                    //得到环境光
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    
                    //从物体坐标的法向量变换到全局坐标的法向量
                    float3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
                    
                    //光照方向
                    fixed3 litDir = normalize(_WorldSpaceLightPos0.xyz);
                    
                    //兰伯特定律 c = (c * m) max(0, dot(n.normalize, l.normalize)) = (c * m) * cos
                    //fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, litDir));
    
                    //半兰伯特定理 c = (c * m)(0.5 * cos + 0.5), 可实现暗部增强亮光
                    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (dot(worldNormal, litDir) * 0.5 + 0.5);
                    
    
                    o.color = ambient + diffuse;
    
                    return o;
                }
    
                fixed4 frag(v2f i) : SV_Target
                {
                    return fixed4(i.color, 1.0);
                }
                ENDCG
            }
        }
        
        FallBack "Diffuse"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    逐片元漫反射

    Shader "Lit/DiffuseLitShader2"
    {
        Properties
        {
            _Diffuse("Diffuse", Color) = (1, 1, 1, 1)
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include 
                #include 
                #include 
    
                struct a2v
                {
                    float4 pos : POSITION;
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float4 worldNormal : TEXCOORD0;
                };
    
                fixed4 _Diffuse;
    
                v2f vert(a2v v)
                {
                    v2f o;
                    
                    //得到裁剪空间
                    o.pos = UnityObjectToClipPos(v.pos.xyz);
    
                    //获得世界空间的法向量,并保存在 uv 中
                    o.worldNormal = float4(UnityObjectToWorldNormal(v.normal.xyz), 1.0);
    
                    return o;
                }
    
                fixed4 frag(v2f i) : SV_Target
                {
                    //得到 ambient
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    
                    //gl 的 方向
                    float3 litDir = normalize(_WorldSpaceLightPos0.xyz);
    
                    //使用 兰伯特定律
                    //fixed3 diffuse = _LightColor0.rgb * _Diffuse * saturate(dot(i.worldNormal.xyz, litDir));
    
                    //使用 半兰伯特定律
                    fixed3 diffuse = _LightColor0.rgb * _Diffuse * (dot(i.worldNormal.xyz, litDir) * 0.5 + 0.5);
    
                    return fixed4(diffuse + ambient, 1.0);
                }
                ENDCG
            }
        }
        
        FallBack "Diffuse"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    来源为 Unity Shader 入门精要这本书 - 漫反射光照的实现

  • 相关阅读:
    java开发手册-05MySQL 数据库
    电源硬件设计----电源基础知识(3)
    2023-mac brew安装python最新版本,遇见的问题和处理方式
    大模型交互-超拟人合成
    「Spring Boot 系列」03. Spring Boot配置文件&yaml的基本语法
    JDBC读取Mysql数据列表
    基于googlenet深度学习网络的睁眼闭眼识别算法matlab仿真
    华为机试 - 目录删除
    lavaweb【初识后续问题的解决】
    插入排序和希尔排序
  • 原文地址:https://blog.csdn.net/m0_52361859/article/details/126921827