EIYOOO 2025-04-12 20:32 采纳率: 25%
浏览 3

Forward前向渲染交界线

求问为什么会出现明显交界线
如何修改

img


Shader "CS201/01Phong"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _AOMap ("AOMap", 2D) = "white" {}
        _SpecMask ("_SpecMask", 2D) = "white" {}
        _Shininess ("Shininess", Float) = 1
        _AmbientColor ("AmbientColor", Color) = (1,1,1,1)
        _SpecInt ("SpecInt", Float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Tags {"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase
            
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 normal_world : TEXCOORD1;
                float3 vertex_world : TEXCOORD2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _AOMap;
            sampler2D _SpecMask;
            float4 _LightColor0;
            float _Shininess;
            float4 _AmbientColor;
            float _SpecInt;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.normal_world = normalize(mul(unity_ObjectToWorld,float4(v.normal,0)).xyz);
                o.vertex_world = mul(v.vertex,unity_ObjectToWorld).xyz;
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                half4 base_color = tex2D(_MainTex, i.uv);
                half4 ao_color = tex2D(_AOMap, i.uv);
                half4 spec_mask = tex2D(_SpecMask, i.uv);
                
                half3 normal_world = normalize(i.normal_world);
                half3 light_world = normalize(_WorldSpaceLightPos0.xyz);
                half NdotL = dot(normal_world,light_world);
                half3 diffuse_color = max(0,NdotL) * _LightColor0.xyz * base_color.xyz;

                half3 reflect_light_world = normalize(reflect(-light_world,normal_world));
                half3 view_world = normalize(_WorldSpaceCameraPos.xyz - i.vertex_world);
                half RLdotV = dot(reflect_light_world,view_world);
                half3 specular_color = pow(max(0,RLdotV),_Shininess)* _LightColor0.xyz * _SpecInt * spec_mask.rgb;

                half3 final_color = (diffuse_color + specular_color + _AmbientColor.xyz) * ao_color;
                
                return half4(final_color, 1.0);
            }
            ENDCG
        }
        Pass
        {
            Tags {"LightMode" = "ForwardAdd"}
            blend One One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdadd
            
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 normal_world : TEXCOORD1;
                float3 vertex_world : TEXCOORD2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _AOMap;
            sampler2D _SpecMask;
            float4 _LightColor0;
            float _Shininess;
            float4 _AmbientColor;
            float _SpecInt;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.normal_world = normalize(mul(unity_ObjectToWorld,float4(v.normal,0)).xyz);
                o.vertex_world = mul(v.vertex,unity_ObjectToWorld).xyz;
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                half4 base_color = tex2D(_MainTex, i.uv);
                half4 ao_color = tex2D(_AOMap, i.uv);
                half4 spec_mask = tex2D(_SpecMask, i.uv);
                
                half3 normal_world = normalize(i.normal_world);
                #if defined  (DIRECTIONAL)
                half3 light_world = normalize(_WorldSpaceLightPos0.xyz);
                half attenuation = 1;
                #elif defined (POINT)
                half3 light_world = normalize(_WorldSpaceLightPos0.xyz - i.vertex_world);
                half distance = length(_WorldSpaceLightPos0.xyz - i.vertex_world);
                half range = 1.0 / unity_WorldToLight[0][0];
                float attenuation = saturate((range - distance) / range);
                #endif
                half NdotL = dot(normal_world,light_world);
                half3 diffuse_color = max(0,NdotL) * _LightColor0.xyz * base_color.xyz * attenuation;

                half3 reflect_light_world = normalize(reflect(-light_world,normal_world));
                half3 view_world = normalize(_WorldSpaceCameraPos.xyz - i.vertex_world);
                half RLdotV = dot(reflect_light_world,view_world);
                half3 specular_color = pow(max(0,RLdotV),_Shininess)* _LightColor0.xyz * _SpecInt * spec_mask.rgb * attenuation;

                half3 final_color = (diffuse_color + specular_color + _AmbientColor.xyz) * ao_color;
                
                return half4(final_color, 1.0);
            }
            ENDCG
        }
    }
}

  • 写回答

3条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2025-04-12 20:34
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 关键点分析
      - 从提供的Shader代码片段来看,出现明显交界线的原因可能是光照计算的问题。比如纹理采样、法线计算、光照模型的实现等方面可能存在瑕疵。
      - 仅给出了部分Shader代码,缺少光照计算等核心部分,难以准确判断具体原因。
    2. 解决方案
      - 检查纹理采样
      • 确保纹理采样的坐标计算正确。例如,如果使用UV坐标采样纹理,要保证在不同面片上UV坐标的连续性。
      • 示例代码(假设纹理采样在光照计算之前):
    fixed4 col = tex2D(_MainTex, i.uv);
    
    • 法线处理
      • 准确计算法线,并且在不同面片之间保持法线的一致性。如果法线计算不准确,会导致光照效果出现突变,从而产生交界线。
      • 例如,通过顶点法线插值来计算片元法线:
    v2f vert (appdata v)
    {
        v2f o;
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
        float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
        o.normal = UnityObjectToWorldNormal(v.normal);
        return o;
    }
    
    fixed4 frag (v2f i) : SV_Target
    {
        fixed3 worldNormal = normalize(UnityWorldToObject(i.normal));
        // 后续光照计算使用worldNormal
    }
    
    • 光照模型改进
      • 确保光照模型(如Phong模型)的计算正确。例如,在计算漫反射和镜面反射时,要正确考虑法线、光照方向和视角方向等因素。
      • 以简单的Phong光照模型为例:
    fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
    fixed3 reflectDir = normalize(reflect(-lightDir, worldNormal));
    
    fixed diff = max(dot(worldNormal, lightDir), 0);
    fixed spec = pow(max(dot(reflectDir, viewDir), 0), _Shininess);
    
    fixed4 col = tex2D(_MainTex, i.uv);
    col.rgb = col.rgb * _LightColor0.rgb * diff + _LightColor0.rgb * spec;
    
    1. 不同解决方案的优缺点
      - 检查纹理采样
      • 优点:相对容易检查和修改,是一个基础性的步骤,如果纹理采样有问题,能快速定位和解决。
      • 缺点:如果纹理采样本身没问题,可能无法解决根本问题,还需要进一步排查其他方面。
      • 法线处理
      • 优点:法线的准确性对光照效果影响很大,正确处理法线能有效改善光照的连续性,减少交界线。
      • 缺点:法线计算可能涉及到一些数学知识和图形学原理,需要一定的理解和调试。
      • 光照模型改进
      • 优点:直接针对光照效果进行优化,能从根本上解决光照导致的交界线问题。
      • 缺点:光照模型的实现较为复杂,需要对光照模型有深入的理解,调试难度相对较大。
    2. 总结
      - 出现明显交界线可能是纹理采样、法线处理或光照模型等方面的问题。可以通过检查纹理采样坐标、准确计算法线以及优化光照模型等步骤来尝试解决。在实际调试中,可能需要综合考虑多个因素,逐步排查找到问题的根源并进行修正。

    请注意,以上代码基于Unity ShaderLab,并且只是示例,具体实现可能需要根据完整的Shader需求进行调整。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    评论

报告相同问题?

问题事件

  • 创建了问题 4月12日