3D Grid (with individual cell control)

I was messing around with creating a grid via shaders and came up with this lil guy.

“Cell manipulator” is just an example of how you could go about manipulating individual cells.

As of right now, the manipulated gutter color (gutter color when cells are shrunk) relies on setting both manipulator_gutter_color and gutter_noise_color.

Shader code
shader_type spatial;
render_mode unshaded;

uniform float grid_size = 512.0;
uniform float cell_size = 1.0;
uniform float gutter_size = 0.04;
uniform vec4 cell_color : source_color = vec4(0.078, 0.024, 0.0, 1.0);
uniform vec4 gutter_color : source_color = vec4(0.922, 0.376, 0.0, 1.0);
uniform float cell_roundedness : hint_range(0.0, 0.9999) = 0.0;

group_uniforms CellManipulator;
uniform float cell_manipulator_radius = 0.0; // Radius of the effect
uniform vec2 cell_manipulator_uv_pos = vec2(0.5, 0.5); // The UV coordinate to affect
uniform float manipulated_cell_size = 0.5; // Minimum cell size
uniform vec4 manipulator_gutter_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float cell_manipulation_anim_speed = 1.0;

group_uniforms GutterNoise;
uniform vec3 gutter_noise_color : source_color = vec3(1.0, 1.0, 1.0);
uniform sampler2D gutter_noise: source_color;
uniform float gutter_noise_speed = 0.1;

group_uniforms Fresnel;
uniform vec3 fresnel_color : source_color = vec3(0.675, 0.192, 0.0);
uniform float fresnel_intensity = 0.2;
uniform float fresnel_amount = 15.0;

vec4 square_rounded(vec2 uv, float width, float radius) {
    uv = uv * 2.0 - 1.0;
    radius *= width; // make radius go from 0-1 instead of 0-width
    vec2 abs_uv = abs(uv.xy) - radius;
    vec2 dist = max(abs_uv, 0.0);
    float square = step(width - radius, length(dist));
    return vec4(vec3(square), square); // Return with alpha value as the last component
}

vec3 fresnel_glow(float amount, float intensity, vec3 color, vec3 normal, vec3 view)
{
    return pow((1.0 - dot(normalize(normal), normalize(view))), amount) * color * intensity;
}

void fragment() {
    float _min_cell_size = manipulated_cell_size / grid_size;
    float _max_cell_size = cell_size / grid_size;
    float _target_radius = cell_manipulator_radius / grid_size;
    // Calculate the center of the current cell based on the max cell size
    vec2 cell_coord = floor(UV / _max_cell_size);
    vec2 cell_center = cell_coord * _max_cell_size + _max_cell_size * 0.5;
    
    // Animate the cell size using a sine wave function
    float animated_cell_size = mix(_min_cell_size, _max_cell_size * 0.75, (sin(TIME * cell_manipulation_anim_speed * 2.0 * PI) * 0.5) + 0.5);

    // Calculate the distance from the cell center to the target UV
    float cell_dist = distance(cell_center, cell_manipulator_uv_pos);
    float cell_dist_t = clamp(cell_dist / _target_radius, 0.0, 1.0);
    
    float px_dist = distance(UV, cell_manipulator_uv_pos);
    float px_dist_t = clamp(px_dist / _target_radius, 0.0, 1.0);
    
    // Determine the cell size based on the distance
    float _cell_size = mix(animated_cell_size, _max_cell_size, cell_dist_t);
    float size_t = _cell_size / _max_cell_size;

    // Calculate the scaled UV coordinates based on the max cell size for alignment
    vec2 aligned_uv = UV / _max_cell_size;
    vec2 grid_uv = fract(aligned_uv);

    // Adjust the grid UV based on the calculated cell size to maintain uniform scaling
    vec2 adjusted_uv = (grid_uv - 0.5) * (_max_cell_size / _cell_size) + 0.5;
    
    // Define the gutter size relative to the cell size
    float _gutter_size = gutter_size * _max_cell_size / _cell_size;
    float gutter_half = _gutter_size * 0.5;
    
    vec4 _gutter_color = mix(manipulator_gutter_color, gutter_color, px_dist_t);
    vec4 noise = texture(gutter_noise, UV + (vec2(0, 1) * gutter_noise_speed * TIME));
    vec4 color_noise = vec4(noise.rgb * gutter_noise_color, 1.0);
    vec3 mixed_gutter_color = (_gutter_color + color_noise).rgb;
    mixed_gutter_color = mix(mixed_gutter_color, _gutter_color.rgb, px_dist_t);

    // Determine the color based on the position within the cell
    if (adjusted_uv.x < gutter_half || adjusted_uv.x > 1.0 - gutter_half || adjusted_uv.y < gutter_half || adjusted_uv.y > 1.0 - gutter_half) {
        ALBEDO = mixed_gutter_color;
    } else {
        vec4 square_result = square_rounded(adjusted_uv, 1.0 - _gutter_size, 0.9999 - cell_roundedness);
        if (square_result.a <= 0.0) {
            ALBEDO = cell_color.rgb;
        } else {
            ALBEDO = mixed_gutter_color;
        }
    }
    ALBEDO = ALBEDO + fresnel_glow(fresnel_amount, fresnel_intensity, fresnel_color, NORMAL, VIEW);
}
Tags
3d grid, grid, vaporwave
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Dashed Grid (The Best Darn Grid Shader (Yet))

Infinite Ground Grid

VR Grid floor with falloff based on XRCamera position.

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments