// 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 }