Watch
3
0
Fork
You've already forked raylib-cs
0

Additional resources from the Raylib repo.

This commit is contained in:
Meatcorps 2026-05-21 06:09:28 +02:00
commit ce3a7da69b
51 changed files with 41499 additions and 0 deletions

View file

@ -0,0 +1,18 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main()
{
vec4 texelColor = texture2D(texture0, fragTexCoord);
if (texelColor.a == 0.0) discard;
gl_FragColor = texelColor*fragColor*colDiffuse;
}

View file

@ -0,0 +1,78 @@
#version 120
// Input from the vertex shader
varying vec2 fragTexCoord;
// Output color for the screen
varying vec4 finalColor;
uniform sampler2D texture0;
uniform vec2 resolution;
// Fontsize less then 9 may be not complete
uniform float fontSize;
float GreyScale(in vec3 col)
{
return dot(col, vec3(0.2126, 0.7152, 0.0722));
}
float GetCharacter(float n, vec2 p)
{
p = floor(p*vec2(-4.0, 4.0) + 2.5);
// Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
{
float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
// This checked if the 'a'-th bit of 'n' was set
float shiftedN = floor(n/pow(2.0, a));
if (mod(shiftedN, 2.0) == 1.0)
{
return 1.0; // The bit is on
}
}
return 0.0; // The bit is off, or we are outside the grid
}
// -----------------------------------------------------------------------------
// Main shader logic
// -----------------------------------------------------------------------------
void main()
{
vec2 charPixelSize = vec2(fontSize, fontSize);
vec2 uvCellSize = charPixelSize / resolution;
// The cell size is based on the fontSize set by application
vec2 cellUV = floor(fragTexCoord / uvCellSize)*uvCellSize;
vec3 cellColor = texture2D(texture0, cellUV).rgb;
// Gray is used to define what character will be selected to draw
float gray = GreyScale(cellColor);
float n = 4096.0;
// Character set from https://www.shadertoy.com/view/lssGDj
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
if (gray > 0.2) n = 65600.0; // :
if (gray > 0.3) n = 18725316.0; // v
if (gray > 0.4) n = 15255086.0; // o
if (gray > 0.5) n = 13121101.0; // &
if (gray > 0.6) n = 15252014.0; // 8
if (gray > 0.7) n = 13195790.0; // @
if (gray > 0.8) n = 11512810.0; // #
vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
// cellColor and charShape will define the color of the char
vec3 color = cellColor*GetCharacter(n, p);
gl_FragColor = vec4(color, 1.0);
}

View file

@ -0,0 +1,56 @@
#version 120
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec4 fragColor;
varying vec3 fragNormal;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform vec3 viewPos;
uniform float numBands;
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
};
uniform Light lights[4];
void main()
{
vec4 texColor = texture2D(texture0, fragTexCoord);
vec3 baseColor = texColor.rgb * fragColor.rgb * colDiffuse.rgb;
vec3 norm = normalize(fragNormal);
float lightAccum = 0.08; // ambient floor
for (int i = 0; i < 4; i++)
{
if (lights[i].enabled == 1)
{
vec3 lightDir;
if (lights[i].type == 0)
{
// Directional: direction is from position toward target.
lightDir = normalize(lights[i].position - lights[i].target);
}
else
{
// Point: direction from surface to light.
lightDir = normalize(lights[i].position - fragPosition);
}
float NdotL = max(dot(norm, lightDir), 0.0);
// Quantize NdotL into numBands discrete steps.
float quantized = min(floor(NdotL * numBands), numBands - 1.0) / (numBands - 1.0);
lightAccum += quantized * lights[i].color.r;
}
}
lightAccum = clamp(lightAccum, 0.0, 1.0);
gl_FragColor = vec4(baseColor * lightAccum, texColor.a * colDiffuse.a);
}

View file

