grunk/addons/ursc/spatial/common.gdshaderinc

424 lines
11 KiB
Plaintext
Raw Normal View History

2025-03-16 16:59:30 -06:00
// If you want to use fog controlled by a Godot Environment resource (pixel-based),
// simply uncomment the following line:
// #define USE_ENVIRONMENT_FOG
// Render mode
render_mode
#if defined(BLEND_MODE)
BLEND_MODE,
#endif
#if defined(CULL_MODE)
CULL_MODE,
#else
cull_back,
#endif
#if defined(ALPHA_BLEND)
depth_draw_always,
#else
depth_draw_opaque,
#endif
#if defined(UNSHADED)
unshaded,
#else
diffuse_lambert_wrap,
vertex_lighting,
#endif
#if defined(AMBIENT_LIGHT_DISABLED)
ambient_light_disabled,
#endif
#if defined(FOG_DISABLED)
fog_disabled,
#endif
specular_disabled,
shadows_disabled;
// Constants
#if !defined(OVERRIDE_VERTEX_SNAP_RESOLUTION)
const ivec2 VERTEX_SNAP_RESOLUTION = ivec2(320, 240);
#endif
// Global uniforms
#if !defined(TEXTURE_DISABLED) && !defined(SHINY)
#if !defined(TEXTURE_METAL)
global uniform bool affine_texture_mapping;
#endif
global uniform bool texture_filtering;
global uniform float texture_lod_halve_distance;
#endif
#if defined(OVERRIDE_VERTEX_SNAP_RESOLUTION)
global uniform ivec2 vertex_snap_resolution;
#else
global uniform int vertex_snap_intensity;
#endif
#if !defined(FOG_DISABLED) && !defined(USE_ENVIRONMENT_FOG)
global uniform vec4 fog_color : source_color;
global uniform float fog_start_distance;
global uniform float fog_end_distance;
#endif
global uniform float cull_distance;
// Uniforms
#if defined(ALPHA_BLEND) || (defined(ALPHA_SCISSOR) && !defined(SHINY) && !defined(TEXTURE_METAL))
uniform vec4 albedo_color : source_color = vec4(1.0);
#else
uniform vec3 albedo_color : source_color = vec3(1.0);
#endif
#if defined(SHINY)
uniform float color_depth : hint_range(16, 64, 16) = 16;
uniform float glossiness : hint_range(0, 1, 0.05) = 0.4;
uniform float shadow_intensity : hint_range(0, 1, 0.05) = 0.65;
#elif !defined(TEXTURE_DISABLED)
uniform sampler2D albedo_texture :
source_color,
filter_nearest,
#if defined(TEXTURE_REPEAT)
repeat_enable;
#else
repeat_disable;
#endif
#if (defined(ALPHA_SCISSOR) && !defined(SHINY) && !defined(TEXTURE_METAL))
uniform float alpha_scissor : hint_range(0, 1, 0.01) = 0.1;
#else
uniform bool albedo_texture_as_primary_color = true;
uniform float mix_factor: hint_range(0.0, 1.0, 0.01) = 1.0;
#endif
uniform float texture_lod_halve_distance_override : hint_range(0.0, 32.0, 2.0) = 0;
#if !defined(TEXTURE_METAL)
uniform vec2 uv_offset = vec2(0.0);
uniform vec2 uv_scale = vec2(1.0);
uniform vec2 uv_scroll_speed = vec2(0.0);
#endif
#endif
#if defined(BILLBOARD)
uniform int billboard_mode: hint_range(0, 2);
uniform bool use_transform_scale = true;
#endif
uniform float cull_distance_override: hint_range(0.0, 1024.0, 2.0) = 0;
uniform bool convert_vertex_colors = false;
// Varyings
#if !defined(TEXTURE_DISABLED) && !defined(TEXTURE_METAL) && !defined(SHINY)
varying float position_w;
#endif
#if !defined(TEXTURE_DISABLED) && !defined(SHINY)
varying flat int should_halve_texture_lod;
#endif
#if !defined(FOG_DISABLED) && !defined(USE_ENVIRONMENT_FOG)
varying float fog_mix_factor;
#endif
// Functions
#if defined(SHINY)
vec3 glimmer(vec3 input)
{
float grayscale = max(vec3(input).r, max(vec3(input).g, vec3(input).b));
float lower = floor(grayscale * color_depth) / color_depth;
float lower_difference = abs(grayscale - lower);
float upper = ceil(grayscale * color_depth) / color_depth;
float upper_difference = abs(upper - grayscale);
float level = lower_difference <= upper_difference ? lower : upper;
float adjustment = level / grayscale;
return vec3(input) * adjustment;
}
#elif !defined(TEXTURE_DISABLED)
vec4 albedoTextureFiltered(vec2 uv)
{
vec2 albedo_texture_size = vec2(textureSize(albedo_texture, 0));
vec2 tex_pix_a = vec2(1.0 / albedo_texture_size.x, 0.0);
vec2 tex_pix_b = vec2(0.0, 1.0 / albedo_texture_size.y);
vec2 tex_pix_c = vec2(tex_pix_a.x,tex_pix_b.y);
vec2 half_tex = vec2(tex_pix_a.x * 0.5, tex_pix_b.y * 0.5);
vec2 uv_centered = uv - half_tex;
vec4 diffuse_color = texture(albedo_texture, uv_centered);
vec4 sample_a = texture(albedo_texture, uv_centered + tex_pix_a);
vec4 sample_b = texture(albedo_texture, uv_centered + tex_pix_b);
vec4 sample_c = texture(albedo_texture, uv_centered + tex_pix_c);
float interp_x = modf(uv_centered.x * albedo_texture_size.x, albedo_texture_size.x);
float interp_y = modf(uv_centered.y * albedo_texture_size.y, albedo_texture_size.y);
if (uv_centered.x < 0.0)
{
interp_x = 1.0 - interp_x * -1.0;
}
if (uv_centered.y < 0.0)
{
interp_y = 1.0 - interp_y * -1.0;
}
diffuse_color = (
diffuse_color +
interp_x * (sample_a - diffuse_color) +
interp_y * (sample_b - diffuse_color)) *
(1.0 - step(1.0, interp_x + interp_y));
diffuse_color += (
(sample_c + (1.0 - interp_x) * (sample_b - sample_c) +
(1.0 - interp_y) * (sample_a - sample_c)) *
step(1.0, interp_x + interp_y));
return diffuse_color;
}
#endif
// https://gamedev.stackexchange.com/a/194038
vec3 fromLinear(vec3 linear_color)
{
bvec3 cutoff = lessThan(linear_color.rgb, vec3(0.0031308));
vec3 higher = vec3(1.055) * pow(linear_color.rgb, vec3(1.0 / 2.4)) - vec3(0.055);
vec3 lower = linear_color.rgb * vec3(12.92);
return mix(higher, lower, cutoff);
}
// https://gamedev.stackexchange.com/a/194038
vec3 toLinear(vec3 srgb_color)
{
bvec3 cutoff = lessThan(srgb_color.rgb, vec3(0.04045));
vec3 higher = pow((srgb_color.rgb + vec3(0.055)) / vec3(1.055), vec3(2.4));
vec3 lower = srgb_color.rgb / vec3(12.92);
return mix(higher, lower, cutoff);
}
void vertex()
{
if (convert_vertex_colors)
COLOR.rgb = fromLinear(COLOR.rgb);
#if !defined(TEXTURE_DISABLED) && !defined(TEXTURE_METAL) && !defined(SHINY)
UV = UV * uv_scale + uv_offset + (uv_scroll_speed * TIME);
#endif
#if defined(BILLBOARD)
if (billboard_mode > 0)
{
if (billboard_mode == 1)
{
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
INV_VIEW_MATRIX[0],
INV_VIEW_MATRIX[1],
INV_VIEW_MATRIX[2],
MODEL_MATRIX[3]);
}
else
{
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
vec4(normalize(cross(vec3(0.0, 1.0, 0.0), INV_VIEW_MATRIX[2].xyz)), 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(normalize(cross(INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0),
MODEL_MATRIX[3]);
}
if (use_transform_scale)
{
MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(
vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),
vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0),
vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
}
MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
}
#endif
float vertex_distance = length((MODELVIEW_MATRIX * vec4(VERTEX, 1.0)));
#if !defined(FOG_DISABLED) && !defined(USE_ENVIRONMENT_FOG)
if (fog_start_distance >= 0.0 && fog_start_distance < fog_end_distance)
{
fog_mix_factor = clamp(
(vertex_distance - fog_start_distance) / (fog_end_distance - fog_start_distance),
0.0, 1.0);
}
else
{
fog_mix_factor = 0.0;
}
#endif
#if !defined(TEXTURE_DISABLED) && !defined(SHINY)
float actual_texture_lod_halve_distance =
texture_lod_halve_distance_override > 0.0
? texture_lod_halve_distance_override
: texture_lod_halve_distance;
should_halve_texture_lod = (
!texture_filtering &&
actual_texture_lod_halve_distance > 0.0 &&
vertex_distance > actual_texture_lod_halve_distance) ? 1 : 0;
#endif
float actual_cull_distance =
cull_distance_override > 0.0 ? cull_distance_override : cull_distance;
if (actual_cull_distance > 0.0 && vertex_distance > actual_cull_distance)
{
POSITION = vec4(sqrt(-1));
}
else
{
POSITION = PROJECTION_MATRIX * MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
#if defined(OVERRIDE_VERTEX_SNAP_RESOLUTION)
vec4 snapped_position = POSITION;
snapped_position.xyz = POSITION.xyz / POSITION.w;
vec2 actual_vertex_snap_resolution = vec2(vertex_snap_resolution);
snapped_position.x =
floor(actual_vertex_snap_resolution.x * snapped_position.x) /
actual_vertex_snap_resolution.x;
snapped_position.y =
floor(actual_vertex_snap_resolution.y * snapped_position.y) /
actual_vertex_snap_resolution.y;
snapped_position.xyz *= POSITION.w;
POSITION.xyz = snapped_position.xyz;
#else
if (vertex_snap_intensity > 0 && vertex_snap_intensity <= 2)
{
vec2 real_vertex_snap_resolution =
vec2(VERTEX_SNAP_RESOLUTION) * (1.0 / float(vertex_snap_intensity));
vec4 snapped_position = POSITION;
snapped_position.xyz = POSITION.xyz / POSITION.w;
snapped_position.x =
floor(real_vertex_snap_resolution.x * snapped_position.x) /
real_vertex_snap_resolution.x;
snapped_position.y =
floor(real_vertex_snap_resolution.y * snapped_position.y) /
real_vertex_snap_resolution.y;
snapped_position.xyz *= POSITION.w;
POSITION.xyz = snapped_position.xyz;
}
#endif
}
#if !defined(TEXTURE_DISABLED) && !defined(TEXTURE_METAL) && !defined(SHINY)
if (affine_texture_mapping)
{
position_w = POSITION.w;
UV *= abs(POSITION.w);
}
#endif
}
void fragment()
{
#if defined(SHINY)
vec3 light_dir = vec3(0.500000, 0.250000, 1.000000);
float light_dot = dot(light_dir, NORMAL);
vec3 brightness = glimmer(vec3(pow(light_dot, 10.0)));
brightness = clamp(brightness * vec3(glossiness), vec3(0.00000), vec3(1.00000));
vec3 shadow_dir = vec3(-light_dir.x, -light_dir.y, light_dir.z);
float dark_dot = dot(NORMAL, shadow_dir);
vec3 darkness = glimmer(vec3(dark_dot));
ALBEDO =
clamp(albedo_color.rgb +
brightness +
darkness * vec3(-shadow_intensity), 0.0, 1.0);
#if defined(ALPHA_BLEND)
ALPHA = albedo_color.a;
#endif
#else
#if defined(TEXTURE_DISABLED)
ALBEDO = albedo_color.rgb * COLOR.rgb;
#if defined(ALPHA_BLEND)
ALPHA = albedo_color.a * COLOR.a;
#endif
#else
vec2 uv;
#if defined(TEXTURE_METAL)
uv = vec2(NORMAL.x / 2.0 + 0.5, (-NORMAL.y) / 2.0 + 0.5);
#else
uv = UV;
if (affine_texture_mapping)
uv /= abs(position_w);
#endif
vec4 sampled_color;
if (should_halve_texture_lod == 1)
{
vec2 half_albedo_texture_size = vec2(textureSize(albedo_texture, 0)) * 0.5;
vec2 new_uv = floor(uv * half_albedo_texture_size) / half_albedo_texture_size;
sampled_color = texture(albedo_texture, new_uv);
}
else
{
if (texture_filtering)
sampled_color = albedoTextureFiltered(uv);
else
sampled_color = texture(albedo_texture, uv);
}
#if (defined(ALPHA_SCISSOR) && !defined(SHINY) && !defined(TEXTURE_METAL))
ALBEDO = albedo_color.rgb * sampled_color.rgb;
ALPHA = albedo_color.a * sampled_color.a;
ALPHA_SCISSOR_THRESHOLD = alpha_scissor;
#else
vec3 primary_color =
albedo_texture_as_primary_color ? sampled_color.rgb : COLOR.rgb;
vec3 secondary_color =
albedo_texture_as_primary_color ? COLOR.rgb : sampled_color.rgb;
ALBEDO =
(1.0 - mix_factor) * primary_color +
mix_factor * secondary_color * primary_color;
ALBEDO *= albedo_color.rgb;
#if defined(ALPHA_BLEND)
ALPHA = albedo_color.a * sampled_color.a * COLOR.a;
#endif
#endif
#endif
#endif
#if !defined(FOG_DISABLED) && !defined(USE_ENVIRONMENT_FOG)
FOG.a = fog_mix_factor;
FOG.rgb = toLinear(fog_color.rgb);
#endif
}