首页 > 其他分享 >标准光照Shader

标准光照Shader

时间:2024-01-26 19:11:45浏览次数:28  
标签:bump Shader 标准 worldPos xy ans float4 光照 float3

思路

《Shader入门精要》看到第九章,试着结合前面的知识实现一个标准光照模型,采用Blin-Phong模型,分为三大部分环境光,漫反射,高光反射。实现过程中加入凹凸效果,阴影效果。注释部分是透明效果,采用透明度测试的方法实现。具体细节见代码

代码

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/StandardLightModel"
{
    Properties
    {
        _Color("Color Pint", Color) = (1, 1, 1, 1)
        _Specular("Specular", Color) = (1, 1, 1, 1)
        _MainTex("Main Tex", 2D) = "white"{}
        _BumpMap("Normal Map", 2D) = "bump"{}
        _BumpScale("Normal Scale", Float) = 1.0
        _Gloss("Gloss", range(0, 256)) = 20
        //_Cutoff("Cutoff", range(0, 1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        //Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "Autolight.cginc"

            float4 _Color;
            float4 _Specular;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;
            float _Gloss;
            //float _Cutoff;

            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float4 texcoord : TEXCOORD0;
            };
            struct v2f
            {
				float4 pos : SV_POSITION;
				float4 uv : TEXCOORD0;
				float4 TtoW0 : TEXCOORD1;  
				float4 TtoW1 : TEXCOORD2;  
				float4 TtoW2 : TEXCOORD3;
				SHADOW_COORDS(4)
            };

            v2f vert(a2v v)
            {
                v2f ans;
                ans.pos = UnityObjectToClipPos(v.vertex);

                ans.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                ans.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                ans.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                ans.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                ans.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

                TRANSFER_SHADOW(ans);
                return ans;
            }

            float4 frag(v2f v) : SV_Target
            {
                float3 worldPos = float3(v.TtoW0.w, v.TtoW1.w, v.TtoW2.w);
                float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                
                float3 bump = UnpackNormal(tex2D(_BumpMap, v.uv.zw));
                bump.xy *= _BumpScale;
                bump.z = sqrt(1.0 - max(0, dot(bump.xy, bump.xy)));
                bump = normalize(float3(dot(v.TtoW0.xyz, bump), dot(v.TtoW1.xyz, bump), dot(v.TtoW2.xyz, bump)));

                float4 texColor = tex2D(_MainTex, v.uv.xy);
                // TODO : 透明度测试
                // clip(texColor.a - _Cutoff);
                //
                
                float3 albedo = texColor.rgb * _Color.rgb;
                float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                float3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldLightDir, bump));

                float3 halfDir = normalize(worldLightDir + worldViewDir);
                float3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);

                UNITY_LIGHT_ATTENUATION(atten, v, worldPos);
                return float4(ambient + (diffuse + specular) * atten, 1.0);
            }
            ENDCG
        }

        Pass
        {
            Tags{"LightMode" = "ForwardAdd"}
            Blend One One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdadd
            #include "Lighting.cginc"
            #include "Autolight.cginc"

            float4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;

            struct a2v
            {
                float4 vertex : POSITION;
                float4 normal : NORMAL;
                float4 tangent : TANGENT;
                float4 texcoord : TEXCOORD0;
            };
            struct v2f
            {
				float4 pos : SV_POSITION;
				float4 uv : TEXCOORD0;
				float4 TtoW0 : TEXCOORD1;  
				float4 TtoW1 : TEXCOORD2;  
				float4 TtoW2 : TEXCOORD3;
				SHADOW_COORDS(4)
            };

            v2f vert(a2v v)
            {
                v2f ans;
                ans.pos = UnityObjectToClipPos(v.vertex);
                ans.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                ans.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
                ans.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                ans.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                ans.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

                TRANSFER_SHADOW(ans);
                return ans;
            }

            float4 frag(v2f v) : SV_Target
            {
                float3 worldPos = float3(v.TtoW0.w, v.TtoW1.w, v.TtoW2.w);
                float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                
                float3 bump = UnpackNormal(tex2D(_BumpMap, v.uv.zw));
                bump.xy *= _BumpScale;
                bump.z = sqrt(1.0 - max(0, dot(bump.xy, bump.xy)));
                bump = normalize(float3(dot(v.TtoW0.xyz, bump), dot(v.TtoW1.xyz, bump), dot(v.TtoW2.xyz, bump)));

                float4 texColor = tex2D(_MainTex, v.uv.xy);
                float3 albedo = texColor.rgb * _Color.rgb;
                float3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldLightDir, bump));


                UNITY_LIGHT_ATTENUATION(atten, v, worldPos);
                return float4(diffuse * atten, 1.0);
            }
            ENDCG
        }
    }
    // FallBack "Transparent/Cutout/VertexLit"
    FallBack "Specular"
}

