Week 10 HW

For this week’s homework I created a displacement shader using Unity’s shader graph. I follow along this video  and created a shader that moves the vertices of a plane up and down at random intervals using noise. I decided to add a chessboard texture to the plane and decorate it with some animated pawn 3D models that I found online. Unfortunately I was unable to attach an image because the limit is 500kb which is way too small even after I compress the image.

Week 9 Homework

This week’s homework was really tough because I was finding it difficult to convert from GLSL to HLSL but eventually I began to understand it better thanks to Jeremy.

Studio MDHR

Studio MDHR developed cuphead using Unity. The game uses a lot of post processing effects to add atmosphere and polish. An example of this can be seen in the rain and thunder during the Grim Matchstick boss fight. Another example of post processing is the grain and scratches overlaid on the screen throughout the entire game. The game is entirely 2D so I am guessing it uses unlit materials, increasing performance. Several particle elements appear to be created with Unity’s shader graph and have even been attempted to be recreated. The developers excelled at recreating the iconic rubber house cartoon style through art, animation and music. The 2D nature of the game shows off the great artstyle without being overbearing in detail. I think Cuphead would be a drastically different and arguably worse looking game if it included realistic reflections because it would not fit in with the hand drawn style. I’m not sure how a PBR could even be incorporated within a 2D game but it might be an interesting concept.

For some reason I can not upload images larger than 500kb so I’ve linked a google drive folder with screenshots from this week.

https://drive.google.com/drive/folders/11IuMLZDs4eP2S3q0rvQMIjHzjM0KjDh7?usp=sharing

Color wheel Shader from the book of shaders that spins using _Time.y (image 1 in google drive)

<div>
<div>Shader "Custom/week9"</div>
<div>{</div>
<div>    Properties</div>
<div>    {</div>
<div>        _Color ("Color", Color) = (1,1,1,1)</div>
<div>        _MainTex ("Albedo (RGB)", 2D) = "white" {}</div>
<div>        _Glossiness ("Smoothness", Range(0,1)) = 0.5</div>
<div>        _Metallic ("Metallic", Range(0,1)) = 0.0</div>
<div>    }</div>
<div>    SubShader</div>
<div>    {</div>
<div>        Tags { "RenderType"="Opaque" }</div>
<div>        LOD 200</div>
<div>        CGPROGRAM</div>
<div>        // Physically based Standard lighting model, and enable shadows on all light types</div>
<div>        #pragma surface surf Standard fullforwardshadows</div>
<div>        // Use shader model 3.0 target, to get nicer looking lighting</div>
<div>        #pragma target 3.0</div>
<div>        sampler2D _MainTex;</div>
<div>        struct Input</div>
<div>        {</div>
<div>            float2 uv_MainTex;</div>
<div>        };</div>
<div>        half _Glossiness;</div>
<div>        half _Metallic;</div>
<div>        fixed4 _Color;</div>
<div>        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.</div>
<div>        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.</div>
<div>        // #pragma instancing_options assumeuniformscaling</div>
<div>        UNITY_INSTANCING_BUFFER_START(Props)</div>
<div>            // put more per-instance properties here</div>
<div>        UNITY_INSTANCING_BUFFER_END(Props)</div>
<div>        float3 hsb2rgb( in float3 c ){</div>
<div>    float3 rgb = clamp(abs(fmod(c.x*6.0+float3(0.0,4.0,2.0),</div>
<div>                             6.0)-3.0)-1.0,</div>
<div>                     0.0,</div>
<div>                     1.0 );</div>
<div>    rgb = rgb*rgb*(3.0-2.0*rgb);</div>
<div>    return c.z * lerp( float3(1.0,1.0,1.0), rgb, c.y);</div>
<div>}</div>
<div>        void surf (Input IN, inout SurfaceOutputStandard o)</div>
<div>        {</div>
<div></div>
<div>    float3 color = float3(0.0,0.0,0.0);</div>
<div>    float TWO_PI= 6.28318530718;</div>
<div>    // Use polar coordinates instead of cartesian</div>
<div>    float2 center = float2(0.5, 0.5);</div>
<div>    float2 toCenter = IN.uv_MainTex - center;</div>
<div>    float angle = atan2(toCenter.x,toCenter.y);</div>
<div>    float radius = length(toCenter)*2.0;</div>
<div>    // Map the angle (-PI to PI) to the Hue (from 0 to 1)</div>
<div>    // and the Saturation to the radius</div>
<div>    color = hsb2rgb(float3((angle/TWO_PI)+_Time.y,radius,1.0));</div>
<div>    //gl_FragColor = vec4(color,1.0);</div>
<div>            // Albedo comes from a texture tinted by color</div>
<div>            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * float4(color.x,color.y,color.z,1.0);</div>
<div>            o.Albedo = c.rgb;</div>
<div>            // Metallic and smoothness come from slider variables</div>
<div>            o.Metallic = _Metallic;</div>
<div>            o.Smoothness = _Glossiness;</div>
<div>            o.Alpha = c.a;</div>
<div>        }</div>
<div>        ENDCG</div>
<div>    }</div>
<div>    FallBack "Diffuse"</div>
<div>}</div>
</div>

