Unity实现物体移动过的平面区域会有凹陷的痕迹,就像耕地的感觉

目前使用代码只做到了物体行驶过的地方,通过修改贴图像素颜色,行成一条灰色的痕迹,求一个利用shader实现让灰色区域的凹陷下去的效果,谢谢

引用 皆我百晓生 小程序回复内容作答:
要在Unity中实现灰色区域凹陷的效果,你可以使用Shader来操作顶点和法线,使其看起来像是被物体踩踏过的凹陷地形。

下面是一个简单的示例Shader代码,可以让灰色区域凹陷下去:

Shader "Custom/DentedTerrain" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _IndentDepth ("Indent Depth", Range(0, 1)) = 0.5
        _IndentIntensity ("Indent Intensity", Range(0, 1)) = 0.5
    }

    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float depth : TEXCOORD1;
            };

            sampler2D _MainTex;
            float _IndentDepth;
            float _IndentIntensity;

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.vertex.xy * 0.5 + 0.5;
                o.depth = length(float2(v.vertex.x, v.vertex.y)) * _IndentIntensity;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                float4 texColor = tex2D(_MainTex, i.uv);
                texColor.rgb -= i.depth * _IndentDepth;
                return texColor;
            }
            ENDCG
        }
    }
}

这段Shader代码创建了一个自定义的Shader,并接受一个主贴图、凹陷深度和凹陷强度作为属性。在顶点处理函数vert中,根据顶点位置计算出凹陷的深度,并存储在顶点的depth变量中。在片段处理函数frag中,根据depth变量的值来调整贴图的颜色,形成凹陷的效果。

要使用这个Shader,你可以创建一个材质,并将其指定为你的地形的材质。然后在材质上设置好贴图、凹陷深度和凹陷强度的参数。

请注意,这只是一个简单的示例,你可能需要根据你的需求进行调整和优化。如果你对Shader不熟悉,建议学习一些基础的Shader知识,以便更好地理解和调整这段代码。

希望这可以帮助你实现灰色区域凹陷的效果!

给你个参考


Shader "Custom/ConcaveShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Depth ("Depth", Range(0, 1)) = 0.1
    }

    SubShader
    {
        Tags { "Queue"="Transparent" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _Depth;

            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                // Sample the main texture
                half4 col = tex2D(_MainTex, i.uv);

                // Calculate depth based on the grayscale value
                half depth = col.r * _Depth;

                // Displace the vertex position based on depth
                i.vertex.xy += i.vertex.xy * depth;

                return col;
            }
            ENDCG
        }
    }
}

参考结合GPT4.0、文心一言,如有帮助,恭请采纳。

可以使用一个简单的片元着色器(fragment shader)来模拟这个效果。
在Unity中,你可以创建一个自定义的Shader,并在片元着色器中对每个片元的颜色进行修改。下面是一个简单的例子:

Shader "Custom/DepressionShader"  
{  
    Properties  
    {  
        _MainTex ("Texture", 2D) = "white" {}  
        _DepressionColor ("Depression Color", Color) = (0,0,0,0)  
    }  
    SubShader  
    {  
        Tags { "RenderType"="Opaque" }  
        LOD 100  
  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            // 这里可以添加其他需要的包含和指令  
  
            struct appdata  
            {  
                float4 vertex : POSITION;  
                float2 uv : TEXCOORD0;  
            };  
  
            struct v2f  
            {  
                float2 uv : TEXCOORD0;  
                float4 vertex : SV_POSITION;  
            };  
  
            sampler2D _MainTex;  
            float4 _MainTex_ST;  
            float4 _DepressionColor;  
  
            v2f vert (appdata v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);  
                return o;  
            }  
  
            fixed4 frag (v2f i) : SV_Target  
            {  
                // sample the texture  
                fixed4 col = tex2D(_MainTex, i.uv);  
                // if the texture color is depression color, make it darker  
                if (col.rgb == _DepressionColor.rgb) {  
                    col.rgb -= 0.1;  
                }  
                return col;  
            }  
            ENDCG  
        }  
    }  
}

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
要实现这个效果,你可以使用Unity的ShaderLab语言编写一个自定义的Shader。以下是一个简单的实现方法:

  1. 首先,创建一个新的Shader文件,例如PlaneScratch.shader
  2. 在Shader中,定义一个二维纹理_MainTex,用于接收物体行驶过的区域的贴图。
  3. 定义一个二维向量_NormalMap,用于接收法线贴图。
  4. 在顶点着色器中,计算物体行驶过的区域的高度值,并将其存储在一个临时变量中。
  5. 在片段着色器中,根据高度值和法线贴图,计算凹陷效果。
  6. 将计算出的凹陷效果应用到物体的表面材质上。

以下是一个简单的Shader代码示例:

Shader "Custom/PlaneScratch" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _NormalMap ("Normal Map", 2D) = "bump" {}
    }

    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}
        LOD 100

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        sampler2D _NormalMap;

        struct Input {
            float2 uv_MainTex;
            float3 worldPos;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            // Sample the texture
            half4 c = tex2D(_MainTex, IN.uv_MainTex);

            // Calculate the height value based on the texture
            float height = c.g * c.a;

            // Sample the normal map
            half3 n = tex2D(_NormalMap, IN.uv_MainTex).rgb;

            // Calculate the depression effect based on the height and normal map
            float depression = max(0, -height * dot(n.xyz, normalize(-IN.worldPos)));

            // Apply the depression effect to the surface
            o.Albedo = c.rgb - depression;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

将这个Shader应用到你的物体表面材质上,然后在Unity中运行场景,你应该能看到物体行驶过的区域产生了凹陷的效果。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢



Shader "Custom/ConcaveShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Depth ("Depth", Range(0, 1)) = 0.1
    }
    SubShader
    {
        Tags { "Queue"="Transparent" }
        LOD 100
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            float _Depth;
            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            half4 frag (v2f i) : SV_Target
            {
                // Sample the main texture
                half4 col = tex2D(_MainTex, i.uv);
                // Calculate depth based on the grayscale value
                half depth = col.r * _Depth;
                // Displace the vertex position based on depth
                i.vertex.xy += i.vertex.xy * depth;
                return col;
            }
            ENDCG
        }
    }
}

