#version 430 core out vec4 FragColor; uniform vec2 u_resolution; // framebuffer size in pixels uniform ivec2 u_gridSize; // sand grid size uniform usampler2D u_state; // GL_R8UI texture uniform vec2 u_brushPos; uniform float u_brushRadius; uniform int u_showBrush; void main() { vec2 fragCoord = gl_FragCoord.xy; // Normalized coordinates vec2 uv = fragCoord / u_resolution; uv.y = 1.0 - uv.y; // Map to grid coordinates ivec2 cell = ivec2(uv * vec2(u_gridSize)); cell = clamp(cell, ivec2(0), u_gridSize - ivec2(1)); uint v = texelFetch(u_state, cell, 0).r; vec3 color = (v == 1u) ? vec3(0.9, 0.8, 0.1) // sand : vec3(0.05, 0.05, 0.10); // background if (u_showBrush != 0) { // center of this cell in grid coordinates vec2 cellCenter = vec2(cell) + vec2(0.5); float dist = length(cellCenter - u_brushPos); // how thick the ring is, in cells float thickness = 1.0; // 1-cell-thick ring // abs(dist - radius) < thickness => inside ring float d = abs(dist - u_brushRadius); // Smooth edge: edge = 1 at center of ring, 0 outside float edge = smoothstep(thickness, 0.0, d); vec3 ringColor = vec3(1.0); // white ring color = mix(color, ringColor, edge); } FragColor = vec4(color, 1.0); }