My attempt to recreate my arrow shader from week 2 (sadly I was not able to get this to work)

<div>
<div>Shader "Custom/week9"</div>
<div>{</div>
<div>    Properties</div>
<div>    {</div>
<div>        _Color ("Color", Color) = (1,1,1,1)</div>
<div>        _MainTex ("Albedo (RGB)", 2D) = "white" {}</div>
<div>        _Glossiness ("Smoothness", Range(0,1)) = 0.5</div>
<div>        _Metallic ("Metallic", Range(0,1)) = 0.0</div>
<div>    }</div>
<div>    SubShader</div>
<div>    {</div>
<div>        Tags { "RenderType"="Opaque" }</div>
<div>        LOD 200</div>
<div>        CGPROGRAM</div>
<div>        // Physically based Standard lighting model, and enable shadows on all light types</div>
<div>        #pragma surface surf Standard fullforwardshadows</div>
<div>        // Use shader model 3.0 target, to get nicer looking lighting</div>
<div>        #pragma target 3.0</div>
<div>        sampler2D _MainTex;</div>
<div>        struct Input</div>
<div>        {</div>
<div>            float2 uv_MainTex;</div>
<div>        };</div>
<div>        half _Glossiness;</div>
<div>        half _Metallic;</div>
<div>        fixed4 _Color;</div>
<div>        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.</div>
<div>        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.</div>
<div>        // #pragma instancing_options assumeuniformscaling</div>
<div>        UNITY_INSTANCING_BUFFER_START(Props)</div>
<div>            // put more per-instance properties here</div>
<div>        UNITY_INSTANCING_BUFFER_END(Props)</div>
<div>        float2 brickTile(float2 _st, float _zoom){</div>
<div>    _st *= _zoom;</div>
<div></div>
<div></div>
<div>    return frac(_st);</div>
<div>}</div>
<div>float circle(in float2 _st, in float _radius){</div>
<div>    float2 dist = _st-float2(0.5,0.5);</div>
<div>    return 1.-smoothstep(_radius-(_radius*0.1),</div>
<div>                         _radius+(_radius*0.1),</div>
<div>                         dot(dist,dist));</div>
<div>}</div>
<div>float2 rotate2D (float2 _st, float _angle) {</div>
<div>    _st -= 0.5;</div>
<div>    _st =  float2x2(cos(_angle),-sin(_angle),</div>
<div>                sin(_angle),cos(_angle)) * _st;</div>
<div>    _st += 0.5;</div>
<div>    return _st;</div>
<div>}</div>
<div>float2 tile (float2 _st, float _zoom) {</div>
<div>    _st.x += step(1., fmod(_st.y,2.0)) * 2.;</div>
<div>    _st *= _zoom;</div>
<div></div>
<div>    return frac(_st);</div>
<div>}</div>
<div>float2 rotateTilePattern(float2 _st){</div>
<div>    float PI = 6.28318530718/2;</div>
<div>    //  Scale the coordinate system by 2x2</div>
<div>    _st *=2.0;</div>
<div>    //  Give each cell an index number</div>
<div>    //  according to its position</div>
<div>    float index = 0.0;</div>
<div>    index += step(1., fmod(_st.x,2.0));</div>
<div>    index += step(1., fmod(_st.y,2.0))*2.0;</div>
<div>    //      |</div>
<div>    //  2   |   3</div>
<div>    //      |</div>
<div>    //--------------</div>
<div>    //      |</div>
<div>    //  0   |   1</div>
<div>    //      |</div>
<div>    // Make each cell between 0.0 - 1.0</div>
<div>    _st = frac(_st);</div>
<div>    // Rotate each cell according to the index</div>
<div>    if(index == 1.0){</div>
<div>        //  Rotate cell 1 by 90 degrees</div>
<div>        _st = rotate2D(_st,PI*0.25);</div>
<div>    } else if(index == 2.0){</div>
<div>        //  Rotate cell 2 by -90 degrees</div>
<div>        _st = rotate2D(_st,PI*-1.);</div>
<div>    } else if(index == 3.0){</div>
<div>        //  Rotate cell 3 by 180 degrees</div>
<div>        _st = rotate2D(_st,PI*+0.75);</div>
<div>    }</div>
<div></div>
<div>    return _st*2.;</div>
<div>}</div>
<div>        void surf (Input IN, inout SurfaceOutputStandard o)</div>
<div>        {</div>
<div></div>
<div>    float3 color = float3(0.0,0.0,0.0);</div>
<div>    float PI = 6.28318530718/2;</div>
<div>    float TWO_PI= 6.28318530718;</div>
<div>    // Use polar coordinates instead of cartesian</div>
<div>    float2 _st = float2(0.5, 0.5);</div>
<div>    float2 toCenter = IN.uv_MainTex - _st;</div>
<div>    float angle = atan2(toCenter.x,toCenter.y);</div>
<div>    float radius = length(toCenter)*2.0;</div>
<div></div>
<div></div>
<div>    _st = tile(float2(-_st.y+(frac(_Time.y)),-_st.x),3.0);</div>
<div></div>
<div>    _st = rotateTilePattern(_st);</div>
<div>    float clr= circle(_st-_st.x,(0.5-_st.y));</div>
<div>    color = float3(clr,clr,clr);</div>
<div></div>
<div>    float3 blue=float3(0.003,0.575,1.000);</div>
<div>    color=lerp(color,blue,.9);</div>
<div>            o.Albedo = 1.0;</div>
<div>            // Metallic and smoothness come from slider variables</div>
<div>            o.Metallic = _Metallic;</div>
<div>            o.Smoothness = _Glossiness;</div>
<div>            o.Alpha = 1.0;</div>
<div>        }</div>
<div>        ENDCG</div>
<div>    }</div>
<div>    FallBack "Diffuse"</div>
<div>}</div>
</div>

I also looked at using Unity’s animator to switch between shaders (image 2 in google drive folder)

 

Week 5 Homework


precision mediump float;
uniform vec2 uResolution;
uniform vec2 uMousePosition;
// lets grab texcoords just for fun
varying vec2 vTexCoord;

// our texture coming from p5
uniform sampler2D tex0;
uniform sampler2D tex1;

void main() {

vec2 uv = vTexCoord;
// the texture is loaded upside down and backwards by default so lets flip it
uv = 1.0 - uv;

// to pixelate an image we need to alter our uvs so that instead of being a smooth gradient it steps from one color to the next
// in order to do this we will use the floor function
// floor will round a float down to the nearest int, so 4.98 would become 4.0, and -37.2 would become -37.0
// first the uv's are multipled times a tiles variable
float tiles = (uMousePosition.x/3.0+5.0);
uv = uv * tiles;

// second the uvs are rounded down to the nearest int
uv = (floor(uv));

// lastly we divide by tiles again so that uvs is between 0.0 - 1.0
uv = uv / tiles;

// often times in glsl you will see programmers combining many operation onto one line.
// the previous three steps could have also been written as uv = floor( uv * tiles ) / tiles

// get the webcam as a vec4 using texture2D and plug in our distored uv's
vec4 color0 = texture2D(tex0, uv);
vec4 color1 = texture2D(tex1, uv);

float blend = clamp(uMousePosition.y / uResolution.x, 0., 1.0);

// use blend to cross-fade with mix()
vec4 color = mix( color1, color0, blend);

gl_FragColor = vec4(color);

// if you'd like a debug view of what the uv's look like try running this line
// gl_FragColor = vec4(uv.x, uv.y, 0.0, 1.0);
}