调整凹陷区域的灰度值

援引文心一言:
你可以通过创建一个自定义的Shader来实现这个效果。在Unity中,Shader可以用来定义材料的渲染效果。下面是一个简单的Shader的实例,它可以用来实现凹陷的效果。

首先创建一个新的Shader,例如命名为"DepressionShader",并选择一个合适的渲染队列(比如2500)。




csharp
Shader "Custom/DepressionShader" {  
    Properties {  
        _MainTex ("Texture", 2D) = "white" {}  
        _Depth ("Depth", Range(0, 1)) = 0.5  
    }  
    SubShader {  
        Tags { "RenderType"="Opaque" "Queue"="Geometry+2500" }  
        LOD 100  
  
        Pass {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            // 这里可以添加其他需要的包含和指令  
  
            struct appdata {  
                float4 vertex : POSITION;  
                float2 uv : TEXCOORD0;  
            };  
  
            struct v2f {  
                float2 uv : TEXCOORD0;  
                float4 vertex : SV_POSITION;  
            };  
  
            sampler2D _MainTex;  
            float _Depth;  
  
            v2f vert (appdata v) {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                o.uv = v.uv;  
                return o;  
            }  
  
            fixed4 frag (v2f i) : SV_Target {  
                fixed4 tex = tex2D(_MainTex, i.uv);  
                float depth = tex.r; // 假设我们的深度信息在红色通道  
                return lerp(tex, fixed4(0.5, 0.5, 0.5, 1), smoothstep(0.5 - _Depth, 0.5 + _Depth, depth));  
            }  
            ENDCG  
        }  
    }  
}


这个Shader基于主纹理(_MainTex)和深度参数(_Depth)对像素进行混合,以实现凹陷效果。你可以通过修改这些参数来改变效果。其中,深度参数决定了凹陷的程度。值越大,凹陷程度越小;值越小,凹陷程度越大。凹陷部分的颜色是灰色(0.5, 0.5, 0.5)。你可以根据需要修改这个颜色。

要使用这个Shader,你需要创建一个新的材质,并将Shader应用到这个材质上。然后,你可以将这个材质应用到你的物体上。在运行时,物体会显示出凹陷效果。记住,你的主纹理应该包含一个深度通道,这样Shader才能正确地混合像素。

结合GPT给出回答如下请题主参考
以下是一个实现凹陷效果的shader示例,代码注释已加入:

Shader "Custom/TrackShader" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _TrackTex ("Track Texture", 2D) = "white" {}
        _TrackColor ("Track Color", Color) = (0.2, 0.2, 0.2, 1.0)
        _TrackWidth ("Track Width", Range(0.01, 0.1)) = 0.05
        _TrackDepth ("Track Depth", Range(0.02, 0.1)) = 0.05
    }
    SubShader {
        Pass {
            Tags { "RenderType"="Opaque" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            
            // Shader uniforms
            sampler2D _MainTex;
            sampler2D _TrackTex;
            float4 _TrackColor;
            float _TrackWidth;
            float _TrackDepth;
            float _Time;
            
            // Vertex shader
            v2f vert (appdata v) {
                v2f o;
                // Calculate vertex position
                o.vertex = UnityObjectToClipPos(v.vertex);
                // Set UV coordinate
                o.uv = v.uv;
                return o;
            }
            
            // Fragment shader
            fixed4 frag (v2f i) : SV_Target {
                // Get texture color
                fixed4 col = tex2D(_MainTex, i.uv);
                // Get track texture color
                fixed4 trackCol = tex2D(_TrackTex, i.uv);
                // Calculate grayscale value
                float gray = dot(trackCol.rgb, float3(0.299, 0.587, 0.114));
                // Determine if pixel is in track area
                float inTrack = step(gray, 0.5);
                // Calculate track depth
                float depth = (1.0 - gray) * _TrackDepth;
                // Calculate track width offset
                float2 offset = normalize(i.uv - 0.5) * _TrackWidth * inTrack;
                // Adjust depth based on time for animation effect
                depth += sin(_Time * 10.0 + i.uv.x * 20.0) * 0.01;
                // Calculate final color by blending track color and original color with depth
                fixed4 finalCol = lerp(col, _TrackColor, depth) * inTrack;
                // Return final color
                return finalCol;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

使用方法:

  1. 将上述代码保存为一个名为“TrackShader.shader”的文件,导入Unity项目中

  2. 在需要应用该shader的Material上选择该shader

  3. 在Shader Inspector中设置Track Texture为包含灰色轨迹的贴图,设置Track Width为轨迹宽度,设置Track Depth为轨迹的凹陷深度

  4. 运行场景,物体在移动过程中将在轨迹处产生凹陷效果

注意事项:

  1. 该shader目前只支持单通道灰度图轨迹,如需使用彩色轨迹请自行修改相关代码

  2. 该shader使用了_DeltaTime变量做动画效果,因此需要使用Time节点向shader传递时间信息。可以在Material中勾选“Use Global Time”选项或手动向shader传递时间信息

兄弟们,问题已经解决了,借鉴的是InkPainter插件里的案例五