@ -0,0 +1,48 @@
#version 120
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
attribute vec4 vertexColor;
uniform mat4 mvp;
uniform mat4 matModel;
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec4 fragColor;
varying vec3 fragNormal;
// inverse() and transpose() are not built-in until GLSL 1.40
mat3 inverse(mat3 m)
{
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
float b01 = a22*a11 - a12*a21;
float b11 = -a22*a10 + a12*a20;
float b21 = a21*a10 - a11*a20;
float det = a00*b01 + a01*b11 + a02*b21;
return mat3(b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11),
b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) / det;
}
mat3 transpose(mat3 m)
{
return mat3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
void main()
{
fragPosition = vec3(matModel * vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
fragNormal = normalize(normalMatrix * vertexNormal);
gl_Position = mvp * vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,31 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform float contrast;
uniform float saturation;
uniform float brightness;
void main()
{
vec4 texel = texture2D(texture0, fragTexCoord); // Get texel color
// Apply contrast
texel.rgb = (texel.rgb - 0.5)*(contrast/100.0 + 1.0) + 0.5;
// Apply brightness
texel.rgb = texel.rgb + brightness/100.0;
// Apply saturation
float intensity = dot(texel.rgb, vec3(0.299, 0.587, 0.114));
texel.rgb = (texel.rgb - intensity)*saturation/100.0 + texel.rgb;
// Output resulting color
gl_FragColor = texel;
}

View file

@ -0,0 +1,24 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform vec4 colDiffuse;
uniform float divider;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor0 = texture2D(texture0, fragTexCoord);
vec4 texelColor1 = texture2D(texture1, fragTexCoord);
float x = fract(fragTexCoord.s);
float final = smoothstep(divider - 0.1, divider + 0.1, x);
gl_FragColor = mix(texelColor0, texelColor1, final);
}

View file

@ -0,0 +1,27 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec3 fragPosition;
// Input uniform values
uniform sampler2D equirectangularMap;
vec2 SampleSphericalMap(vec3 v)
{
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
uv *= vec2(0.1591, 0.3183);
uv += 0.5;
return uv;
}
void main()
{
// Normalize local position
vec2 uv = SampleSphericalMap(normalize(fragPosition));
// Fetch color from texture map
vec3 color = texture2D(equirectangularMap, uv).rgb;
// Calculate final fragment color
gl_FragColor = vec4(color, 1.0);
}

View file

@ -0,0 +1,20 @@
#version 120
// Input vertex attributes
attribute vec3 vertexPosition;
// Input uniform values
uniform mat4 matProjection;
uniform mat4 matView;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
void main()
{
// Calculate fragment position based on model transformations
fragPosition = vertexPosition;
// Calculate final vertex position
gl_Position = matProjection*matView*vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,58 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Custom variables
const float PI = 3.14159265358979323846;
uniform float uTime;
float divisions = 5.0;
float angle = 0.0;
vec2 VectorRotateTime(vec2 v, float speed)
{
float time = uTime*speed;
float localTime = fract(time); // The time domain this works on is 1 sec
if ((localTime >= 0.0) && (localTime < 0.25)) angle = 0.0;
else if ((localTime >= 0.25) && (localTime < 0.50)) angle = PI/4.0*sin(2.0*PI*localTime - PI/2.0);
else if ((localTime >= 0.50) && (localTime < 0.75)) angle = PI*0.25;
else if ((localTime >= 0.75) && (localTime < 1.00)) angle = PI/4.0*sin(2.0*PI*localTime);
// Rotate vector by angle
v -= 0.5;
v = mat2(cos(angle), -sin(angle), sin(angle), cos(angle))*v;
v += 0.5;
return v;
}
float Rectangle(in vec2 st, in float size, in float fill)
{
float roundSize = 0.5 - size/2.0;
float left = step(roundSize, st.x);
float top = step(roundSize, st.y);
float bottom = step(roundSize, 1.0 - st.y);
float right = step(roundSize, 1.0 - st.x);
return (left*bottom*right*top)*fill;
}
void main()
{
vec2 fragPos = fragTexCoord;
fragPos.xy += uTime/9.0;
fragPos *= divisions;
vec2 ipos = floor(fragPos); // Get the integer coords
vec2 fpos = fract(fragPos); // Get the fractional coords
fpos = VectorRotateTime(fpos, 0.2);
float alpha = Rectangle(fpos, 0.216, 1.0);
vec3 color = vec3(0.3, 0.3, 0.3);
gl_FragColor = vec4(color, alpha);
}

View file

@ -0,0 +1,57 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;
struct Light {
int enabled;
int type; // Unused in this demo
vec3 position;
vec3 target; // Unused in this demo
vec4 color;
};
const int NR_LIGHTS = 4;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPosition;
const float QUADRATIC = 0.032;
const float LINEAR = 0.09;
void main()
{
vec3 fragPosition = texture2D(gPosition, fragTexCoord).rgb;
vec3 normal = texture2D(gNormal, fragTexCoord).rgb;
vec3 albedo = texture2D(gAlbedoSpec, fragTexCoord).rgb;
float specular = texture2D(gAlbedoSpec, fragTexCoord).a;
vec3 ambient = albedo*vec3(0.1);
vec3 viewDirection = normalize(viewPosition - fragPosition);
for (int i = 0; i < NR_LIGHTS; i++)
{
if (lights[i].enabled == 0) continue;
vec3 lightDirection = lights[i].position - fragPosition;
vec3 diffuse = max(dot(normal, lightDirection), 0.0)*albedo*lights[i].color.xyz;
vec3 halfwayDirection = normalize(lightDirection + viewDirection);
float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0);
vec3 specular = specular*spec*lights[i].color.xyz;
// Attenuation
float distance = length(lights[i].position - fragPosition);
float attenuation = 1.0/(1.0 + LINEAR*distance + QUADRATIC*distance*distance);
diffuse *= attenuation;
specular *= attenuation;
ambient += diffuse + specular;
}
gl_FragColor = vec4(ambient, 1.0);
}

View file

@ -0,0 +1,16 @@
#version 120
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
// Output vertex attributes (to fragment shader)
varying vec2 fragTexCoord;
void main()
{
fragTexCoord = vertexTexCoord;
// Calculate final vertex position
gl_Position = vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,28 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
// Input uniform values
uniform sampler2D depthTexture;
uniform bool flipY;
float nearPlane = 0.1;
float farPlane = 100.0;
void main()
{
// Handle potential Y-flipping
vec2 texCoord = fragTexCoord;
if (flipY)
texCoord.y = 1.0 - texCoord.y;
// Sample depth texture
float depth = texture2D(depthTexture, texCoord).r;
// Linearize depth
float linearDepth = (2.0*nearPlane)/(farPlane + nearPlane - depth*(farPlane - nearPlane));
// Output final color
gl_FragColor = vec4(vec3(linearDepth), 1.0);
}

View file

@ -0,0 +1,17 @@
#version 120
#extension GL_EXT_frag_depth : enable
varying vec2 fragTexCoord;
varying vec4 fragColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main()
{
vec4 texelColor = texture2D(texture0, fragTexCoord);
gl_FragColor = texelColor*colDiffuse*fragColor;
gl_FragDepthEXT = 1.0 - gl_FragCoord.z;
}

View file

@ -0,0 +1,58 @@
#version 120
/*************************************************************************************
The Sieve of Eratosthenes -- a simple shader by ProfJski
An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
The screen is divided into a square grid of boxes, each representing an integer value
Each integer is tested to see if it is a prime number. Primes are colored white
Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer
You can change the scale variable to make a larger or smaller grid
Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers
WARNING: If you make scale too large, your GPU may bog down!
***************************************************************************************/
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Make a nice spectrum of colors based on counter and maxSize
vec4 Colorizer(float counter, float maxSize)
{
float red = 0.0, green = 0.0, blue = 0.0;
float normsize = counter/maxSize;
red = smoothstep(0.3, 0.7, normsize);
green = sin(3.14159*normsize);
blue = 1.0 - smoothstep(0.0, 0.4, normsize);
return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0);
}
void main()
{
vec4 color = vec4(1.0);
float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid
float value = scale*floor(fragTexCoord.y*scale) + floor(fragTexCoord.x*scale); // Group pixels into boxes representing integer values
int valuei = int(value);
//if ((valuei == 0) || (valuei == 1) || (valuei == 2)) gl_FragColor = vec4(1.0);
//else
{
//for (int i = 2; (i < int(max(2.0, sqrt(value) + 1.0))); i++)
// NOTE: On GLSL 100 for loops are restricted and loop condition must be a constant
// Tested on RPI, it seems loops are limited around 60 iteractions
for (int i = 2; i < 48; i++)
{
if ((value - float(i)*floor(value/float(i))) <= 0.0)
{
gl_FragColor = Colorizer(float(i), scale);
//break; // Uncomment to color by the largest factor instead
}
}
}
}

View file

@ -0,0 +1,42 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Input size in pixels of the textures
uniform vec2 resolution;
void main()
{
// Size of one pixel in texture coordinates (from 0.0 to 1.0)
float x = 1.0/resolution.x;
float y = 1.0/resolution.y;
// Status of the current cell (1 = alive, 0 = dead)
int origValue = (texture2D(texture0, fragTexCoord).r < 0.1)? 1 : 0;
// Sum of alive neighbors
int sumValue = (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Top-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Top
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Top-right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Bottom-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Bottom
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Bottom-right
// Game of life rules:
// Current cell remains alive when 2 or 3 neighbors are alive, dies otherwise
// Current cell goes from dead to alive when exactly 3 neighbors are alive
if (((origValue == 1) && (sumValue == 2)) || sumValue == 3)
gl_FragColor = vec4(0.0, 0.0, 0.0, 255.0); // Alive: draw the pixel black
else
gl_FragColor = fragColor; // Dead: draw the pixel with the background color, RAYWHITE
}

View file

@ -0,0 +1,34 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec3 fragNormal;
varying vec4 fragColor;
// TODO: Is there some alternative for GLSL100
//layout (location = 0) out vec3 gPosition;
//layout (location = 1) out vec3 gNormal;
//layout (location = 2) out vec4 gAlbedoSpec;
//uniform vec3 gPosition;
//uniform vec3 gNormal;
//uniform vec4 gAlbedoSpec;
// Input uniform values
uniform sampler2D texture0; // Diffuse texture
uniform sampler2D specularTexture;
void main()
{
// Store the fragment position vector in the first gbuffer texture
//gPosition = fragPosition;
// Store the per-fragment normals into the gbuffer
//gNormal = normalize(fragNormal);
// Store the diffuse per-fragment color
gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb;
// Store specular intensity in gAlbedoSpec's alpha component
gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r;
}

View file

@ -0,0 +1,60 @@
#version 120
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
attribute vec4 vertexColor;
// Input uniform values
uniform mat4 matModel;
uniform mat4 matView;
uniform mat4 matProjection;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec3 fragNormal;
varying vec4 fragColor;
// https://github.com/glslify/glsl-inverse
mat3 inverse(mat3 m)
{
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
float b01 = a22*a11 - a12*a21;
float b11 = -a22*a10 + a12*a20;
float b21 = a21*a10 - a11*a20;
float det = a00*b01 + a01*b11 + a02*b21;
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
}
// https://github.com/glslify/glsl-transpose
mat3 transpose(mat3 m)
{
return mat3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
void main()
{
// Calculate vertex attributes for fragment shader
vec4 worldPos = matModel*vec4(vertexPosition, 1.0);
fragPosition = worldPos.xyz;
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
fragNormal = normalMatrix*vertexNormal;
// Calculate final vertex position
gl_Position = matProjection*matView*worldPos;
}

View file

@ -0,0 +1,17 @@
#version 120
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
varying vec2 fragTexCoord;
varying vec4 fragColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main()
{
vec4 texelColor = texture2D(texture0, fragTexCoord);
gl_FragColor = texelColor*colDiffuse*fragColor;
gl_FragDepthEXT = gl_FragCoord.z;
}

View file

@ -0,0 +1,291 @@
#version 120
#extension GL_EXT_frag_depth : enable //Extension required for writing depth
#extension GL_OES_standard_derivatives : enable //Extension used for fwidth()
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Custom Input Uniform
uniform vec3 camPos;
uniform vec3 camDir;
uniform vec2 screenCenter;
#define ZERO 0
// SRC: https://learnopengl.com/Advanced-OpenGL/Depth-testing
float CalcDepth(in vec3 rd, in float Idist)
{
float local_z = dot(normalize(camDir),rd)*Idist;
return (1.0/(local_z) - 1.0/0.01)/(1.0/1000.0 -1.0/0.01);
}
// SRC: https://iquilezles.org/articles/distfunctions/
float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
{
p.x = abs(p.x);
float l = length(p.xy);
p.xy = mat2(-c.x, c.y,
c.y, c.x)*p.xy;
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
(p.x>0.0)?p.y:l);
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
vec2 d = abs(q) - w;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
// r = sphere's radius
// h = cutting's plane's position
// t = thickness
float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
{
// Six way symetry Transformation
vec3 ap = abs(p);
if (ap.x < max(ap.y, ap.z)){
if (ap.y < ap.z) ap.xz = ap.zx;
else ap.xy = ap.yx;
}
vec2 q = vec2(length(ap.yz), ap.x);
float w = sqrt(r*r-h*h);
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t;
}
// SRC: https://iquilezles.org/articles/boxfunctions
vec2 iBox(in vec3 ro, in vec3 rd, in vec3 rad)
{
vec3 m = 1.0/rd;
vec3 n = m*ro;
vec3 k = abs(m)*rad;
vec3 t1 = -n - k;
vec3 t2 = -n + k;
return vec2(max(max(t1.x, t1.y), t1.z),
min(min(t2.x, t2.y), t2.z));
}
vec2 opU(vec2 d1, vec2 d2)
{
return (d1.x<d2.x) ? d1 : d2;
}
vec2 map(in vec3 pos)
{
vec2 res = vec2(sdHorseshoe(pos-vec3(-1.0,0.08, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5) ;
res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5)) ;
return res;
}
// SRC: https://www.shadertoy.com/view/Xds3zN
vec2 raycast(in vec3 ro, in vec3 rd)
{
vec2 res = vec2(-1.0,-1.0);
float tmin = 1.0;
float tmax = 20.0;
// Raytrace floor plane
float tp1 = (-ro.y)/rd.y;
if (tp1>0.0)
{
tmax = min(tmax, tp1);
res = vec2(tp1, 1.0);
}
float t = tmin;
for (int i=0; i<70 ; i++)
{
if (t>tmax) break;
vec2 h = map(ro+rd*t);
if (abs(h.x) < (0.0001*t))
{
res = vec2(t,h.y);
break;
}
t += h.x;
}
return res;
}
// https://iquilezles.org/articles/rmshadows
float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
{
// bounding volume
float tp = (0.8-ro.y)/rd.y; if (tp>0.0) tmax = min(tmax, tp);
float res = 1.0;
float t = mint;
for (int i=ZERO; i<24; i++)
{
float h = map(ro + rd*t).x;
float s = clamp(8.0*h/t,0.0,1.0);
res = min(res, s);
t += clamp(h, 0.01, 0.2);
if (res<0.004 || t>tmax) break;
}
res = clamp(res, 0.0, 1.0);
return res*res*(3.0-2.0*res);
}
// https://iquilezles.org/articles/normalsSDF
vec3 calcNormal(in vec3 pos)
{
vec2 e = vec2(1.0, -1.0)*0.5773*0.0005;
return normalize(e.xyy*map(pos + e.xyy).x +
e.yyx*map(pos + e.yyx).x +
e.yxy*map(pos + e.yxy).x +
e.xxx*map(pos + e.xxx).x);
}
// https://iquilezles.org/articles/nvscene2008/rwwtt.pdf
float calcAO(in vec3 pos, in vec3 nor)
{
float occ = 0.0;
float sca = 1.0;
for (int i=ZERO; i<5; i++)
{
float h = 0.01 + 0.12*float(i)/4.0;
float d = map(pos + h*nor).x;
occ += (h-d)*sca;
sca *= 0.95;
if (occ>0.35) break;
}
return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y);
}
// https://iquilezles.org/articles/checkerfiltering
float checkersGradBox(in vec2 p)
{
// filter kernel
vec2 w = fwidth(p) + 0.001;
// analytical integral (box filter)
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
// xor pattern
return 0.5 - 0.5*i.x*i.y;
}
// https://www.shadertoy.com/view/tdS3DG
vec4 render(in vec3 ro, in vec3 rd)
{
// background
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
// raycast scene
vec2 res = raycast(ro,rd);
float t = res.x;
float m = res.y;
if (m>-0.5)
{
vec3 pos = ro + t*rd;
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
vec3 ref = reflect(rd, nor);
// material
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
float ks = 1.0;
if (m<1.5)
{
float f = checkersGradBox(3.0*pos.xz);
col = 0.15 + f*vec3(0.05);
ks = 0.4;
}
// lighting
float occ = calcAO(pos, nor);
vec3 lin = vec3(0.0);
// sun
{
vec3 lig = normalize(vec3(-0.5, 0.4, -0.6));
vec3 hal = normalize(lig-rd);
float dif = clamp(dot(nor, lig), 0.0, 1.0);
//if (dif>0.0001)
dif *= calcSoftshadow(pos, lig, 0.02, 2.5);
float spe = pow(clamp(dot(nor, hal), 0.0, 1.0),16.0);
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
//spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0);
lin += col*2.20*dif*vec3(1.30,1.00,0.70);
lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks;
}
// sky
{
float dif = sqrt(clamp(0.5+0.5*nor.y, 0.0, 1.0));
dif *= occ;
float spe = smoothstep(-0.2, 0.2, ref.y);
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0);
//if (spe>0.001)
spe *= calcSoftshadow(pos, ref, 0.02, 2.5);
lin += col*0.60*dif*vec3(0.40,0.60,1.15);
lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks;
}
// back
{
float dif = clamp(dot(nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0)*clamp(1.0-pos.y,0.0,1.0);
dif *= occ;
lin += col*0.55*dif*vec3(0.25,0.25,0.25);
}
// sss
{
float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
dif *= occ;
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
}
col = lin;
col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t));
}
return vec4(vec3(clamp(col,0.0,1.0)),t);
}
vec3 CalcRayDir(vec2 nCoord){
vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0)));
vec3 vertical = normalize(cross(horizontal,camDir));
return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y);
}
mat3 setCamera()
{
vec3 cw = normalize(camDir);
vec3 cp = vec3(0.0, 1.0 ,0.0);
vec3 cu = normalize(cross(cw,cp));
vec3 cv = (cross(cu,cw));
return mat3(cu, cv, cw);
}
void main()
{
vec2 nCoord = (gl_FragCoord.xy - screenCenter.xy)/screenCenter.y;
mat3 ca = setCamera();
// focal length
float fl = length(camDir);
vec3 rd = ca*normalize(vec3(nCoord,fl));
vec3 color = vec3(nCoord/2.0 + 0.5, 0.0);
float depth = gl_FragCoord.z;
{
vec4 res = render(camPos - vec3(0.0, 0.0, 0.0) , rd);
color = res.xyz;
depth = CalcDepth(rd,res.w);
}
gl_FragColor = vec4(color , 1.0);
gl_FragDepthEXT = depth;
}