I took a look at Adam Ferriss’ pixel sketch and merged it with the texture blend example from class. I added interaction using mouse X and mouse Y so that when the mouse is moved horizontally the image output becomes pixelated and when the mouse is moved vertically the camera output and image are blended. Figuring out these interactions took quite a while because I’ve never looked at GLSL with P5 but I was glad to get this little sketch functioning!

screen-recorder-thu-feb-18-2021-18-01-33screen-recorder-thu-feb-18-2021-18-02-04

 

Week 3

I call this one spaghetti.

download-8 download-10


// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
#define PI 3.14159265358979323846
float random (in vec2 st) {
return fract(sin(dot(st.xy,
vec2(0.360,0.320)))
* 43758.5453123);
}

// Value noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/lsf3WH
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st)+sin(u_time*0.1);
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( random( i + vec2(0.0,0.0) ),
random( i + vec2(1.0,0.0) ), u.x),
mix( random( i + vec2(0.0,1.0) ),
random( i + vec2(1.0,1.0) ), u.x), u.y);
}

mat2 rotate2d(float angle){
return mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
}
vec2 rotatePattern(vec2 _st, float _angle){
_st -= 0.5;
_st = mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle)) * _st;
_st += -0.596;
return _st;
}

vec2 tile(vec2 _st, float _zoom){
_st *= _zoom;
return fract(_st);
}
float lines(in vec2 pos, float b){
float scale = 1.600;
pos *= scale;
return smoothstep(0.0,
.5+b*.5,
abs((sin(pos.x*u_time/25.0)+b*abs(sin((u_time)))))*.5);
}
vec2 rotateTilePattern(vec2 _st){

// Scale the coordinate system by 2x2
_st *= 2.0;

// Give each cell an index number
// according to its position
float index = 0.0;
index += step(1., mod(_st.x,2.0));
index += step(1., mod(_st.y,2.0))*2.0;

// |
// 2 | 3
// |
//--------------
// |
// 0 | 1
// |

// Make each cell between 0.0 - 1.0
_st = fract(_st);

// Rotate each cell according to the index
if(index == 1.0){
// Rotate cell 1 by 90 degrees
_st = rotatePattern(_st,PI*0.25);
} else if(index == 2.0){
// Rotate cell 2 by -90 degrees
_st = rotatePattern(_st,PI*-.75);
} else if(index == 3.0){
// Rotate cell 3 by 180 degrees
_st = rotatePattern(_st,PI*.75);
}
else{
_st = rotatePattern(_st,PI*-.25);
}

return _st;
}

void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = tile(st,1.);
st = rotateTilePattern(st);
st.y *= u_resolution.y/u_resolution.x;

vec2 pos = st.yx*vec2(0.990,0.960);
vec3 color = vec3(0.0);
float pattern = pos.x;
// Add noise
pos = rotate2d( noise(pos) ) * pos;

// Draw lines
pattern = lines(pos,.5);

gl_FragColor = vec4(vec3(1.0,pattern*.9,0.25),1.0);
}

It’s getting hard for me to add on to my old code because the functions tend to feel overwhelming so I decided to start fresh using the wood example created by @patriciogv. I love the endless possibilities of using noise and I’m interested in learning more about Perlin noise.

Week 2 Homework

Shader #1

For this shader I began with the Truchet Tile code from The Book of Shaders. Through rotating different tiles and experimentation I was able to create an arrow shape. I immediately knew that I wanted the arrows to move in the direction they are pointing and it didn’t take too long to figure out how to achieve this. I also played around with creating an outline around the entire canvas. I was hoping to outline the arrows but I got stumped and couldn’t figure out how to do it. It’s not the prettiest shader but I found that making the arrow shape and then making them move was a good coding exercise.

download-7


// Author Max Shapovalov
//Title: Arrows
//Modified work of @patriciogv ( patriciogonzalezvivo.com ) - 2015

#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265358979323846
uniform vec2 u_resolution;
uniform float u_time;

float circle(in vec2 _st, in float _radius){
vec2 dist = _st-vec2(0.5);
return 1.-smoothstep(_radius-(_radius*0.1),
_radius+(_radius*0.1),
dot(dist,dist));
}
vec2 rotate2D (vec2 _st, float _angle) {
_st -= 0.5;
_st = mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle)) * _st;
_st += 0.5;
return _st;
}

vec2 tile (vec2 _st, float _zoom) {
_st.x += step(1., mod(_st.y,2.0)) * 2.;
_st *= _zoom;

return fract(_st);
}

vec2 rotateTilePattern(vec2 _st){

// Scale the coordinate system by 2x2
_st *=2.0;

// Give each cell an index number
// according to its position
float index = 0.0;
index += step(1., mod(_st.x,2.0));
index += step(1., mod(_st.y,2.0))*2.0;

// |
// 2 | 3
// |
//--------------
// |
// 0 | 1
// |

// Make each cell between 0.0 - 1.0
_st = fract(_st);

// Rotate each cell according to the index
if(index == 1.0){
// Rotate cell 1 by 90 degrees
_st = rotate2D(_st,PI*0.25);
} else if(index == 2.0){
// Rotate cell 2 by -90 degrees
_st = rotate2D(_st,PI*-1.);
} else if(index == 3.0){
// Rotate cell 3 by 180 degrees
_st = rotate2D(_st,PI*+0.75);
}

return _st*2.;
}
vec2 brickTile(vec2 _st, float _zoom){
_st *= _zoom;

// Here is where the offset is happening
_st.x += step(1., mod(_st.y+0.5,3.)) * 0.5;

return fract(_st);
}
void main(void){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 pattern = vec3(0.0);
vec3 pattern2 = vec3(0.0);
vec3 blue=vec3(0.003,0.575,1.000);
vec2 bl = step(vec2(0.05),st); // bottom-left
vec2 tr = step(vec2(0.05),1.-st); // top-right
vec3 outline = vec3(bl.x * bl.y * tr.x * tr.y);

blue = mix(blue,vec3(outline.x,1.0,1.0),.6);
st = tile(vec2(-st.y+(fract(u_time/5.0)),-st.x),1.0);
st = brickTile(st,3.0);
st = rotateTilePattern(st);
pattern = vec3(circle(st-st.x,(0.5-st.y)));
outline = vec3(circle(st,(0.5-st.y)));

blue = mix(blue,vec3(outline.x,1.0,1.0),.1);

pattern=mix(pattern,blue,.9);
pattern=smoothstep(vec3(pattern),vec3(.2),vec3(.5));
gl_FragColor = vec4(pattern,1.);

}

Shader #2

In this shader I played around with creating circles and squares overtop of one another and then using the step function to get a silhouette. I found that the order of functions and can drastically change how the shader looks. Lastly I divided the canvas in four quadrants and made them spin.

download-4

// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015
//title: crosses
#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265358979323846

uniform vec2 u_resolution;
uniform float u_time;

vec2 rotate2D (vec2 _st, float _angle) {
 _st -= 0.5;
 _st = mat2(cos(_angle),-sin(_angle),
 sin(_angle),cos(_angle)) * _st;
 _st += 0.5;
 return _st;
}

