A Shady Story

TL;DR - Dev log of me learning shaders by trying to recreate pics/effects I find online. :)

Over my game dev career. I've come across these black magic programs they call shaders. I'd see something like this

image

and ask "How do you do that?". The reply would be "it's a shader". In my attempt to become one of these magicians I'd start a shader tutorial series. It'd be blah blah blah runs on the GPU, something something lighting, pixar, blah blah blah lambertian, dot product and you'd end up with

image

-_______-

I picked up the basic theory. You've got vertices, move them and morph the mesh. You've got pixels, change their color. Oh, and it runs in parallel.

Then I had to write my first production shader. It was for Raptor Polo. We needed to be able to have player colors. There were a ton of frames of animation. The process of splitting the clothes from the orc, grayscaling them and puting them separately was infeasible. So I wrote a shader that did that. This was in Unity3D.

image

Next shaders were written for a WEB GL. Passed the shader audio frequency data to offset vertices as a song played. Eventually the shader and the music sculpted a sphere into a "rose". And then based on the offset the color of the vertex. That's why its darker closer to the center. Thanks CT mini jams.

image

Started to get excited about shaders. Next shader was for Semblance. Needed to recreate the lighting streaks like in this concept piece.

image

This was a fun challenge. Learnt about shader buffers and using more than one pass. Used a "masking effect" to get the light streaks.

image

Over this period I've been collecting images across the net of shaders I'd like to attempt to make. This thread is gonna be like the art dumps but of my progress learning shaders.

