unity粗糙、高光、光泽度调节shader记录

记录一个URP中的带粗糙、高光、光泽度调节的shader,方便之后作为扩展的基础使用。

csharp 复制代码
// OrenNayarURP.shader
Shader "Custom/OrenNayarURP"
{
    Properties
    {
        [MainTexture] _BaseMap("Texture", 2D) = "white" {}
        [MainColor] _BaseColor("Color", Color) = (1,1,1,1)
        //粗糙
        _Roughness("Roughness", Range(0, 1)) = 0.5
        //高光
        _Specular("Specular", Range(0, 1)) = 0.0
        //光泽
        _Gloss("Gloss", Range(0, 1)) = 0.5
    }
    
    SubShader
    {
        Tags 
        { 
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "IgnoreProjector" = "True"
        }
        
        Pass
        {
            Name "ForwardLit"
            Tags { "LightMode" = "UniversalForward" }
            
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _SHADOWS_SOFT
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            
            struct Attributes
            {
                float4 positionOS   : POSITION;
                float3 normalOS     : NORMAL;
                float2 uv           : TEXCOORD0;
            };
            
            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                float2 uv           : TEXCOORD0;
                float3 normalWS     : TEXCOORD1;
                float3 positionWS   : TEXCOORD2;
                float3 viewDirWS    : TEXCOORD3;
            };
            
            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);
            float4 _BaseMap_ST;
            
            CBUFFER_START(UnityPerMaterial)
                float4 _BaseColor;
                float _Roughness;
                float _Specular;
                float _Gloss;
            CBUFFER_END
            
            // Oren-Nayar BRDF 函数
            float OrenNayarDiffuse(
                float3 lightDir,
                float3 viewDir,
                float3 normal,
                float roughness)
            {
                float NdotL = saturate(dot(normal, lightDir));
                float NdotV = saturate(dot(normal, viewDir));
                
                if (NdotL <= 0 || NdotV <= 0)
                    return 0.0;
                
                float sigma = roughness * 1.570796; // π/2
                float sigma2 = sigma * sigma;
                
                float A = 1.0 - 0.5 * (sigma2 / (sigma2 + 0.33));
                float B = 0.45 * (sigma2 / (sigma2 + 0.09));
                
                float3 lightProj = normalize(lightDir - normal * NdotL);
                float3 viewProj = normalize(viewDir - normal * NdotV);
                
                float cosPhi = dot(lightProj, viewProj);
                cosPhi = saturate(cosPhi);
                
                float thetaL = acos(NdotL);
                float thetaV = acos(NdotV);
                float alpha = max(thetaL, thetaV);
                float beta = min(thetaL, thetaV);
                
                float L1 = A;
                float L2 = B * cosPhi * sin(alpha) * tan(beta);
                
                return NdotL * (L1 + L2);
            }
            
            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                
                VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
                OUT.positionHCS = positionInputs.positionCS;
                OUT.positionWS = positionInputs.positionWS;
                
                VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS);
                OUT.normalWS = normalInputs.normalWS;
                
                OUT.viewDirWS = GetWorldSpaceNormalizeViewDir(OUT.positionWS);
                OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
                
                return OUT;
            }
            
            half4 frag(Varyings IN) : SV_Target
            {
                // 准备数据
                float3 normalWS = normalize(IN.normalWS);
                float3 viewDirWS = normalize(IN.viewDirWS);
                
                // 获取主光源
                Light mainLight = GetMainLight();
                float3 lightDirWS = normalize(mainLight.direction);
                
                // Oren-Nayar 漫反射
                float diffuse = OrenNayarDiffuse(lightDirWS, viewDirWS, normalWS, _Roughness);
                float3 diffuseColor = diffuse * mainLight.color * _BaseColor.rgb;
                
                // 简单高光
                float3 halfVec = normalize(lightDirWS + viewDirWS);
                float specular = pow(saturate(dot(normalWS, halfVec)), _Gloss * 128) * _Specular;
                float3 specularColor = specular * mainLight.color;
                
                // 纹理采样
                float4 texColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
                
                // 组合颜色
                float3 finalColor = (diffuseColor + specularColor) * texColor.rgb;
                
                return half4(finalColor, 1.0);
            }
            ENDHLSL
        }
    }
}
相关推荐
星夜泊客4 小时前
Unity UI 渲染与 Rebuild 机制简易解析
unity·游戏引擎
一线灵6 小时前
跨平台游戏引擎 Axmol-2.11.1 发布
游戏引擎
qiminixi15 小时前
Unity 6000下载
unity·unity 6000·unity 6000下载
CreasyChan19 小时前
Unity Shader 入门指南
unity·c#·游戏引擎·shader
漂视数字孪生世界20 小时前
Unity团结引擎的前世今生
unity·游戏引擎·数字孪生
心前阳光1 天前
Unity通过ScriptableObject学习访问者模式
学习·unity·访问者模式
fcm191 天前
unity之重新导入TMP
unity
心疼你的一切1 天前
【技术创作的璀璨盛宴——2025年CSDN博客之星总评选深度总结】
microsoft·unity·游戏引擎·游戏程序·csdn·博客之星
心前阳光1 天前
Unity批量实例化UI后设置UI位置失效
unity