自定义着色器不接收光线

Posted

技术标签:

【中文标题】自定义着色器不接收光线【英文标题】:Custom shader does not receive light 【发布时间】:2020-01-12 21:15:03 【问题描述】:

我制作了一个运行良好的网格着色器。但是,它根本不受任何光线的影响。只是为了让您了解具有着色器的平面:

它的尺寸是 1000x1x1000(足够宽) 使用任何其他材质显示阴影并启用投射阴影 使用 Unity 2019.3.0f3 通用渲染管线

The plane using custom grid shader(不接收光)

The plane using basic shader(接收光)

Custom grid shader code

我尝试了一些解决方案,包括在末尾添加 FallBack "Diffuse"#include 以及 TRANSFER_SHADOW 的东西。但是,这些也不起作用。

【问题讨论】:

【参考方案1】:

如果您希望光照信息,您需要告诉着色器如何处理光照信息。这是一个将漫反射光直接应用于网格着色器的反照率的示例:

Shader "Custom/Grid"

    Properties
    
        _GridThickness("Grid Thickness", Float) = 0.01
        _GridSpacing("Grid Spacing", Float) = 10.0
        _GridColour("Grid Colour", Color) = (0.5, 0.5, 0.5, 0.5)
        _BaseColour("Base Colour", Color) = (0.0, 0.0, 0.0, 0.0)
    

        SubShader
        Tags  "Queue" = "Transparent" 

        Pass 
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Tags 
        "LightMode" = "ForwardBase"
         // gets us access to main directional light


        CGPROGRAM

        // Define the vertex and fragment shader functions
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityStandardBRDF.cginc" // for shader lighting info and some utils
        #include "UnityStandardUtils.cginc" // for energy conservation

        // Access Shaderlab properties
        uniform float _GridThickness;
        uniform float _GridSpacing;
        uniform float4 _GridColour;
        uniform float4 _BaseColour;

        // Input into the vertex shader
        struct vertexInput
        
            float4 vertex : POSITION;
            float3 normal : NORMAL; // include normal info
        ;

        // Output from vertex shader into fragment shader
        struct vertexOutput
        
            float4 pos : SV_POSITION;
            float4 worldPos : TEXCOORD0;
            float3 normal : TEXCOORD1; // pass normals along
        ;

        // VERTEX SHADER
        vertexOutput vert(vertexInput input)
        
            vertexOutput output;
            output.pos = UnityObjectToClipPos(input.vertex);
            // Calculate the world position coordinates to pass to the fragment shader
            output.worldPos = mul(unity_ObjectToWorld, input.vertex);

            output.normal = input.normal; //get normal for frag shader from vert info

            return output;
        

        // FRAGMENT SHADER
        float4 frag(vertexOutput input) : COLOR
        
            float3 lightDir = _WorldSpaceLightPos0.xyz;
            float3 viewDir = normalize(_WorldSpaceCameraPos - input.worldPos);
            float3 lightColor = _LightColor0.rgb;

            float3 col;

            if (frac(input.worldPos.x / _GridSpacing) < _GridThickness || frac(input.worldPos.z / _GridSpacing) < _GridThickness)
                col = _GridColour;
            else
                col = _BaseColour;

            col *= lightColor * DotClamped(lightDir, input.normal); // apply diffuse light by angle of incidence

            return float4(col, 1);
        
        ENDCG
        
    

您应该check out these tutorials 了解更多关于照亮对象的其他方法。如果您希望他们发送到accept shadows,同样适用。

在此处设置 FallBack "Diffuse" 不会做任何事情,因为着色器没有“回退”,它完全按照您的编程方式运行,没有光照或阴影。

【讨论】:

谢谢!我使用的是通用渲染管道 (URP),所以我最终使用了 ShaderGraph,这要简单得多。

以上是关于自定义着色器不接收光线的主要内容,如果未能解决你的问题,请参考以下文章

unity能改默认的shader吗

Phong 着色器不起作用

着色器不工作

Opengl为啥这个着色器不起作用?

在顶点着色器中定位顶点后如何更新法线?

OpenGL片段着色器不照亮场景