【问题标题】:Combine point cloud shader and terrain blending shader结合点云着色器和地形混合着色器
【发布时间】:2019-10-16 01:35:35
【问题描述】:

我正在尝试为我的点云网格组合两个着色器。 第一个着色器是一个几何着色器,它有 1 个纹理和一种控制点大小的方法。

第二个着色器根据网格中点的高度混合多个纹理。 我对着色器编码非常陌生,想将两者结合起来。

如果我从字面上将它们复制粘贴到一个文件中,则混合不起作用。我想混合纹理并控制点云大小。

我很迷茫,非常感谢任何帮助。

第一个着色器

Shader "Custom/TerrainShaderAll"{
Properties{
    _DeepWater("DeepWater", 2D) = "white" {}
    _ShallowWater("ShallowWater", 2D) = "white" {}
    _Sand("Sand", 2D) = "white" {}
    _Grass("Grass", 2D) = "white"{}
    _Tree("Tree", 2D) = "white" {}
    _Rock("Rock", 2D) = "white" {}
    _Snow("Snow", 2D) = "white" {}
    _e1("e1", 2D) = "white" {}
    _e2("e2", 2D) = "white" {}
    _e3("e3", 2D) = "white" {}
    _WaterLevel("Water Level", Float) = 0
    _LayerSize("LayerSize", Float) = 20
    _BlendRange("BlendRange", Range(0,1.5)) = 0.1
}
    Subshader{
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            uniform sampler2D _DeepWater;
            uniform sampler2D _ShallowWater;
            uniform sampler2D _Sand;
            uniform sampler2D _Grass;
            uniform sampler2D _Tree;
            uniform sampler2D _Rock;
            uniform sampler2D _Snow;
            uniform sampler2D _e1;
            uniform sampler2D _e2;
            uniform sampler2D _e3;


            uniform float _WaterLevel;
            uniform float _LayerSize;
            uniform float _BlendRange;

            struct fragmentInput {
                float4 pos : SV_POSITION;
                float4 texcoord : TEXCOORD0;
                float4 blend: COLOR;
            };

            fragmentInput vert(appdata_base v)
            {
                float NumOfTextures = 10;
                fragmentInput o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.texcoord = v.texcoord;

                float MinValue = _WaterLevel - (NumOfTextures - 1) * _LayerSize;
                float MaxValue = (_WaterLevel + _LayerSize);
                float Blend = MaxValue - v.vertex.z;
                Blend = clamp(Blend / (NumOfTextures * _LayerSize), 0, 1);

                o.blend.xyz = 0;
                o.blend.w = Blend;
                return o;
            }


            inline float CalculateBlend(float TextureFloat)
            {
                return 1 - clamp((1 - TextureFloat) / _BlendRange, 0, 1);
            }

            inline float4 DoBlending(float TextureID, float TextureFloat, fixed4 BaseTexture, fixed4 BlendTexture)
            {
                float Blend = CalculateBlend(clamp(TextureFloat - TextureID, 0, 1));
                return lerp(BaseTexture, BlendTexture, Blend);
            }

            float4 frag(fragmentInput i) : COLOR0
            {
                float NumOfTextures = 10;
                float TextureFloat = i.blend.w * NumOfTextures;

                if (TextureFloat < 1)
                {
                    fixed4 DeepWaterColor = tex2D(_DeepWater, i.texcoord);
                    fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.texcoord);

                    return DoBlending(0, TextureFloat, DeepWaterColor, ShallowWaterColor);
                }
                if (TextureFloat < 2)
                {
                    fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.texcoord);
                    fixed4 SandColor = tex2D(_Sand, i.texcoord);

                    return DoBlending(1, TextureFloat, ShallowWaterColor, SandColor);
                }
                if (TextureFloat < 3)
                {
                    fixed4 SandColor = tex2D(_Sand, i.texcoord);
                    fixed4 GrassColor = tex2D(_Grass, i.texcoord);

                    return DoBlending(2, TextureFloat, SandColor, GrassColor);
                }
                if (TextureFloat < 4)
                {
                    fixed4 GrassColor = tex2D(_Grass, i.texcoord);
                    fixed4 TreeColor = tex2D(_Tree, i.texcoord);

                    return DoBlending(3, TextureFloat, GrassColor, TreeColor);
                }
                if (TextureFloat < 5)
                {
                    fixed4 TreeColor = tex2D(_Tree, i.texcoord);
                    fixed4 RockColor = tex2D(_Rock, i.texcoord);

                    return DoBlending(4, TextureFloat, TreeColor, RockColor);
                }
                if (TextureFloat < 6)
                {
                    fixed4 RockColor = tex2D(_Rock, i.texcoord);
                    fixed4 SnowColor = tex2D(_Snow, i.texcoord);

                    return DoBlending(5, TextureFloat, RockColor, SnowColor);
                }
                if (TextureFloat < 7)
                {
                    fixed4 SnowColor = tex2D(_Snow, i.texcoord);
                    fixed4 e1Color = tex2D(_e1, i.texcoord);

                    return DoBlending(6, TextureFloat, SnowColor, e1Color);
                }
                if (TextureFloat < 8)
                {
                    fixed4 e1Color = tex2D(_e1, i.texcoord);
                    fixed4 e2Color = tex2D(_e2, i.texcoord);

                    return DoBlending(7, TextureFloat, e1Color, e2Color);
                }
                if (TextureFloat < 9)
                {
                    fixed4 e2Color = tex2D(_e2, i.texcoord);
                    fixed4 e3Color = tex2D(_e3, i.texcoord);

                    return DoBlending(8, TextureFloat, e2Color, e3Color);
                }

                fixed4 e3Color = tex2D(_e3, i.texcoord);

                return e3Color;

                fixed4 DeepWaterColor = tex2D(_DeepWater, i.texcoord);
                fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.texcoord);

                return lerp(DeepWaterColor, ShallowWaterColor, i.blend.w);

            }
        ENDCG
        }
    }
    FallBack "Diffuse"
}

