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
        }
    }
}
相关推荐
相信神话20214 小时前
3.2《酒魂》规则设计文档
游戏引擎·godot·2d游戏编程·godot4·2d游戏开发
Avalon71214 小时前
Unity3D响应式渲染UI框架UniVue
游戏·ui·unity·c#·游戏引擎
风酥糖15 小时前
Godot游戏练习01-第33节-新增会爆炸的敌人
游戏·游戏引擎·godot
ellis197015 小时前
Unity UI性能优化一之插件【Unity UI Optimization Tool】
unity·性能优化
Zik----18 小时前
Unity基础学习笔记(B站视频课整理)
unity·vr
郑寿昌1 天前
UE5与UE6在Lumen和Nanite的差异解析
游戏引擎·图形渲染·着色器
郝学胜-神的一滴1 天前
罗德里格斯旋转公式(Rodrigues‘ Rotation Formula)完整推导
c++·unity·godot·图形渲染·three.js·unreal
郑寿昌2 天前
UE6 AI加速Lumen光线追踪降噪技术解析
人工智能·游戏引擎
晴夏。2 天前
GAS下的网络同步的全面分析【超级全面】
游戏引擎·ue·gas·网络同步
田鸡_2 天前
Unity新输入系统(Input System)教学篇
unity·游戏引擎·游戏程序