[Elemental Shader Jam] Lava

edited in General
I decided to give this a bash, not exactly what I had in mind originally.
pretty much stole chippits breeze wave shader as a base for the swell.
had issues trying to get the fresnel to work as I wanted it.

sorry for the somewhat horrible gif

image

textures used:
main :
image
_CloudTex/heatCloud :
image

Shader "Custom/lava-swell" 
{
	Properties
	{
		_MainTex ("Main Texture", 2D) = "white" {}
		_CloudTex ("heat pulse texture", 2D) = "white" {}
		_WindEffect ("Wind power", Float) = 0.1
		_DistanceTimeScale ("Distance Factor", Float) = 1
		_RustleStrength ("Rustle strength", Float) = 0.1
		_RustleSpeed ("Rustle speed", Float) = 1.5
		_WindDirection ("Wind direction", Vector) = (1.5, 0, -0.25, 0)
		_FresnelExponent ("Fresnel power", Range (1, 32)) = 20
		_Color ("Fresnel color", Color) = (1, 1, 1, 1)
	}
	
	CGINCLUDE	
	half 		_WindEffect;
	half 		_DistanceTimeScale;
	half 		_RustleStrength;
	half 		_RustleSpeed;
	fixed3		_WindDirection;
	float 		_FresnelExponent;
	fixed4		_Color;
	ENDCG
	
	SubShader 
	{
		Pass
		{
			Tags { "LightMode" = "ForwardBase"
			"Queue"="Transparent"  }
		
			CGPROGRAM
			#include "UnityCG.cginc"
			
			uniform float3 _LightColor0;
			
			sampler2D	_MainTex;
			sampler2D   _CloudTex;
			float4		_MainTex_ST;
			
			struct v2f
			{
				float4 	pos : POSITION;
				half2	uv : TEXCOORD0;
				float3	lightDir : TEXCOORD1;
				fixed3	norm : TEXCOORD2;
			};
			
			v2f vert (appdata_full v)
			{
				v2f o;
				
				// Work in object space for normal-based rustle
				float4 pos = v.vertex;
				
				// Move vert along its own normals based on rustle parameters, modified time with 
				// world space (so all verts do not move at the same time), and green vert colour
				pos.xyz += v.normal.xyz * cos(_Time.z * _RustleSpeed + pos.x + pos.y + pos.z) * v.color.g * _RustleStrength;
				
				// World space now for swaying
				float4 worldPos = mul(_Object2World, pos);
				
				// Calculate time across world space, based on the wind direction.
				float directionalTime = _Time.z - dot(worldPos, _WindDirection) * _DistanceTimeScale;
				
				// Use time to calculate the strength of our wave right now, modulated by vert colour R
				float waveInfluence = (cos(directionalTime) * 0.55 + 0.45) * v.color.r * _WindEffect;
				worldPos.xyz += _WindDirection * waveInfluence;
				
				o.pos = mul(UNITY_MATRIX_VP, worldPos);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.lightDir = ObjSpaceLightDir(v.vertex);
				o.norm = v.normal;
				
				return o;
			}

			fixed4 frag (v2f i) : COLOR0
			{
				fixed4 col = tex2D(_MainTex, i.uv+0.1*_Time.x);
				fixed4 overlay = col.r;
				fixed4 heatCloud = tex2D(_CloudTex, i.uv-0.4*_Time.x);
				
				float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.rgb;
				
				lightColor += dot(normalize(i.norm), normalize(i.lightDir)) * _LightColor0 * 2;
				// 
				col.rgb *= (lightColor+(0.2,0.2,0.2)+ (heatCloud.rgb)*0.5+overlay.rgb*sin(i.uv.x+_Time.y)*1.2-sin(i.uv.x+_Time.y)*0.1);
				return col;
			}
	
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	
		
		Pass
		{		
			Tags { "LightMode" = "ForwardAdd" 
			"Queue"="Transparent"}
			
			Blend One One
		
			CGPROGRAM
			#include "UnityCG.cginc"
			
			uniform float3 _LightColor0;
			uniform sampler2D _LightTexture0;
			uniform float4x4 _LightMatrix0;
			
			sampler2D	_MainTex;
			float4		_MainTex_ST;
			
			struct v2f
			{
				float4 	pos : POSITION;
				half2	uv : TEXCOORD0;
				float3	lightDir : TEXCOORD1;
				fixed3 	norm : TEXCOORD2;
				float3	lightCoord: TEXCOORD3;
			};
			
			v2f vert (appdata_full v)
			{		
				v2f o;
				
				// Work in object space for normal-based rustle
				float4 pos = v.vertex;
				pos.xyz += v.normal.xyz * cos(_Time.z * _RustleSpeed + pos.x + pos.y + pos.z) * v.color.g * _RustleStrength;
				
				// World space now for swaying
				float4 worldPos = mul(_Object2World, pos);
				
				float directionalTime = _Time.z - dot(worldPos, _WindDirection) * _DistanceTimeScale;
				float waveInfluence = (cos(directionalTime) * 0.55 + 0.45) * v.color.r * _WindEffect;
				worldPos.xyz += _WindDirection * waveInfluence;
				
				o.pos = mul(UNITY_MATRIX_VP, worldPos);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.lightDir = ObjSpaceLightDir(v.vertex);
				o.norm = v.normal;
				o.lightCoord = mul(_LightMatrix0, mul(_Object2World, v.vertex)).xyz;
				
				return o;
			}

			fixed4 frag (v2f i) : COLOR0
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				
				
				float lightDist = dot(i.lightCoord, i.lightCoord);
				float atten = tex2D(_LightTexture0, lightDist.rr).UNITY_ATTEN_CHANNEL;
				
				float3 lightColor = dot(normalize(i.norm), normalize(i.lightDir)) * _LightColor0 * atten * 2;			
				
				col.rgb *= lightColor;
				return col;
			}
	
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
		Pass
		{		
			Tags { "Queue"="Transparent" }
			cull front
			CGPROGRAM
			#include "UnityCG.cginc"
			
			sampler2D _MainTex;
			float4		_MainTex_ST;
			
			struct v2f
			{
				float4 	pos : POSITION;
				half2	uv : TEXCOORD0;
				float3	viewDir : TEXCOORD1;
				fixed3	norm : TEXCOORD2;
			};
			
			v2f vert (appdata_full v)
			{
				v2f o;
				
				// Work in object space for normal-based rustle
				float4 pos = v.vertex;
				
				// Move vert along its own normals based on rustle parameters, modified time with 
				// world space (so all verts do not move at the same time), and green vert colour
				pos.xyz += v.normal.xyz * cos(_Time.z * _RustleSpeed + pos.x + pos.y + pos.z) * v.color.g * _RustleStrength*0.1;
				
				// World space now for swaying
				float4 worldPos = mul(_Object2World, pos);
				
				// Calculate time across world space, based on the wind direction.
				float directionalTime = _Time.z - dot(worldPos, _WindDirection) * _DistanceTimeScale;
				
				// Use time to calculate the strength of our wave right now, modulated by vert colour R
				float waveInfluence = (cos(directionalTime) * 0.55 + 0.45) * v.color.r * _WindEffect;
				worldPos.xyz += _WindDirection * waveInfluence;
				
				o.pos = mul(UNITY_MATRIX_VP, worldPos);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.viewDir = ObjSpaceViewDir(v.vertex);
				o.norm = v.normal;
				
				return o;
			}

			fixed4 frag (v2f i) : COLOR0
			{
				// Fresnel term at pixel level for the best look. 
				// Fresnel term is simply 1 minus view dot n.
				float fresnel = 1 - dot(normalize(i.viewDir), normalize(i.norm*-1));
				fresnel = pow(fresnel, _FresnelExponent);
				//fresnel = round(fresnel);
				_Color = _Color -(0,0,0,1-fresnel);
				return (fixed4)fresnel * _Color ;
			}
	
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
}


Comments

  • Looks cool! :)

    I sort of expect that when some of the cracks grow more brightly (a "bright" red usually starts to hue shift through saturated orange to yellow), that there'd be some bloom around them, whether it's a postprocess, or whether your shader cleverly does that itself. :D
  • edited
    It's looking good! I like the whole bubbling effect you've got going. If you're using Unity Free, implementing bloom around the cracks without RTT would be tricky, but coming up with an alternative would be an interesting challenge and add a lot to the shader! :D
  • edited
    image

    I realise now that a large portion of my time has been used in trying to mask out the cracks from the rest of the texture
    so that I can run operations on them only, and that it might have just been easier to add a third mask texture and do the work externally.

    Will update the code later
  • That would seem a wise course of action! You could also put the mask into the alpha channel of one of your existing textures for the sake of performance.
Sign In or Register to comment.