1
votes

I am trying to combine two shaders for my point cloud mesh. 1st shader is a geometry shader which has 1 texture and a way to control the point size.

2nd shader blends multiple textures based on the height of point in the mesh. I am very very new to shader coding and would like to combine the two.

If i literally copy paste them both into one file, then blending does not work. I would like to blend the textures and control the point cloud size.

I am very lost and would really appreciate any help.

1st Shader

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"
}

2nd Shader

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
    }
}
1
If i literally copy paste them both into one file Yeah, that's not how programming works. Each shader has a vert function and a frag function. You need to combine the math in these to do what you want at each vertex and each pixel. The second shader also has a geom function, but the first doesn't. Good luck. - Draco18s no longer trusts SE
I wish it did. So vert controls position and frag controls color? would I be correct in saying that? and I cannot have two verts and frags blocks in the same shader file? or is there an execution order? - Anurag Tiwari
Not really no. If anything controls position, its geom. vert is more for vertex color (where complex color calculations are done once per vertex, then each pixel is computed based on effective its barycenter and the 3 verts). Recommended reading: one two - Draco18s no longer trusts SE
geom controls position, vert and frag control color. and can target SV_Target or Color0 or Color1? color(texture) is what im after. - Anurag Tiwari
Recommended reading: one two great suggestions thank you - Anurag Tiwari

1 Answers

0
votes

The point cloud shader doesn't do much in the frag and vert functions. So, I thought maybe it would work to take out the frag and the vert code from the blending shader and putting it into the point cloud shader:

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
    }
}

I can't test this right now so there are probably some copy & paste errors, especially in having to rename & add members to the v2f/g2f structs. Let me know of any errors in the comments.