View file

@ -0,0 +1,80 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
uniform vec2 c; // c.x = real, c.y = imaginary component. Equation done is z^2 + c
uniform vec2 offset; // Offset of the scale.
uniform float zoom; // Zoom of the scale.
// NOTE: Maximum number of shader for-loop iterations depend on GPU,
// for example, on RasperryPi for this examply only supports up to 60
const int maxIterations = 255; // Max iterations to do
const float colorCycles = 1.0; // Number of times the color palette repeats
// Square a complex number
vec2 ComplexSquare(vec2 z)
{
return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0);
}
// Convert Hue Saturation Value (HSV) color into RGB
vec3 Hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz)*6.0 - K.www);
return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main()
{
/**********************************************************************************************
Julia sets use a function z^2 + c, where c is a constant
This function is iterated until the nature of the point is determined
If the magnitude of the number becomes greater than 2, then from that point onward
the number will get bigger and bigger, and will never get smaller (tends towards infinity)
2^2 = 4, 4^2 = 8 and so on
So at 2 we stop iterating
If the number is below 2, we keep iterating
But when do we stop iterating if the number is always below 2 (it converges)?
That is what maxIterations is for
Then we can divide the iterations by the maxIterations value to get a normalized value
that we can then map to a color
We use dot product (z.x*z.x + z.y*z.y) to determine the magnitude (length) squared
And once the magnitude squared is > 4, then magnitude > 2 is also true (saves computational power)
*************************************************************************************************/
// The pixel coordinates are scaled so they are on the mandelbrot scale
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
z.x += offset.x;
z.y += offset.y;
int iter = 0;
for (int iterations = 0; iterations < maxIterations; iterations++)
{
z = ComplexSquare(z) + c; // Iterate function
if (dot(z, z) > 4.0) break;
iter = iterations;
}
// Another few iterations decreases errors in the smoothing calculation
// See http://linas.org/art-gallery/escape/escape.html for more information
z = ComplexSquare(z) + c;
z = ComplexSquare(z) + c;
// This last part smooths the color (again see link above)
float smoothVal = float(iter) + 1.0 - (log(log(length(z)))/log(2.0));
// Normalize the value so it is between 0 and 1
float norm = smoothVal/float(maxIterations);
// If in set, color black. 0.999 allows for some float accuracy error
if (norm > 0.999) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
else gl_FragColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0, 1.0)), 1.0);
}

Some files were not shown because too many files have changed in this diff Show more