vec2 tile (vec2 _st, float _zoom) {
 _st *= _zoom;
 return fract(_st);
}
vec2 brickTile(vec2 _st, float _zoom){
 _st *= _zoom;

 // Here is where the offset is happening
 
 _st.x += step(1., mod(_st.y,2.0)) ;
 
 return fract(_st);
}
vec2 rotateTilePattern(vec2 _st){

 // Scale the coordinate system by 2x2
 _st *= 2.0;

 // Give each cell an index number
 // according to its position
 float index = 0.0;
 index += step(1., mod(_st.x,2.0));
 index += step(1., mod(_st.y,2.0))*2.0;

 // |
 // 2 | 3
 // |
 //--------------
 // |
 // 0 | 1
 // |

 // Make each cell between 0.0 - 1.0
 _st = fract(_st);

 // Rotate each cell according to the index
 if(index == 1.0){
 // Rotate cell 1 by 90 degrees
 _st = rotate2D(_st,PI*1.);
 } else if(index == 2.0){
 // Rotate cell 2 by -90 degrees
 _st = rotate2D(_st,PI*-0.0);
 } else if(index == 3.0){
 // Rotate cell 3 by 180 degrees
 _st = rotate2D(_st,PI*-.5);
 }
 else{
 _st = rotate2D(_st,PI*.5);
}

 return _st;
}
float circle(in vec2 _st, in float _radius){
 vec2 dist = _st-vec2(0.5);
 return 1.-smoothstep(_radius-(_radius*0.01),
 _radius+(_radius*0.01),
 dot(dist,dist)*4.0);
}
void main (void) {
 vec2 st = gl_FragCoord.xy/u_resolution.xy;
 st = tile(st,1.0);
 st = rotate2D(st,-PI*abs(sin(u_time*.01)));
 st = rotateTilePattern(st*1.);
 st = rotate2D(st,PI*u_time*.011);
 st = tile(st,1.5);
 st = brickTile(st,2.0);
 st = rotateTilePattern(st);
 vec3 color = vec3(step(st.x,st.y));
 vec3 color2 = vec3(circle(st,0.5));
 vec3 color3 = step(color,color2);
 vec3 color4=mix(vec3(color),vec3(color2),color3);
 


 
 st = tile(st,2.0);
 
 
 gl_FragColor = vec4(color4,1.0);
 
}

Week 1 Homework

I think my first post was removed so this is a repost!

My first experiment was very simple. I used u_time to create a rising animation between turquoise and blue.

download-5

// Author:
// Title:blue&green rise

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float multiplier = 0.8;
void main() {
 
 vec2 st= gl_FragCoord.xy/u_resolution.xy;
 vec3 blue=vec3(0.012,0.739,1.000);
 vec3 green=vec3(0.454,1.000,0.741);
 vec3 color= mix(blue, green, st.x);
 color=mix(blue,green,smoothstep(abs(sin(u_time*multiplier)),1.0, st.y));
 gl_FragColor = vec4(color,1.0);
 
}

My second experiment was playing around with HSB values and I played around with u_time once again to create an animation that scrolls through different hues in the red channel. I found that copying and pasting variables in different spots was a good way to understand how the code works.

download-6


<img class="alignnone size-medium wp-image-126" src="http://blog.ocad.ca/wordpress/digf3011-fw2021-01/files/2021/01/download-6-300x300.png" alt="download-6" width="300" height="300" />

// Authour: Max Shapovalov
// Title: HSB Code
// Source: Jeremy Rotsztain

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float multiplier =0.1;
float x=0.1;
#define PI 3.1415926535

// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main() {

// get the xy coordinate & normalize to [0, 1] range
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;

// set a fill color with hsb
// store as vec3
vec3 hsb;
hsb.r = 1.0; // animate hue with time
hsb.g = -st.x+st.y; // saturation
hsb.b = u_resolution.y/1000.0; // brightness

if( true ){

// color wash
// same calculation as above with slight x-offset
hsb.r = u_time*0.160 + st.x*0.304;
}

if( false ){

// distanced based hue
float d = distance( st, vec2(0.50,0.500))*1.489;
hsb.r = d;

// animate hue over time
hsb.r = sin(u_time*PI*0.2+d);
}

// use custom function to translate hsv to rgb color space
vec3 color = hsb2rgb(hsb);

gl_FragColor = vec4(color, 1.0);
}