Hallucination with vertigo 3D

Suitable for thrill seekers. Your head may get dizzy in reality!

Shader code
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx;

uniform sampler2D albedo_x : source_color;
uniform sampler2D albedo_y : source_color;
uniform sampler2D albedo_z : source_color;
uniform bool use_different_textures = false;
uniform sampler2D albedo_texture : source_color;

uniform sampler2D normal_x : hint_normal;
uniform sampler2D normal_y : hint_normal;
uniform sampler2D normal_z : hint_normal;
uniform bool use_different_normals = false;
uniform sampler2D normal_texture : hint_normal;
uniform float normal_strength : hint_range(0.0, 2.0) = 1.0;

uniform sampler2D roughness_texture : hint_default_white;
uniform float roughness : hint_range(0.0, 1.0) = 0.5;
uniform sampler2D metallic_texture : hint_default_white;
uniform float metallic : hint_range(0.0, 1.0) = 0.0;
uniform sampler2D ao_texture : hint_default_white;
uniform float ao_strength : hint_range(0.0, 1.0) = 0.0;

uniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);
uniform float triplanar_sharpness : hint_range(1.0, 32.0) = 8.0;
uniform vec3 triplanar_offset = vec3(0.0, 0.0, 0.0);
uniform bool world_space = true;
uniform bool use_custom_direction = false;
uniform vec3 custom_direction_x = vec3(1.0, 0.0, 0.0);
uniform vec3 custom_direction_y = vec3(0.0, 1.0, 0.0);
uniform vec3 custom_direction_z = vec3(0.0, 0.0, 1.0);

uniform float blend_multiplier : hint_range(0.0, 5.0) = 1.0;
uniform float y_multiplier : hint_range(0.0, 5.0) = 1.0;
uniform float x_multiplier : hint_range(0.0, 5.0) = 1.0;
uniform float z_multiplier : hint_range(0.0, 5.0) = 1.0;

uniform vec4 albedo_tint : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float brightness : hint_range(0.0, 2.0) = 1.0;
uniform float contrast : hint_range(0.0, 2.0) = 1.0;
uniform float saturation : hint_range(0.0, 2.0) = 1.0;

vec3 adjust_color(vec3 color) {
    color *= brightness;
    color = mix(vec3(0.5), color, contrast);
    float luminance = dot(color, vec3(0.299, 0.587, 0.114));
    color = mix(vec3(luminance), color, saturation);
    return color;
}

vec4 triplanar_texture(sampler2D tex_x, sampler2D tex_y, sampler2D tex_z, vec3 world_pos, vec3 blend) {
    vec4 tx = texture(tex_x, world_pos.yz);
    vec4 ty = texture(tex_y, world_pos.xz);
    vec4 tz = texture(tex_z, world_pos.xy);
    
    blend.x *= x_multiplier;
    blend.y *= y_multiplier;
    blend.z *= z_multiplier;
    
    blend /= (blend.x + blend.y + blend.z);
    
    return tx * blend.x + ty * blend.y + tz * blend.z;
}

vec4 triplanar_texture_same(sampler2D tex, vec3 world_pos, vec3 blend) {
    vec4 tx = texture(tex, world_pos.yz);
    vec4 ty = texture(tex, world_pos.xz);
    vec4 tz = texture(tex, world_pos.xy);
    
    blend.x *= x_multiplier;
    blend.y *= y_multiplier;
    blend.z *= z_multiplier;
    
    blend /= (blend.x + blend.y + blend.z);
    
    return tx * blend.x + ty * blend.y + tz * blend.z;
}

