2D metaball liquid effect - how to feed output of one rendering pass as input to another shader

Posted by Guye Incognito on Game Development See other posts from Game Development or by Guye Incognito
Published on 2014-06-04T17:18:52Z Indexed on 2014/06/04 21:45 UTC
Read the original article Hit count: 343

Filed under:
|
|

I'm attempting to make a shader for unity3d web project. I want to implement something like in the great answer by DMGregory in this question. in order to achieve a final look something like this.. enter image description here

Its metaballs with specular and shading.
The steps to make this shader are.
1. Convert the feathered blobs into a heightmap.
2. Generate a normalmap from the heightmap
3. Feed the normal map and height map into a standard unity shader, for instance transparent parallax specular.

I pretty much have all the pieces I need assembled but I am new to shaders and need help putting them together

I can generate a heightmap from the blobs using some fragment shader code I wrote (I'm just using the red channel here cus i dont know if you can access the brightness)

    half4 frag (v2f i) : COLOR{     
        half4 texcol,finalColor;
        texcol = tex2D (_MainTex, i.uv);        
        finalColor=_MyColor;
        if(texcol.r<_botmcut)
        {
            finalColor.r= 0;  
        }
        else if((texcol.r>_topcut))
        {
            finalColor.r= 0;
        }
        else
        {
            float r = _topcut-_botmcut; 
            float xpos = _topcut - texcol.r;

            finalColor.r= (_botmcut + sqrt((xpos*xpos)-(r*r)))/_constant;
        }           
        return finalColor;
    }

turns these blobs.. enter image description here

into this heightmap enter image description here

Also I've found some CG code that generates a normal map from a height map. The bit of code that makes the normal map from finite differences is here

    void surf (Input IN, inout SurfaceOutput o)
                {
                    o.Albedo = fixed3(0.5);

                    float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));

                    float me = tex2D(_HeightMap,IN.uv_MainTex).x;
                    float n = tex2D(_HeightMap,float2(IN.uv_MainTex.x,IN.uv_MainTex.y+1.0/_HeightmapDimY)).x;
                    float s = tex2D(_HeightMap,float2(IN.uv_MainTex.x,IN.uv_MainTex.y-1.0/_HeightmapDimY)).x;
                    float e = tex2D(_HeightMap,float2(IN.uv_MainTex.x-1.0/_HeightmapDimX,IN.uv_MainTex.y)).x;
                    float w = tex2D(_HeightMap,float2(IN.uv_MainTex.x+1.0/_HeightmapDimX,IN.uv_MainTex.y)).x;

                    float3 norm = normal;
                    float3 temp = norm; //a temporary vector that is not parallel to norm
                    if(norm.x==1)
                        temp.y+=0.5;
                    else
                        temp.x+=0.5;

                    //form a basis with norm being one of the axes:
                    float3 perp1 = normalize(cross(norm,temp));
                    float3 perp2 = normalize(cross(norm,perp1));

                    //use the basis to move the normal in its own space by the offset
                    float3 normalOffset = -_HeightmapStrength * ( ( (n-me) - (s-me) ) * perp1 + ( ( e - me ) - ( w - me ) ) * perp2 );
                    norm += normalOffset;
                    norm = normalize(norm);

                    o.Normal = norm;
                }

Also here is the built-in transparent parallax specular shader for unity.

    Shader "Transparent/Parallax Specular" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
        _Parallax ("Height", Range (0.005, 0.08)) = 0.02
        _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    }

    SubShader {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        LOD 600

    CGPROGRAM
    #pragma surface surf BlinnPhong alpha
    #pragma exclude_renderers flash

    sampler2D _MainTex;
    sampler2D _BumpMap;
    sampler2D _ParallaxMap;
    fixed4 _Color;
    half _Shininess;
    float _Parallax;

    struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
        float3 viewDir;
    };

    void surf (Input IN, inout SurfaceOutput o) {
        half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
        float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
        IN.uv_MainTex += offset;
        IN.uv_BumpMap += offset;

        fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
        o.Albedo = tex.rgb * _Color.rgb;
        o.Gloss = tex.a;
        o.Alpha = tex.a * _Color.a;
        o.Specular = _Shininess;
        o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    }
    ENDCG
    }

    FallBack "Transparent/Bumped Specular"
    }

© Game Development or respective owner

Related posts about unity

Related posts about shaders