Comments

  • edited
    First of these shaders is to try replicate this

    So far this is what I've got.

    image
    shaders004.gif
    783 x 435 - 126K
  • Nice! Do you have a plan for how to tackle the rest of it? :)
  • @Elyaradine

    Right now my next step is to create a the springing to the vertices. I want to use the the same spring function I've been using in Semblance.

    I've read you can write to textures using shaders. So, I'm going to save the velocity of each vertex in a texture. Save direction in rgb and magnitude in alpha.

    A lot of guess work. Let me know if I'm heading down the wrong road.
    Thanked by 1Elyaradine
  • This is why you are awesome Sugar! Keep it up please!!!
    Thanked by 2Elyaradine SUGBOERIE
  • This is such a cool post, and I'm looking forward to watching your progress.

    A while back I was starting to look at how shaders worked and I happened to watch an episode of Archer with a scene in an office with a water feature on the right. And I thought to myself that it would be the perfect scene to try recreate with a custom cel shading, glass, and moving water shader. Of course, I never did that :(
    Thanked by 1SUGBOERIE
  • woohoo shaders <3

    stuff looks awesome!
    Thanked by 1SUGBOERIE
  • edited
    @SUGBOERIE I'm not sure if you're using directx or how similar it might be to opengl but in opengl you'd render to a FBO and then from there you can create a texture :) That's actually how I do shadow mapping. Then just for added effect I pass my shadow texture through my grass shader and using the camera displacements etc work out how I should darken the grass.

    image

    What shader language are you doing this all in? :)
  • I kept working on the shader last night. Found myself reading into GPGPU programming to do the texture thing to store values. Came out with this, a physics driven spring simulation on the GPU.

    @IceCliff I'm using Unity3D for the current shader. It's GLSL, I think. In Unity there's RenderTextures, based on what I read about FBO they are similar. You can write to them. and use the texture again in another shader.
  • I keep refreshing this thread, but nothing's happening. :P
  • @Elyaradine I've actually been beating my head against a rock trying to merge these two ideas.

    SImple shader that checks each vert against the position of the moving sphere and extrudes it out based on the verts normal.

    image

    and

    This is two shaders. One that computes the springing and the other that takes the texture from the springing shader and extrudes the vert based on the color of the texture.

    image

    So, uhm ... yeah.
    shaders004.gif
    742 x 403 - 213K
  • edited
    What are you looking at trying next?

    If you're stuck, you could perhaps try relaxing the constraint of having it all done in one ubershader, but to either layer multiple objects together, or use helper objects that drive your shaders?
  • @Elyaradine Thanks for keeping me on my toes. I almost feel like I may have just gotten over it if it weren't for you asking.

    So here's what I went with. I stuck with the 2 shader solution I had for simulating the springing. Now I had to figure out how to make the distorting sphere go through the spring shader.

    The springing shader is purely a fragment shader. So, I had to think of the distorting sphere going through the texture in uv coordinates.

    Here's a diagram of the theory. A sphere going through a plane in 2D is just a a circle on the plane that who's radius grows and shrinks again.

    image

    simple enough, equation of a circle with shader parameters for x, y. Interpolate towards the radius.

    image

    Obviously a linear interpolation creates a cone. I need a "sphere". So, just circle interpolate.

    image

    Now Unity's standard sphere maps the verts uvs nicely enough for me to fake where to make my circles grow and shrink from

    image

    So, I knew where to grow the circles on the texture. The shader that takes texture from the springing shader just does a simple vertex displacement based on the red channel of the texture.

    image

    I was using ProBuilder to create the Icosahedron sphere but it doesn't map the uvs like the Unity sphere. I guess I need to try manually create a model with the uv mapping I want???

    There's nothing fancy with the sphere that goes through the springing sphere. It's just mapping it's x values to an animation curve that changes the values on the shader to spring. To make it general, I probably would use the their positions and radius values.

    Things not quite right
    - The extrusion max height should be based on the size of the radius
    - the circle interpolation shouldn't be the full interpolation every time but also based on the radius

    That's what I've got so far. :)

    dissection.png
    500 x 900 - 13K
  • edited
    YES!

    That is badass. :D

    Have you tried what this looks like when the displacement tears the mesh apart? (I don't know for certain, especially because I haven't used ProBuilder, but I think you can reimport your sphere with automatic smoothing set to a tiny angle (0-1 degrees) to break all of the edges. I imagine ProBuilder would have some kind of edge-hardening tool built into it too.)

    Great job man! What's next?

    --
    (also, just fyi, I was biting my tongue super hard not to suggest the implementations that I'd have attempted. I'm glad I did, because I think you've got a better (more dynamic) result than what I'd have suggested. :D)
    Thanked by 1SUGBOERIE
  • It's great to see an advanced approach to graphics being fostered here in SA. Not nearly enough people in this field!
    Thanked by 1SUGBOERIE
  • Very cool stuff!

    Is it possible to increase the "resolution" of the sphere ripples simply by using a model with more verts?
    And can this handle two spheres moving through the big one at once?
    Thanked by 1SUGBOERIE
  • Have you tried what this looks like when the displacement tears the mesh apart?
    No. That's the next step.
    Is it possible to increase the "resolution" of the sphere ripples simply by using a model with more verts?
    Yes. Theoretically, haven't tested it.

    And can this handle two spheres moving through the big one at once?
    Unfortunately not.

    @jackshiels, thanks. I'm trying my best. :D
  • @SUGBORIE dude that springing is bloody awesome. Do you have any good resources to suggest for learning it? :)

    Also have you tried using compute shaders? I was reading about them recently and it seems like it would be extremely helpful for you for this exact kind of task.
  • image

    I think I'm done, well I'm kinda over it now. I feel like I've exhausted enjoyment of the learning process here. I didn't get to the shiny rendering, or these

    - The extrusion max height should be based on the size of the radius
    - the circle interpolation shouldn't be the full interpolation every time but also based on the radius
    - trying to make it general (there's few of cheats :P )

    but I'm happy about what I learnt about GPGPU programming. Want to tackle the next shader now. I'm hoping to write a full article about the process soon. :)

    Thanks @IceCliff!

    The spring algorithm I got from here.

    The simulation on a shader I learnt here. It's very Unity focussed but before I found it I read a lot about simulations on the GPU on different platforms. Just can't find the articles now.

    shaders010.gif
    828 x 458 - 1M
    Thanked by 1IceCliff
  • edited
    Sun on shadertoy - original with GLSL code

    Unity demo - adapted for unity

    good luck
    Thanked by 2SUGBOERIE IceCliff
  • Hot damn foxes <3 you've legitimately inspired me to learn some more shader programming again.
  • IceCliff said:
    Hot damn foxes <3 you've legitimately inspired me to learn some more shader programming again.
    OO, you can make more if you add to this learn ComputeShader
  • edited
    Hey been a while since I posted here. Trying to get back to this. I started learning about raymarching and volumetric shading using Alan Zucconi's tutorial. At the end of the tut he came out with this.

    image

    I ended up with this. :(

    image

    I'm writing some shaders in shadertoy and I get the theory of raymarching and signed distance fields. I can't for the life of me see what I've done wrong with this one in Unity, here's the shader. Any help?

    Shader "Unlit/VolumeSphere"
    {
    	Properties
    	{
    		_Centre ("Center", Float) = 0.0
    		_Radius ("Radius", Float) = 0.5
    	}
    	SubShader
    	{
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    			};
    
    			struct v2f
    			{
    				float4 pos : SV_POSITION;
     				float3 wPos : TEXCOORD1;
    			};
    
    			float _Radius;
    			float4 _Centre;
    			
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.pos = UnityObjectToClipPos(v.vertex);
    				o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    				return o;
    			}
    			
    			#define STEPS 64
    			#define STEP_SIZE 0.01
    
    			bool sphereHit(float p)
    			{
    				return distance(p, _Centre) < _Radius;
    			}
    			
    			bool raymarchHit (float3 position, float3 direction)
    			{
    				for (int i = 0; i < STEPS; i++)
    				{
    					if ( sphereHit(position) )
    						return true;
    					
    					position += direction * STEP_SIZE;
    				}
    				
    				return false;
    			}
    
    			fixed4 frag (v2f i) : SV_Target
    			{
    				float worldPos = i.wPos;
    				float3 viewDirection = normalize(i.wPos - _WorldSpaceCameraPos);
    				
    				if (raymarchHit(worldPos, viewDirection))
    					return fixed4(1.0, 0.0, 0.0, 1.0);
    
    				return fixed4(1.0, 1.0, 1.0, 1.0);
    			}
    
    			
    			ENDCG
    		}
    	}
    }
    rotate.gif
    336 x 302 - 35K
    volrender.gif
    789 x 466 - 1M
  • edited
    Went through your code, there were some minor errors, floats instead of float3 and stuff like that, code below works.

    Shader "Unlit/VolumeSphere"
    {
    	Properties
    	{
    		_Radius("Radius", Float) = 0.5
    	}
    	SubShader
    	{
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    			};
    
    			struct v2f
    			{
    				float4 pos : POSITION0;
    				float3 wPos : TEXCOORD1;
    				float3 ver : TEXCOORD2;
    			};
    
    			float _Radius = 0.5;
    			float3 Centre = float3(0,0,0);
    			
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.pos = UnityObjectToClipPos(v.vertex);
    				o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    				o.ver = v.vertex;
    				return o;
    			}
    			
    			#define STEPS 64
    			#define STEP_SIZE 0.1
    
    			bool sphereHit(float3 p)
    			{
    				return (distance(p, Centre) < _Radius);
    			}
    
    			bool raymarchHit (float3 position, float3 direction)
    			{
    				for (int i = 0; i < STEPS; i++)
    				{
    					bool hit = sphereHit(position);
    					if (hit)
    						return true;
    
    					position += direction * STEP_SIZE;
    				}
    				
    				return false;
    			}
    
    			float4 frag (v2f i) : COLOR
    			{
    				float3 worldPos = i.wPos;
    				float3 viewDirection = normalize(i.wPos - _WorldSpaceCameraPos);
    				
    				if (raymarchHit(worldPos, viewDirection))
    					return fixed4(1.0, 0.0, 0.0, 1.0);
    
    				return fixed4(1.0, 1.0, 1.0, 1.0);
    			}
    
    			
    			ENDCG
    		}
    	}
    }

    image
  • @critic thanks. Feel so dumb for all the type errors.
    Thanked by 1critic
  • edited
    It happens, I'm glad you posted this here, it's nice and clean code, a good base for ray-marching stuff.
    Thanked by 1EvanGreenwood
  • Hey. I'm back to working on more shaders. I translated threes.js Matt Deslauriers shader on shaping curves with parametric equations

    image

    Here's a WEBGL demo of the final shader. It's not as sexy as his though. I didn't end u working on the rendering part. As you've seen that's not my strong point at this moment even with the first shader in this thread. That's what I'd like to work on more.

    I put up the code on github with all the various steps commented out if you'd like to follow the tutorial.
    shaping-curves.gif
    605 x 461 - 2M
  • image

    I got back at it. Wanted to pretty up the first shader I worked on. Remember, like 2 years ago. LOL. Also did a short twitter thread of the process mostly the same as above. I also put up a project on GitHub where I'll dump all future shader experiments.
  • Back at it. Decided to play around with metaballs. Nothing too hectic. New learning was how to push arrays to a shader. Although the particle system happens on the CPU. Dropped some notes on twitter. Code's up on GitHub too.

    image
  • It's a doodle shader! I want to work on a pure frag shader at some point. Source

    image
  • Quick simple outline shader. Same repo as always
    image
    Thanked by 1riders_of_rohun
Sign In or Register to comment.