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
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..
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..
into this heightmap
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