Skip to content

Instantly share code, notes, and snippets.

@CharStiles
Created April 15, 2025 16:49
Show Gist options
  • Save CharStiles/d1574348f4e4be2a84e3be6097d4a0d1 to your computer and use it in GitHub Desktop.
Save CharStiles/d1574348f4e4be2a84e3be6097d4a0d1 to your computer and use it in GitHub Desktop.
#ifdef GL_ES
precision highp float;
#endif
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
uniform vec3 spectrum;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D prevFrame;
uniform sampler2D prevPass;
varying vec3 v_normal;
varying vec2 v_texcoord;
float rand(vec2 co){
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}
// Same, but mirror every second cell at the diagonal as well
vec2 pModGrid2(inout vec2 p, vec2 size) {
vec2 c = floor((p + size*0.5)/size);
p = mod(p + size*0.5, size) - size*0.5;
p *= mod(c,vec2(2))*2. - vec2(1);
p -= size/2.;
if (p.x > p.y) p.xy = p.yx;
return floor(c/2.);
}
vec2 pModMirror2(inout vec2 p, vec2 size) {
vec2 halfsize = size*0.5;
vec2 c = floor((p + halfsize)/size);
p = mod(p + halfsize, size) - halfsize;
p *= mod(c,vec2(2))*2. - vec2(1);
return c;
}
void pR(inout vec2 p, float a) {
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
}
// Maximum/minumum elements of a vector
float vmax(vec2 v) {
return max(v.x, v.y);
}
float vmax(vec3 v) {
return max(max(v.x, v.y), v.z);
}
float vmax(vec4 v) {
return max(max(v.x, v.y), max(v.z, v.w));
}
// Box: correct distance to corners
float fBox(vec3 p, vec3 b) {
vec3 d = abs(p) - b;
return length(max(d, vec3(0))) + vmax(min(d, vec3(0)));
}
// Smooth minimum function for rounding
// Smooth minimum function for rounding
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);
}
// Smooth maximum function for rounding
float smax(float a, float b, float k) {
return -smin(-a, -b, k);
}
// Rounded box function
float fBoxRound(vec3 p, vec3 b, float r) {
vec3 q = abs(p) - b + vec3(r);
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0) - r;
}
float sdRandomCoinCylinders(vec3 p) {
// Number of coin cylinders
const int NUM_COINS = 8;
// Coin parameters
const float coinRadius = 0.5;
const float coinThickness = 0.2;
// Minimum distance to the center
float minDist = 1000.0;
// Generate coin cylinders from random directions
for (int i = 0; i < NUM_COINS; i++) {
// Generate random direction vector
vec3 dir = normalize(vec3(
cos(float(i) * 2.3), // Use golden ratio for pseudo-randomness
sin(float(i) * 1.7),
cos(float(i) * 2.1)
));
// Project point onto the direction vector
vec3 projectedPoint = p - dot(p, dir) * dir;
// Create cylinder oriented along the direction
vec3 localPoint = p - dir * clamp(mod(((-time*3. + float(i))+0.8 ),10.),0.,10.); // Move cylinders away from center
// Cylindrical SDF
float cylinderDist = length(cross(localPoint, dir)) - coinRadius;
float heightDist = abs(dot(localPoint, dir)) - coinThickness;
// Combine cylindrical and height distance
float coinDist = max(cylinderDist, heightDist);
// Track minimum distance
minDist = min(minDist, coinDist);
}
return minDist;
}struct SurfaceInfo {
float distance;
bool isHole;
};
SurfaceInfo scene(vec3 pos) {
//
//
pR(pos.zx,2.3);
pR(pos.xy,-.8);
pR(pos.zy,-.10);
// Parameters for the wavy surface
float amplitude = 01.1; // Height of the waves
float frequency = 01.0; // Frequency of the waves
float thickness = 0.5; // Thickness of the surface
// Create primary wave in x direction
float wave1 = sin(pos.z+9. * frequency) * amplitude;
// Create secondary wave in z direction for the cross-wave effect
// float wave2 = sin(pos.z * frequency ) * (amplitude * 0.5);
// Combine waves
// float combinedWave = wave1 + wave2;
// Calculate distance to the wavy surface
float surfaceDist = abs(pos.y - wave1) - thickness;
// Create perforations (dots)
float dotSpacing = 0.6;
vec2 dotGrid = mod(vec2(pos.x, pos.z), dotSpacing) - dotSpacing * 0.3;
float dotDist = length(dotGrid) - 0.05;
// Detect if we're in a hole
bool isHole = (dotDist < 0.0) && (abs(surfaceDist) < thickness * 2.0);
// Limit the surface to a reasonable size
float bounds = max(abs(pos.x) - 5.0, abs(pos.z) - 5.0);
surfaceDist = max(surfaceDist, bounds);
return SurfaceInfo(surfaceDist, isHole);
}
// Helper function to get just the distance for normal estimation
float sceneDistance(vec3 pos) {
return scene(pos).distance;
}
vec3 estimateNormal(vec3 p) {
float smallNumber = 0.002;
vec3 n = vec3(
sceneDistance(vec3(p.x + smallNumber, p.yz)) -
sceneDistance(vec3(p.x - smallNumber, p.yz)),
sceneDistance(vec3(p.x, p.y + smallNumber, p.z)) -
sceneDistance(vec3(p.x, p.y - smallNumber, p.z)),
sceneDistance(vec3(p.xy, p.z + smallNumber)) -
sceneDistance(vec3(p.xy, p.z - smallNumber))
);
return normalize(n);
}
vec4 lighting(vec3 ray, vec2 id, bool isHole) {
// If this is a hole, return white
if (isHole) {
return vec4(1.0, 1.0, 1.0, 1.0);
}
vec3 norm = estimateNormal(ray);
vec3 light = vec3(0, 0.2, 0.);
float dif = max(dot(norm, light), 0.0);
vec4 retCol = vec4(dif);
// Add ambient light to prevent pure black
float ambient = 0.321;
retCol += vec4(ambient);
vec3 lightRayDir = normalize(light - ray);
retCol += norm.y;
return ((retCol * vec4(norm, 1.0))-0.13 );
}
vec4 trace(vec3 rayO, vec3 dir) {
vec3 ray = rayO;
float dist = 0.;
float totalDist = 0.;
bool isHole = false;
for(int i = 0; i < 128; ++i) {
SurfaceInfo surfInfo = scene(ray);
dist = surfInfo.distance;
isHole = surfInfo.isHole;
totalDist += dist;
ray += dist * dir;
if(dist < 0.01) {
vec4 retCol = 1.0 - (vec4(totalDist) / 5.0);
return (clamp(lighting(ray, ray.xy, isHole) +0.51,0.,1.)).rrrr+0.5;
}
if(totalDist > 2.){
mix(vec4(9./255.,31./255.,117./255.,1.),vec4(9./255.,31./255.,117./255.,1.),rayO.x);
}
}
return mix(vec4(9./255.,31./255.,117./255.,1.),vec4(9./255.,31./255.,117./255.,1.),rayO.x);
}
vec3 integrate(vec3 cur, float dt){
float dx,dy,dz;
dx = (cur.y - cur.x)*.01;
dy = 3.*cur.z*(cur.x) - 8.*cur.y;
dz = cur.y*cur.z - 10.*cur.z;
cur.x += dx*dt;
cur.y += dy*dt;
cur.z += dz*dt;
return cur;
}
vec3 getRdIsometric(inout vec3 ro, vec3 lookAt, vec2 uv){
vec3 rd = normalize(
lookAt -
ro
);
vec3 right = normalize(cross(vec3(0,1,0), rd));
vec3 up = normalize(cross(rd, right));
float zoom = 11.;
ro += right*uv.x*zoom;
ro += up*uv.y*zoom;
return rd;
}
void main(void)
{
vec2 uv = -1. + 2. * v_texcoord;
// uv.y -=0.3;
uv.y*= resolution.y/resolution.x;
pR(uv,0.591);
// uv.y*= 1.2;
// vec3 cam =vec3(cos(time)*time *0.5,(cos(4.*time + 20.) + 1.)*0.3,-5.);
vec3 lookAt = vec3(0,-1.,-1);
vec3 ro = vec3(0,2,0);
vec3 dir = getRdIsometric(ro, lookAt, uv);
//vec3 dir = ro - ro;
vec4 col = trace(ro, dir);
gl_FragColor =col ;
}
#ifdef GL_ES
precision highp float;
#endif
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
uniform vec3 spectrum;
uniform sampler2D prevFrame;
uniform sampler2D prevPass;
varying vec3 v_normal;
varying vec2 v_texcoord;
// Simple 1D Gaussian weight function
float gaussian(float x, float sigma) {
return exp(-(x * x) / (2.0 * sigma * sigma));
}
void main(void)
{
// Gaussian blur parameters
float sigma = 10.0; // Blur radius
float blurSize = 1.0 / resolution.x; // Size of one pixel
// Number of samples to take
const int samples = 10;
// Initialize color accumulator
vec4 color = vec4(0.0);
float weight_sum = 0.0;
// Sample original texture
// Apply horizontal and vertical blur in one pass
for (int i = -samples/2; i <= samples/2; i++) {
for (int j = -samples/2; j <= samples/2; j++) {
// Calculate weight based on distance from center
float distance = sqrt(float(i*i + j*j));
float weight = gaussian(distance, sigma);
// Sample the texture with offset
vec2 offset = vec2(float(i), float(j)) * blurSize;
vec4 sample = texture2D(prevPass, v_texcoord + offset);
// Accumulate weighted sample
color += sample * weight;
vec4 originalColor = texture2D(prevPass, v_texcoord);
// Edge detection using fwidth()
vec3 edgeValue = fwidth(color.rgb);
float edgeIntensity = (edgeValue.r + edgeValue.g + edgeValue.b) * 3.0;
// Simple edge enhancement
float edgeThreshold = 0.8; // Adjust for more/less edge sensitivity
float edgeContrast = 1.; // Adjust for stronger/weaker edge effect
// Create a clean edge mask
float edgeMask = smoothstep(edgeThreshold, edgeThreshold + 99.9, edgeIntensity);
weight_sum += (weight) + ((( edgeMask))*.2);
// weight_sum = mix(weight_sum+weight*(edgeContrast+edgeMask ), 1.-weight_sum, weight_sum);
}
}
// Normalize by the sum of weights
vec4 blurredColor = color / weight_sum;
// Apply contrast to edges - make them darker
// vec4 finalColor = mix(blurredColor, vec4(0.0, 0.0, 0.0, 1.0), edgeMask * edgeContrast);
gl_FragColor = blurredColor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment