mirror of
https://github.com/terkelg/awesome-creative-coding.git
synced 2025-08-30 04:09:49 +02:00
removed notes folder
This commit is contained in:
136
notes/shaders.md
136
notes/shaders.md
@@ -1,136 +0,0 @@
|
||||
# Shaders
|
||||
> The dark magic – master this, and you rule the world
|
||||
|
||||
## Definitions
|
||||
### GLSL
|
||||
GLSL is the shader language used for WebGL.
|
||||
|
||||
### GLSL Fragment shaders
|
||||
Fragment shaders are responsible for giving each pixel their color.
|
||||
Fragment shaders are run on each pixel: they're not at all aware of their surrounding pixels. This is a challenging constraint at times, but also why they're so speedy.
|
||||
|
||||
Fragment shaders also don't have much to use to find out where they are on the screen either. gl_FragCoord.xy will give you the exact position in pixels, but if you resize the screen the size of the object won't change to fit it.
|
||||
|
||||
So we pass in a uniform value that contains the size, or resolution, of the screen. A uniform is a value passed in from JavaScript that is the same for every pixel in the shader. It's useful for giving the fragment shader some context to work with: for example, you might also pass in the time in seconds to animate the output.
|
||||
|
||||
By dividing gl_FragCoord.xy by iResolution, we can get a value between 0 and 1 for the pixel's position on the screen:
|
||||
```
|
||||
vec2 p = gl_FragCoord.xy / iResolution;
|
||||
```
|
||||
|
||||
### GLSL Vertex Shaders
|
||||
|
||||
### uniforms:
|
||||
These are a class of global variable that can be defined in GLSL shaders. They represent values that are uniform (unchanging) over the course of a rendering operation. Their values are set from outside of the shader, and they cannot be changed from within a shader.
|
||||
|
||||
### Swizzling
|
||||
Beyond being a great name — is a nice feature in GLSL for accessing the properties of a vector.
|
||||
You can get a single float from a vector using .r, .g, .b or .a. For example:
|
||||
|
||||
```
|
||||
vec4(1, 2, 3, 4).r == 1.0
|
||||
vec4(1, 2, 3, 4).g == 2.0
|
||||
vec4(1, 2, 3, 4).b == 3.0
|
||||
vec4(1, 2, 3, 4).a == 4.0
|
||||
```
|
||||
|
||||
But you can also create new vectors from combinations of their components like so:
|
||||
```
|
||||
vec4(1, 2, 3, 4).rb == vec3(1, 3)
|
||||
vec4(1, 2, 3, 4).rgg == vec3(1, 2, 2)
|
||||
vec4(1, 2, 3, 4).ggab == vec3(2, 2, 4, 3)
|
||||
```
|
||||
In addition to .rgba, you can also use .xyzw. These are equivalent, but if you're using the vector for a position instead of a color it's easy to reason about when using the latter.
|
||||
|
||||
### Finding the midpoint
|
||||
The midpoint is just the average of two values, e.g. ```(x1 + x2) / 2```
|
||||
To calculate the midpoint of a vector, you just have to calculate the midpoint of each of its values:
|
||||
```
|
||||
vec2((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0);
|
||||
```
|
||||
*2.0 because there's two values, remember average calculations*
|
||||
|
||||
That's a little verbose though. Can we make it shorter?
|
||||
|
||||
### Piecewise Operations
|
||||
You can treat vectors a little like normal numbers: they can be added, multiplied, divided and subtracted just the same in GLSL!
|
||||
```
|
||||
p1 + p2 == vec2(p1.x + p2.x, p1.y + p2.y)
|
||||
p1 - p2 == vec2(p1.x - p2.x, p1.y - p2.y)
|
||||
p1 * p2 == vec2(p1.x * p2.x, p1.y * p2.y)
|
||||
p1 / p2 == vec2(p1.x / p2.x, p1.y / p2.y)
|
||||
```
|
||||
This is called a piecewise operation, because it is applied to each piece of the vector individually.
|
||||
|
||||
You can even apply a piecewise operation to a vector using float, e.g.:
|
||||
```
|
||||
p1 + 1.0 == vec2(p1.x + 1.0, p2.x + 1.0)
|
||||
p1 - 1.0 == vec2(p1.x - 1.0, p2.x - 1.0)
|
||||
p1 * 5.0 == vec2(p1.x * 5.0, p2.x * 5.0)
|
||||
p1 / 5.0 == vec2(p1.x / 5.0, p2.x / 5.0)
|
||||
```
|
||||
|
||||
So to get the midpoint without using vec2 or any swizzling:
|
||||
```
|
||||
vec2 midpoint(vec2 p1, vec2 p2) {
|
||||
return p1 / 2.0 + p2 / 2.0;
|
||||
}
|
||||
```
|
||||
|
||||
## Boolean Comparisons
|
||||
You can compare float values (but not vectors) using run-of-the-mill boolean operators, e.g.:
|
||||
```
|
||||
bool value = uv.x > 1.05;
|
||||
bool value = uv.x <= 0.0;
|
||||
bool value = uv.x != 0.5;
|
||||
bool value = uv.y != 0.0 && uv.x != 0.0;
|
||||
bool value = uv.y != 0.0 || uv.x != 0.0;
|
||||
```
|
||||
|
||||
## Distance / length
|
||||
You can check if a point is in a circle by seeing if its distance from the circle's center is smaller than the circle's radius. In GLSL we measure distance using the length() function:
|
||||
```
|
||||
float d = length(p2 - p1)
|
||||
```
|
||||
Much more concise than it would be in JavaScript!
|
||||
All that's left to do is compare that distance to the radius and you should be able to draw that circle out to the screen.
|
||||
|
||||
## Signed Distance Functions (SDF)
|
||||
http://jamie-wong.com/2016/07/15/ray-marching-signed-distance-functions/
|
||||
|
||||
Yep, those words probably make a lot less sense when they're put together like that.
|
||||
|
||||
To start: a **distance function** takes a point as input and returns the distance from a surface as output. In GLSL, you'd mark up a 2D Distance Function like so: ```float distanceFn(vec2 position);```
|
||||
|
||||
A signed distance function (SDF) is very similar, but it returns a negative value when it's inside the surface. You can now very quickly draw out that shape in 2D by checking if the SDF's value is less than zero.
|
||||
|
||||
## Smooth minimum
|
||||
A smooth minimum function takes two values as input, and returns a smoothed out value between the two.
|
||||
There's different types of smooth minimum with different tradeoffs, but here's a few taken from the ever-useful (iquilezles.org)[http://iquilezles.org/www/articles/smin/smin.htm]:
|
||||
|
||||
EXPONENTIAL
|
||||
```
|
||||
float smin( float a, float b, float k )
|
||||
{
|
||||
float res = exp( -k*a ) + exp( -k*b );
|
||||
return -log( res )/k;
|
||||
}
|
||||
```
|
||||
|
||||
POLYNOMIAL
|
||||
```
|
||||
float smin( float a, float b, float k )
|
||||
{
|
||||
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
|
||||
return mix( b, a, h ) - k*h*(1.0-h);
|
||||
}
|
||||
```
|
||||
|
||||
POWER
|
||||
```
|
||||
float smin( float a, float b, float k )
|
||||
{
|
||||
a = pow( a, k ); b = pow( b, k );
|
||||
return pow( (a*b)/(a+b), 1.0/k );
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user