vec3 triplanar_normal(sampler2D tex_x, sampler2D tex_y, sampler2D tex_z, vec3 world_pos, vec3 blend, vec3 normal) {
    vec3 tnormalX = texture(tex_x, world_pos.yz).rgb * 2.0 - 1.0;
    vec3 tnormalY = texture(tex_y, world_pos.xz).rgb * 2.0 - 1.0;
    vec3 tnormalZ = texture(tex_z, world_pos.xy).rgb * 2.0 - 1.0;
    
    vec3 axisX = vec3(0.0, tnormalX.x, tnormalX.y);
    vec3 axisY = vec3(tnormalY.x, 0.0, tnormalY.y);
    vec3 axisZ = vec3(tnormalZ.x, tnormalZ.y, 0.0);
    
    axisX = normalize(vec3(normal.x, axisX.y * normal_strength, axisX.z * normal_strength));
    axisY = normalize(vec3(axisY.x * normal_strength, normal.y, axisY.z * normal_strength));
    axisZ = normalize(vec3(axisZ.x * normal_strength, axisZ.y * normal_strength, normal.z));
    
    blend.x *= x_multiplier;
    blend.y *= y_multiplier;
    blend.z *= z_multiplier;
    
    blend /= (blend.x + blend.y + blend.z);
    
    vec3 result = axisX * blend.x + axisY * blend.y + axisZ * blend.z;
    return normalize(result);
}

vec3 triplanar_normal_same(sampler2D tex, vec3 world_pos, vec3 blend, vec3 normal) {
    vec3 tnormalX = texture(tex, world_pos.yz).rgb * 2.0 - 1.0;
    vec3 tnormalY = texture(tex, world_pos.xz).rgb * 2.0 - 1.0;
    vec3 tnormalZ = texture(tex, world_pos.xy).rgb * 2.0 - 1.0;
    
    vec3 axisX = vec3(0.0, tnormalX.x, tnormalX.y);
    vec3 axisY = vec3(tnormalY.x, 0.0, tnormalY.y);
    vec3 axisZ = vec3(tnormalZ.x, tnormalZ.y, 0.0);
    
    axisX = normalize(vec3(normal.x, axisX.y * normal_strength, axisX.z * normal_strength));
    axisY = normalize(vec3(axisY.x * normal_strength, normal.y, axisY.z * normal_strength));
    axisZ = normalize(vec3(axisZ.x * normal_strength, axisZ.y * normal_strength, normal.z));
    
    blend.x *= x_multiplier;
    blend.y *= y_multiplier;
    blend.z *= z_multiplier;
    
    blend /= (blend.x + blend.y + blend.z);
    
    vec3 result = axisX * blend.x + axisY * blend.y + axisZ * blend.z;
    return normalize(result);
}

void fragment() {
    vec3 position;
    vec3 normal;
    
    if (world_space) {
        position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
        normal = normalize((MODEL_MATRIX * vec4(NORMAL, 0.0)).xyz);
    } else {
        position = VERTEX;
        normal = NORMAL;
    }
    
    position = position * triplanar_scale + triplanar_offset;
    
    vec3 blend_weights;
    
    if (use_custom_direction) {
        blend_weights.x = abs(dot(normal, normalize(custom_direction_x)));
        blend_weights.y = abs(dot(normal, normalize(custom_direction_y)));
        blend_weights.z = abs(dot(normal, normalize(custom_direction_z)));
    } else {
        blend_weights = abs(normal);
    }
    
    blend_weights = pow(blend_weights, vec3(triplanar_sharpness * blend_multiplier));
    
    blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z);
    
    vec4 albedo;
    vec3 normal_map;
    
    if (use_different_textures) {
        albedo = triplanar_texture(albedo_x, albedo_y, albedo_z, position, blend_weights);
    } else {
        albedo = triplanar_texture_same(albedo_texture, position, blend_weights);
    }
    
    if (use_different_normals) {
        normal_map = triplanar_normal(normal_x, normal_y, normal_z, position, blend_weights, normal);
    } else {
        normal_map = triplanar_normal_same(normal_texture, position, blend_weights, normal);
    }
    
    float rough = roughness * triplanar_texture_same(roughness_texture, position, blend_weights).r;
    float metal = metallic * triplanar_texture_same(metallic_texture, position, blend_weights).r;
    float ao_value = mix(1.0, triplanar_texture_same(ao_texture, position, blend_weights).r, ao_strength);
    
    albedo.rgb = adjust_color(albedo.rgb) * albedo_tint.rgb;
    
    ALBEDO = albedo.rgb * ao_value;
    METALLIC = metal;
    ROUGHNESS = rough;
    NORMAL = normal_map;
}
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.

More from WhyNilliana

RTX filter for your game (brightness, ripples and other effects)

A magical anomaly

Simple Laser Shader (SLS)

guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
skuncc
7 months ago

i promise i will find a way to use this