shader:start

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
shader:start [2025/05/21 12:20] – [Normalized input Coordinates] mhshader:start [2025/06/02 21:23] (current) – external edit 127.0.0.1
Line 4: Line 4:
  
 ===== Coding Shaders ===== ===== Coding Shaders =====
 +
 +Shaders take a coordinate for each pixel on it's canvas and outputs an rgba value for that coordinate.
  
 ==== Normalized input Coordinates ==== ==== Normalized input Coordinates ====
  
-Generally the ''vec2 uv'' is used to describe a normalized input coordinates by dividing the coordinate by the current resolution :+Generally the **''vec2 uv''** is used to describe a normalized input coordinates by dividing the coordinate by the current resolution :
  
-Different compilers use different syntax to describe the resolution.+Different compilers use different syntax to describe the resolution. Here we'll use Shadertoy's standard.
  
 <code glsl> <code glsl>
Line 36: Line 38:
 To draw a circle, define a center point where the circle should be drawn and use a length function to calculate the length of the coordinates to this center. To draw a circle, define a center point where the circle should be drawn and use a length function to calculate the length of the coordinates to this center.
  
-If it is larger than a value draw a colorif not draw another color.+One simple way is to compare the length to a value and draw a color if it's less and another if it's more : 
 + 
 +<code glsl> 
 +    float d = length(uv); 
 +    float c = d; 
 +     
 +    if (d < .3) c = 0.0 ; else c = 1.0; 
 + 
 +    // Output to screen 
 +    fragColor = vec4(vec3(c),1.0); 
 +</code> 
 + 
 +However, __this is not recommended__ as it creates a discontinuity of the values where they jump from 0.0 to 1.0 when reaching the radius of the circle. 
 + 
 +It's better to use a **''smoothstep''** function like this : 
 + 
 +<code glsl> 
 +    float d = length(uv); 
 +    float r = .3 
 +    float c = smoothstep(r, r-.02, d); 
 + 
 +    // Output to screen 
 +    fragColor = vec4(vec3(c), 1.0); 
 +</code> 
 + 
 +Here in a dedicated function : 
 + 
 +<code glsl>  
 +float drawCircle(vec2 uv, vec2 p, float r, float b) { 
 +//p for Position, r for Radius, b for edge Blur 
 + 
 +    float d = length(uv-p); //This draws to the  
 +    float c = smoothstep(r, r-b, d); 
 +     
 +    return c; 
 +
 +</code> 
 + 
 +In the main function, draw multiple items by adding or subtracting to the color variable (the one being output in the end). 
 + 
 +Drawing multiple circles for example : 
 + 
 +<code glsl> 
 +    float b = 0.01; // Blur of edges of circles 
 +     
 +    float c = drawCircle(uv, vec2(0.), 0.4, b); 
 +    c -= drawCircle(uv, vec2(-.13, 0.12), 0.08, b); 
 +    c -= drawCircle(uv, vec2(.13, 0.12), 0.08, b); 
 +</code> 
 + 
 +<WRAP info> 
 +**Note :** when adding or removing regions in this manner, the color value for each RGB component of each pixel **can go** below 0.0 and above 1.0. 
 + 
 +Shaders will automatically clamp the output between 0.0 and 1.0 but during the calculation of the color, the real value must be taken into account. 
 + 
 +This behavior can lead to unexpected behaviors and colors in certain regions where multiple subtractions/additions have been applied.</WRAP> 
 + 
 +==== Rectangle ==== 
 + 
 +To draw a rectangle we can use a function that draws bands using **''smoothstep''** and then multiply it twice to draw a band horizontally and another band vertically. 
 + 
 +The band function would look like this 
 + 
 +<code glsl> 
 +float drawBand(float t, float start, float end, float blur){ 
 +    float step1 = smoothstep(start-blur, start+blur, t); 
 +    float step2 = smoothstep(end+blur, end-blur, t); //This one is inverted because it's on the other side, going from 1 to 0. 
 +     
 +    return step1*step2; 
 +
 +</code> 
 + 
 +Then get a rectangle by calling this function twice on the x and y : 
 + 
 +<code glsl> 
 +    float mask = 0.; 
 +    float b = .01; 
 +     
 +    mask = drawBand(uv.x, -.2, .2, b); 
 +    mask *= drawBand(uv.y, -.2, .2, b); 
 +</code> 
 +==== Adding Color ==== 
 + 
 +Add color by using a **''vec3 col''** (usually named this way) and creating masks (grayscale, with full black where color won't draw and full white where color draws). 
 + 
 +Simply multiply color by the mask. 
 + 
 +For the circle example above for example, it would look something like this : 
 + 
 +<code glsl> 
 +   vec3 col = vec3(1., 1., 0.); //Initialize color to full yellow. 
 +     
 +    float b = 0.01; // Blur of edges of circles 
 +     
 +    float mask = drawCircle(uv, vec2(0.), 0.4, b); 
 +    mask -= drawCircle(uv, vec2(-.13, 0.12), 0.08, b); 
 +    mask -= drawCircle(uv, vec2(.13, 0.12), 0.08, b); 
 +     
 + 
 +    col *= mask; 
 +</code>
 ===== ISF ===== ===== ISF =====
  
  • shader/start.1747822851.txt.gz
  • Last modified: 2025/06/02 21:18
  • (external edit)