generated from krampus/template-godot4
424 lines
11 KiB
Plaintext
424 lines
11 KiB
Plaintext
|
// 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
|
||
|
}
|