参考

《Unity Shader 入门精要》

标签:bump,Shader,标准,worldPos,xy,ans,float4,光照,float3
From: https://www.cnblogs.com/monituihuo/p/17990510

相关文章

  • python之常用标准库-random
    1.randomdefrandom(self):"""Getthenextrandomnumberintherange[0.0,1.0)."""return(int.from_bytes(_urandom(7),'big')>>3)*RECIP_BPF翻译:获取0,1之间的随机浮点数1#!/usr/bin/python2importrandom3p......
  • python之常用标准库-时间
    1.time时间戳:它代表了从格林尼治时间1970年01月01日00时00分00秒(即北京时间的1970年01月01日08时00分00秒)开始到现在经过的总秒数。struct_time:用一个包含9个序列的元组组成(tm_year=2024,tm_mon=1,tm_mday=26,tm_hour=2,tm_min=49,tm_sec=56,tm_wday=4,tm_yday=26,......
  • WinDbg学习四(标准命令)
    命令都是实现在WinDBG内部的,执行这些命令时不需要加载任何扩展模块。大多数标准命令是一两个字符或者符号,只有version等少数命令除外。测试代码namespaceWinDbgConsoleSearch{internalclassProgram{privatestaticinti;......
  • 世界标准时间格式(yyyy-MM-dd'T'HH:mm:ss.SSS Z)处理
    世界标准时间格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ)处理        日前在接收他人传递过来的数据时碰到yyyy-MM-dd’T’HH:mm:ss.SSSZ格式的时间数据,因网上相关处理文档较少,所以特此记录一下我的处理方法以便日后翻阅。publicStringtimeFormat(Stringtime){Stri......
  • verilog预编译处理(ieee标准)
    `celldefine`endcelldefine在ieee中的描述如下:这两个指令用于将模块标记为单元模块,它们表示包含模块定义。某些PLI使用单元模块用于这些应用,如计算延迟。该命令可以出现在源代码描述中的任何地方。但是,推荐将其放在模块定义的外部。但是具体还不知道怎么用,没实践过。`def......
  • Higress 开源一周年:新版本,新标准,新工具,新征程
    作者:Higress团队历程回顾Higress开源一年时间,一共发布了18个release版本,收获了40多位社区贡献者和1800+star,上图是这一年过来达成的一些关键的里程碑。前面半年通过集成开源生态,打磨开源版本稳定性,并在发布1.0GA版本后,社区又马不停蹄发布了1.1和1.2两个重要版本,实......
  • Higress 开源一周年:新版本,新标准,新工具,新征程
    作者:Higress团队历程回顾Higress开源一年时间,一共发布了18个release版本,收获了40多位社区贡献者和1800+star,上图是这一年过来达成的一些关键的里程碑。前面半年通过集成开源生态,打磨开源版本稳定性,并在发布1.0GA版本后,社区又马不停蹄发布了1.1和1.2两个重要......
  • 正式发布!《ICPMM行业云平台运营管理能力成熟度》系列标准来了!
    近日,由中国信息通信研究院(简称中国信通院)主办的企业上云用云专项行动会在北京举行。在“行业云平台研讨会暨年度成果发布会”专题会议中,中国信通院携手天翼云与业界多家头部机构发布《ICPMM行业云平台运营管理能力成熟度》系列标准以及《行业云平台年度发展指数暨洞察报告(2023)》;天......
  • 正式发布!《ICPMM行业云平台运营管理能力成熟度》系列标准来了!
    近日,由中国信息通信研究院(简称中国信通院)主办的企业上云用云专项行动会在北京举行。在“行业云平台研讨会暨年度成果发布会”专题会议中,中国信通院携手天翼云与业界多家头部机构发布《ICPMM行业云平台运营管理能力成熟度》系列标准以及《行业云平台年度发展指数暨洞察报告(2023)》;天......
  • Shader实现翻书效果
    原理翻书这个过程可以看成是平面上的点都绕z轴旋转,但是直接这样写的话会出现问题。因为旋转轴是在中间的,所以我们在旋转之前要把点向左偏移5个单位这样旋转轴就到了最左边,然后再乘上旋转矩阵得到旋转之后的位置,再向右边偏移5个单位还原一下。这样实现的太生硬了,所以带入正弦函数......