第二个着色器

Shader "Custom/PointCloudGeom" {
Properties {
    [NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
    [NoScaleOffset]_UVMap ("UV", 2D) = "white" {}
    _PointSize("Point Size", Float) = 4.0
    _Color ("PointCloud Color", Color) = (1, 1, 1, 1)
    [Toggle(USE_DISTANCE)]_UseDistance ("Scale by distance?", float) = 0
}

SubShader
{
    Cull Off
    Pass 
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma geometry geom
        #pragma fragment frag
        #pragma shader_feature USE_DISTANCE
        #include "UnityCG.cginc"

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

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

        float _PointSize;
        fixed4 _Color;

        sampler2D _MainTex;
        float4 _MainTex_TexelSize;

        sampler2D _UVMap;
        float4 _UVMap_TexelSize;


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

        [maxvertexcount(4)]
        void geom(point v2f i[1], inout TriangleStream<g2f> triStream)
        {
            g2f o;
            float4 v = i[0].vertex;
            v.y = -v.y;

            // TODO: interpolate uvs on quad
            float2 uv = i[0].uv;
            float2 p = _PointSize * 0.001;
            p.y *= _ScreenParams.x / _ScreenParams.y;

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(-p.x, p.y, 0, 0);
            #else
            o.vertex += float4(-p.x, p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(-p.x, -p.y, 0, 0);
            #else
            o.vertex += float4(-p.x, -p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(p.x, p.y, 0, 0);
            #else
            o.vertex += float4(p.x, p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(p.x, -p.y, 0, 0);
            #else
            o.vertex += float4(p.x, -p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

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

        fixed4 frag (g2f i) : SV_Target
        {
            float2 uv = tex2D(_UVMap, i.uv);
            if(any(uv <= 0 || uv >= 1))
                discard;
            // offset to pixel center
            uv += 0.5 * _MainTex_TexelSize.xy;
            return tex2D(_MainTex, uv) * _Color;
        }
        ENDCG
    }
}

【问题讨论】:

  • If i literally copy paste them both into one file 是的,编程不是这样的。每个着色器都有一个vert 函数和一个frag 函数。你需要结合这些数学来在每个 vertex 和每个像素上做你想做的事情。第二个着色器也有一个 geom 函数,但第一个没有。祝你好运。
  • 希望如此。那么vert 控制位置,frag 控制颜色?我这样说对吗?我不能在同一个着色器文件中有两个顶点和碎片块?还是有执行令?
  • 不是真的没有。如果有任何东西控制位置,它的geomvert 更多用于顶点颜色(其中每个顶点进行一次复杂的颜色计算,然后根据有效的重心和 3 个顶点计算每个像素)。推荐阅读:onetwo
  • geom 控制位置,vertfrag 控制颜色。并且可以定位 SV_Target 或 Color0 或 Color1? color(texture) 是我所追求的。
  • Recommended reading: one two 很棒的建议,谢谢

标签: unity3d shader hlsl


【解决方案1】:

点云着色器在 frag 和 vert 函数中的作用不大。所以,我想也许可以从混合着色器中取出片段和垂直代码并将其放入点云着色器中:

Shader "Custom/PointCloudTerrain" {
Properties {
    _DeepWater("DeepWater", 2D) = "white" {}
    _ShallowWater("ShallowWater", 2D) = "white" {}
    _Sand("Sand", 2D) = "white" {}
    _Grass("Grass", 2D) = "white"{}
    _Tree("Tree", 2D) = "white" {}
    _Rock("Rock", 2D) = "white" {}
    _Snow("Snow", 2D) = "white" {}
    _e1("e1", 2D) = "white" {}
    _e2("e2", 2D) = "white" {}
    _e3("e3", 2D) = "white" {}
    _WaterLevel("Water Level", Float) = 0
    _LayerSize("LayerSize", Float) = 20
    _BlendRange("BlendRange", Range(0,1.5)) = 0.1


    [NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
    [NoScaleOffset]_UVMap ("UV", 2D) = "white" {}
    _PointSize("Point Size", Float) = 4.0
    _Color ("PointCloud Color", Color) = (1, 1, 1, 1)
    [Toggle(USE_DISTANCE)]_UseDistance ("Scale by distance?", float) = 0
}

SubShader
{
    Cull Off
    Pass 
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma geometry geom
        #pragma fragment frag
        #pragma shader_feature USE_DISTANCE
        #include "UnityCG.cginc"

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

        struct v2f
        {

            float4 vertex : SV_POSITION;
            float2 uv : TEXCOORD0;
            float4 blend: COLOR;

        };

            uniform sampler2D _DeepWater;
            uniform sampler2D _ShallowWater;
            uniform sampler2D _Sand;
            uniform sampler2D _Grass;
            uniform sampler2D _Tree;
            uniform sampler2D _Rock;
            uniform sampler2D _Snow;
            uniform sampler2D _e1;
            uniform sampler2D _e2;
            uniform sampler2D _e3;


            uniform float _WaterLevel;
            uniform float _LayerSize;
            uniform float _BlendRange;


        float _PointSize;
        fixed4 _Color;

        sampler2D _MainTex;
        float4 _MainTex_TexelSize;

        sampler2D _UVMap;
        float4 _UVMap_TexelSize;


        struct g2f
        {
            float4 vertex : SV_POSITION;
            float2 uv : TEXCOORD0;
            float4 blend: COLOR;
        };

        [maxvertexcount(4)]
        void geom(point v2f i[1], inout TriangleStream<g2f> triStream)
        {
            g2f o;
            float4 v = i[0].vertex;
            v.y = -v.y;

            // TODO: interpolate uvs on quad
            float2 uv = i[0].uv;
            float2 p = _PointSize * 0.001;
            p.y *= _ScreenParams.x / _ScreenParams.y;

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(-p.x, p.y, 0, 0);
            #else
            o.vertex += float4(-p.x, p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(-p.x, -p.y, 0, 0);
            #else
            o.vertex += float4(-p.x, -p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(p.x, p.y, 0, 0);
            #else
            o.vertex += float4(p.x, p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

            o.vertex = UnityObjectToClipPos(v);
            #ifdef USE_DISTANCE
            o.vertex += float4(p.x, -p.y, 0, 0);
            #else
            o.vertex += float4(p.x, -p.y, 0, 0) * o.vertex.w;
            #endif
            o.uv = uv;
            triStream.Append(o);

        }

        inline float CalculateBlend(float TextureFloat)
        {
            return 1 - clamp((1 - TextureFloat) / _BlendRange, 0, 1);
        }

        inline float4 DoBlending(float TextureID, float TextureFloat, fixed4 BaseTexture, fixed4 BlendTexture)
        {
            float Blend = CalculateBlend(clamp(TextureFloat - TextureID, 0, 1));
            return lerp(BaseTexture, BlendTexture, Blend);
        }

        v2f vert (appdata v)
        {
                float NumOfTextures = 10;
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;

                float MinValue = _WaterLevel - (NumOfTextures - 1) * _LayerSize;
                float MaxValue = (_WaterLevel + _LayerSize);
                float Blend = MaxValue - v.vertex.z;
                Blend = clamp(Blend / (NumOfTextures * _LayerSize), 0, 1);

                o.blend.xyz = 0;
                o.blend.w = Blend;
                return o;
        }

        fixed4 frag (g2f i) : SV_Target
        {
            float NumOfTextures = 10;
            float TextureFloat = i.blend.w * NumOfTextures;

            if (TextureFloat < 1)
            {
                fixed4 DeepWaterColor = tex2D(_DeepWater, i.uv);
                fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.uv);

                return DoBlending(0, TextureFloat, DeepWaterColor, ShallowWaterColor);
            }
            if (TextureFloat < 2)
            {
                fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.uv);
                fixed4 SandColor = tex2D(_Sand, i.uv);

                return DoBlending(1, TextureFloat, ShallowWaterColor, SandColor);
            }
            if (TextureFloat < 3)
            {
                fixed4 SandColor = tex2D(_Sand, i.uv);
                fixed4 GrassColor = tex2D(_Grass, i.uv);

                return DoBlending(2, TextureFloat, SandColor, GrassColor);
            }
            if (TextureFloat < 4)
            {
                fixed4 GrassColor = tex2D(_Grass, i.uv);
                fixed4 TreeColor = tex2D(_Tree, i.uv);

                return DoBlending(3, TextureFloat, GrassColor, TreeColor);
            }
            if (TextureFloat < 5)
            {
                fixed4 TreeColor = tex2D(_Tree, i.uv);
                fixed4 RockColor = tex2D(_Rock, i.uv);

                return DoBlending(4, TextureFloat, TreeColor, RockColor);
            }
            if (TextureFloat < 6)
            {
                fixed4 RockColor = tex2D(_Rock, i.uv);
                fixed4 SnowColor = tex2D(_Snow, i.uv);

                return DoBlending(5, TextureFloat, RockColor, SnowColor);
            }
            if (TextureFloat < 7)
            {
                fixed4 SnowColor = tex2D(_Snow, i.uv);
                fixed4 e1Color = tex2D(_e1, i.uv);

                return DoBlending(6, TextureFloat, SnowColor, e1Color);
            }
            if (TextureFloat < 8)
            {
                fixed4 e1Color = tex2D(_e1, i.uv);
                fixed4 e2Color = tex2D(_e2, i.uv);

                return DoBlending(7, TextureFloat, e1Color, e2Color);
            }
            if (TextureFloat < 9)
            {
                fixed4 e2Color = tex2D(_e2, i.uv);
                fixed4 e3Color = tex2D(_e3, i.uv);

                return DoBlending(8, TextureFloat, e2Color, e3Color);
            }

            fixed4 e3Color = tex2D(_e3, i.uv);

            return e3Color;

            fixed4 DeepWaterColor = tex2D(_DeepWater, i.uv);
            fixed4 ShallowWaterColor = tex2D(_ShallowWater, i.uv);

            return lerp(DeepWaterColor, ShallowWaterColor, i.blend.w);
        }
        ENDCG
    }
}

我现在无法对此进行测试,因此可能存在一些复制和粘贴错误,尤其是在必须重命名和添加成员到 v2f/g2f 结构时。让我知道 cmets 中的任何错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    相关资源
    最近更新 更多