[Elemental Shader Jam] Ice

edited in General
Played with making ice.
image

I want to do that cool fractal thing that you see in the middle here:
image image

...but I'm failing at maths. :(

I was hoping that using a fresnel with some noisiness stuck into it would give me streaks, but that's not really what happens. Any suggestions?
Thanked by 3Fengol konman HellBlade

Comments

  • How did you make the gif? I'm also working on an ice shader
  • What cool fractal thing? (I'm not sure to what specific thing in the middle you refer to :P)
  • Omg you're just showing off now :P
    Thanked by 1Bensonance
  • @Fengol: I used LICEcap. I want to make lots of different ones, but I'm just starting with ice. :)

    @hermantulleken: The star-like spikey thing in the middle that I assume is caused by air bubbles.

    @Tuism: Life is so much easier when I don't give a crap about performance. XD
  • edited
    Took my first dip into postprocessing and wrote something that pretends to be a bloom shader. Of course, Unity comes with a bunch of bloom shaders, but this one is MY bloom shader! :P

    Added some noisiness/bumpiness to the reflections to make them not look so glassy. Unfortunately, the noise is done based on the sphere's UVs, and default primitive spheres have artifacts at the poles, which makes that look funny.

    Also, I gave up on trying to create that fractal, and took the easy way out. Switched my project to DX11, and just used tessellation and displacement in a surface shader to get my spiky fractal shape. It's not quite the shape I want compared to the ice in the first post (it's currently too straight, regular and streaky), but it's okay. I'm not really sure it's worth the effort of trying to make a primitive look more complex though, so I might stop here.

    image

    Here's the code for the outer sphere. It's a mess (there may be some stuff left in there that I ended up not using... I tend to do that when I'm just messing around trying to prototype a look!), but I don't care! :D
    Shader "Custom/Ice" {
    	Properties 
    	{
    		_Color ("Main Colour", Color) = (1,1,1,1)
    		_Bump ("Normal map", 2D) = "bump" {}
    		_Drops ("Droplet normals", 2D) = "bump" {}
    		_Cube ("Cube", CUBE) = "black" {}
    		_RefractIndex ("Refraction Index", Float) = 1.3
    		_FresPower ("Fresnel Power", Float) = 1
    		_Overbright ("Overbrightness", Float) = 1
    		_BumpStrength ("Bump strength", Float) = 1
    		_Noise ("Noise map", 2D) = "gray" {}
    		_Roughness ("Roughness", Float) = 0.1
    	}
    	
    	CGINCLUDE
    	#include "UnityCG.cginc"
    	
    	struct v2f {
    		float4 pos: 		SV_POSITION;
    		half3 norm:			TEXCOORD0;
    		half3 viewDir:		TEXCOORD1;
    		half fres:			TEXCOORD2;
    		half3 tang:			TEXCOORD3;
    		half3 bino:			TEXCOORD4;
    		half2 uv:			TEXCOORD5;
    		half2 uvDrops:		TEXCOORD6;
    		half2 uvNoise:		TEXCOORD7;
    	};
    	
    	samplerCUBE _Cube;
    	sampler2D _Bump;
    	sampler2D _Noise;
    	sampler2D _Drops;
    	half4 _Noise_ST;
    	half4 _Bump_ST;
    	half4 _Drops_ST;
    	half _RefractIndex;
    	half _FresPower;
    	half _Overbright;
    	half _BumpStrength;
    	half _Roughness;
    	fixed4 _Color;
    	
    	ENDCG
    	
    	SubShader 
    	{
    		Tags 
    		{ 
    			"RenderType"="Opaque"
    		}
    		LOD 200
    		
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			v2f vert(appdata_full v)
    			{
    				v2f o;
    				
    				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    				o.norm = normalize(mul((half3x3)_Object2World, v.normal));
    				o.viewDir = normalize(_WorldSpaceCameraPos - mul(_Object2World, v.vertex).xyz);
    				half fresnel = saturate(dot(o.norm, o.viewDir));
    				o.fres = pow(fresnel, _FresPower);
    				
    				o.tang = v.tangent.xyz;
    				o.bino = cross(o.norm, o.tang) * v.tangent.w;
    				
    				o.uv = v.texcoord.xy * _Bump_ST.xy + _Bump_ST.zw;
    				o.uvDrops = v.texcoord.xy * _Drops_ST.xy + (_Drops_ST.zw * _Time.y);
    				
    				o.uvNoise = v.texcoord.xy * _Noise_ST.xy;
    				
    				return o;
    			}
    			
    			fixed4 frag(v2f i):COLOR
    			{
    				// Look up textures
    				fixed noise = tex2D(_Noise, i.uvNoise).a;
    				half3 norm = UnpackNormal(tex2D(_Bump, i.uv));
    				half3 drops = UnpackNormal(tex2D(_Drops, i.uvDrops));
    				norm = normalize(fixed3(norm.r + drops.r, norm.g + drops.g, norm.b));
    				
    				// Calculate normal using normal map offset
    				half3 bentNorm = (i.tang * norm.x) + (i.bino * norm.y) + (i.norm * norm.z);
    				bentNorm = normalize(lerp(i.norm, bentNorm, _BumpStrength));
    				
    				// Refraction
    				half3 refrNormal = normalize(refract(-i.viewDir, bentNorm, 1/_RefractIndex + noise * _Roughness - 0.5 * _Roughness));
    				fixed3 refr = fixed3(texCUBE(_Cube, normalize(refrNormal)).rgb);
    				
    				// Reflection
    				half3 reflNormal = normalize(reflect(-i.viewDir, bentNorm + (noise * _Roughness - 0.5 * _Roughness)));
    				fixed3 refl = fixed3(texCUBE(_Cube, reflNormal).rgb);
    				
    				// Combine reflection and refraction based on fresnel
    				fixed3 combined = lerp(refl, refr, pow(i.fres, 5));
    
    				return fixed4(combined * _Color.rgb * _Overbright, 1);
    			}
    			
    			ENDCG
    		}
    	} 
    	FallBack "Diffuse"
    }


    The bloom shader isn't really worth posting, because I pretty much made a simpler version of what someone posted here. I just removed the dirt and added the possibility of biasing my blurring so that I could get more horizontal blurs.

    And the tessellation I learnt how to do from here. The guy there takes a bunch of work from GPUGems and ShaderX and implements them in Unity, with some pretty kickass results, and shares the projects for free. Great learning material. :)
    Thanked by 2Fengol Tuism
  • Wowser. Just wowser.

    I think the spikes are a bit too harsh though, maybe put some stuff on top of them (like foggy ice surface-ness), but if you're going for a clear surface then it's probably right.

    Why does rotating the ball rotate the room too? Cos that's the only way the reflecitions/refractions in it will move too, right?
  • Really impressive man! Next up, I think you have to do an eye of Sauron shader.
  • edited
    @Tuism: Yeah, I agree about the harshness. It's kind of a tricky thing. The primitive that I'm tessellating, if I scale it up, then the spikes start from farther out, and they look thicker and less harsh, which is good. But because they start from farther out, anything inside the sphere becomes significantly more transparent than anything outside of it. But if I scale it down so that you don't see this hole in the mesh, then all of the spikes become thinner and harsher. Normally, I could add another pass or something, but because it's a surface shader I can't.

    I hate surface shaders.

    And it's not the ball rotating -- it's the camera orbiting around the ball. :) I can see how that would be confusing, given that the camera's orbit pivot is in the same position as the ball's centre. :P

    @Denzil: Thanks dude! I actually want to do some procedural volumetric fire next, just to have that under my belt. In particular, I've always been blown away by how Little Inferno had such dynamic fire fx, and I figure if I can get fire, water and some other fluids working, it could potentially be something around which another little game/sandbox can be built. I imagine Where's My Water might work in a somewhat similar way.
  • Phwoar. That is all. I'm also very happy to read through your code to learn how to improve my own entry's. :P
  • edited
    Okay, I got better fractal spikey things! (Actually, I just needed to make the tessellation coarser for something that looks approximately right.)

    image

    I was also being dumb and tried writing realtime raytraced caustics. XD Ideally, I'd like to move this off of the cpu onto the gpu using DirectCompute, but I dunno how useful that actually is for me to learn. Maybe a hybrid approach would work, where I do the raycasting on the cpu (because easy, Unity physics), but do interpolation and texture manip on the gpu... but I think I'll skip that and do some other shaders rather.

    image
  • Cool photo of an ice sphere, but this is thread is about making shaders :)
    Thanked by 2Tuism Bensonance
  • edited
    Interested to see what that ice shader looks like when you stick it on a more complex model? :)

    Also I like the first ice shader more - the one with the dots instead of these spikes. Looks better to me.
  • I like both, but the first one looks more like glass to me.
  • edited
    I really like the frosted look of the first one too. Tried using a combination of the two. Also added some generic particle stuff just because ambience.

    image
    http://techartjon.com/unity/ice/_Build.html (~3.1MB)

    [edit] Oh, btw, If you're not on a DX11 computer, the fractal thing won't show up. But the rest shoooould work. Unity seems to claim the ice shader now requires SM5 too, but I'm not doing anything special in there that wouldn't run on SM3... (definitely not SM2 though!)[/edit]

    Bah, spent most of tonight trying to do stuff with compute shaders, and it turns out that it's the actual raycasting that's the bottleneck. Then I played with using a gridded sample instead of random samples, hoping that I could reduce the number of rays that I'd need, but I couldn't eliminate the obvious pattern that results. Then I tried blurring the texture, but that helped marginally (probably because I did it wrong). And finally, I had supper. :D

    Enough! Next shader!
  • Very nice!! Pity you didnt get the caustics working in the end... Maybe you should have just faked it with a projected decal ;)
    Thanked by 1Elyaradine
  • Yeah, but I do that at work all the time, and I wanted to learn something new. :P
    Thanked by 1Nitrogen
  • Damn. I want to be this good when I grow up.
    Thanked by 2Denzil Bensonance
  • Yeah, but I do that at work all the time, and I wanted to learn something new. :P
    Well in that case, raycast away! :P But I agree, Next Shader!

  • Stick it on a complex shape and see what happens? :)
  • edited
    @Tuism yeah I'd like to see an ice statue (that looks like me)
  • This ice material is one of the best i've seen....and I've seen many...
    I'm trying to make an ice cube with this but I could not duplicate you very first example...how you do the bubbles inside and the cubemap? I take the same hdr but could not duplicate the result.
  • The bubbles are actually the roughness??
  • Hey, thanks so much for the compliment! :) Not quite sure what you're talking about regarding bubbles in that first example. I think there are two main things going on in there: the one is the "frosted" look, which I think was a fresnel calculation that had some noise thrown into it. The other is the droplets, which was a normal map with drop-like shapes painted into it. Hope that helps you!
  • hey bro. awesome job on this shader. i just found this thread by searching about ice shader in the Google. iam using a dx10 gpu and the picture below is what i got from your built you just posted here:
    I really like the frosted look of the first one too. Tried using a combination of the two. Also added some generic particle stuff just because ambience.

    image
    http://techartjon.com/unity/ice/_Build.html (~3.1MB)

    [edit] Oh, btw, If you're not on a DX11 computer, the fractal thing won't show up. But the rest shoooould work. Unity seems to claim the ice shader now requires SM5 too, but I'm not doing anything special in there that wouldn't run on SM3... (definitely not SM2 though!)[/edit]

    Bah, spent most of tonight trying to do stuff with compute shaders, and it turns out that it's the actual raycasting that's the bottleneck. Then I played with using a gridded sample instead of random samples, hoping that I could reduce the number of rays that I'd need, but I couldn't eliminate the obvious pattern that results. Then I tried blurring the texture, but that helped marginally (probably because I did it wrong). And finally, I had supper. :D

    Enough! Next shader!
    image

    thank you for help :)
    Ice.jpg
    883 x 574 - 131K
  • Hrm. Looks like Unity changes it to a straight-up default diffuse shader when you don't have DX11. >_< Thanks for letting me know! (I'm currently swamped with work, so I'm unlikely to fix this any time soon though...)
  • Really awesome work, man.
Sign In or Register to comment.