Add ground_level, region_blend to flat background; Allow negative world noise height
This commit is contained in:
parent
fcbfcdc7bf
commit
e8fa334584
|
|
@ -224,7 +224,7 @@
|
|||
<None Include="src\shaders\main.glsl" />
|
||||
<None Include="src\shaders\overlays.glsl" />
|
||||
<None Include="src\shaders\samplers.glsl" />
|
||||
<None Include="src\shaders\world_noise.glsl" />
|
||||
<None Include="src\shaders\backgrounds.glsl" />
|
||||
<None Include="src\shaders\editor_functions.glsl" />
|
||||
<None Include="src\shaders\dual_scaling.glsl" />
|
||||
<None Include="src\shaders\auto_shader.glsl" />
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@
|
|||
<None Include="src\shaders\main.glsl">
|
||||
<Filter>4. Shaders</Filter>
|
||||
</None>
|
||||
<None Include="src\shaders\world_noise.glsl">
|
||||
<None Include="src\shaders\backgrounds.glsl">
|
||||
<Filter>4. Shaders</Filter>
|
||||
</None>
|
||||
<None Include=".gitignore">
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ uniform float wind_strength : hint_range(0.0, 1.0, 0.01) = 1.0;
|
|||
uniform float wind_dithering = 4.0;
|
||||
uniform vec2 wind_direction = vec2(1.0,1.0);
|
||||
|
||||
group_uniforms shapeing;
|
||||
group_uniforms shaping;
|
||||
uniform float clod_scale_boost = 3.0;
|
||||
uniform float clod_min_threshold : hint_range(0.0, 1.0, 0.001) = 0.2;
|
||||
uniform float clod_max_threshold : hint_range(0.0, 1.0, 0.001) = 0.5;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ uniform highp sampler2DArray _texture_array_normal : hint_normal, filter_linear_
|
|||
|
||||
// Public uniforms
|
||||
group_uniforms general;
|
||||
uniform float ground_level : hint_range(-1000., 1000.) = 0.0;
|
||||
uniform float region_blend : hint_range(.001, 1., 0.001) = 0.25;
|
||||
uniform bool flat_terrain_normals = false;
|
||||
uniform bool enable_textures = true;
|
||||
uniform float blend_sharpness : hint_range(0, 1) = 0.5;
|
||||
|
|
@ -84,6 +86,7 @@ group_uniforms;
|
|||
varying vec3 v_normal;
|
||||
varying vec3 v_vertex;
|
||||
varying mat3 TBN;
|
||||
varying vec2 bg_ddxy;
|
||||
|
||||
////////////////////////
|
||||
// Vertex
|
||||
|
|
@ -119,6 +122,29 @@ vec3 get_index_uv(const vec2 uv2) {
|
|||
return vec3(uv2 - _region_locations[layer_index], float(layer_index));
|
||||
}
|
||||
|
||||
// Takes in UV2 region space coordinates, returns 1.0 or 0.0 if a region is present or not.
|
||||
float check_region(const vec2 uv2) {
|
||||
ivec2 pos = ivec2(floor(uv2)) + (_region_map_size / 2);
|
||||
int layer_index = 0;
|
||||
if (uint(pos.x | pos.y) < uint(_region_map_size)) {
|
||||
layer_index = clamp(_region_map[ pos.y * _region_map_size + pos.x ] - 1, -1, 0) + 1;
|
||||
}
|
||||
return float(layer_index);
|
||||
}
|
||||
|
||||
// Takes in UV2 region space coordinates, returns a blend value (0 - 1 range) between empty, and valid regions
|
||||
float get_region_blend(vec2 uv2) {
|
||||
uv2 -= 0.5;
|
||||
const vec2 offset = vec2(0.0, 1.0);
|
||||
float a = check_region(uv2 + offset.xy);
|
||||
float b = check_region(uv2 + offset.yy);
|
||||
float c = check_region(uv2 + offset.yx);
|
||||
float d = check_region(uv2 + offset.xx);
|
||||
vec2 w = smoothstep(vec2(0.0), vec2(1.0), fract(uv2));
|
||||
float blend = mix(mix(d, c, w.x), mix(a, b, w.x), w.y);
|
||||
return 1.0 - blend;
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
// Get vertex of flat plane in world coordinates and set world UV
|
||||
v_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
|
|
@ -162,15 +188,21 @@ void vertex() {
|
|||
// Set final vertex height & calculate vertex normals. 3 lookups
|
||||
ivec3 uv_a = get_index_coord(start_pos, VERTEX_PASS);
|
||||
ivec3 uv_b = get_index_coord(end_pos, VERTEX_PASS);
|
||||
float h = mix(texelFetch(_height_maps, uv_a, 0).r,texelFetch(_height_maps, uv_b, 0).r,vertex_lerp);
|
||||
v_vertex.y = h;
|
||||
float h = mix(texelFetch(_height_maps, uv_a, 0).r, texelFetch(_height_maps, uv_b, 0).r, vertex_lerp);
|
||||
|
||||
// Vertex normals
|
||||
// Apply background ground level and region blend
|
||||
float ground_h = ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2));
|
||||
v_vertex.y = h + ground_h;
|
||||
bg_ddxy.x = ground_h - ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2 + vec2(_region_texel_size, 0.)));
|
||||
bg_ddxy.y = ground_h - ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2 + vec2(0., _region_texel_size)));
|
||||
|
||||
// Vertex normals adding background normals
|
||||
float u = mix(texelFetch(_height_maps, get_index_coord(start_pos + vec2(1,0), VERTEX_PASS), 0).r,
|
||||
texelFetch(_height_maps, get_index_coord(end_pos + vec2(1,0), VERTEX_PASS), 0).r, vertex_lerp);
|
||||
float v = mix(texelFetch(_height_maps, get_index_coord(start_pos + vec2(0,1), VERTEX_PASS), 0).r,
|
||||
texelFetch(_height_maps, get_index_coord(end_pos + vec2(0,1), VERTEX_PASS), 0).r, vertex_lerp);
|
||||
|
||||
u += bg_ddxy.x;
|
||||
v += bg_ddxy.y;
|
||||
v_normal = normalize(vec3(h - u, _vertex_spacing, h - v));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,56 @@
|
|||
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
|
||||
R"(
|
||||
//INSERT: FLAT_UNIFORMS
|
||||
uniform float ground_level : hint_range(-1000., 1000.) = 0.0;
|
||||
uniform float region_blend : hint_range(.001, 1., 0.001) = 0.25;
|
||||
varying vec2 bg_ddxy;
|
||||
|
||||
//INSERT: FLAT_FUNCTIONS
|
||||
// Takes in UV2 region space coordinates, returns 1.0 or 0.0 if a region is present or not.
|
||||
float check_region(const vec2 uv2) {
|
||||
ivec2 pos = ivec2(floor(uv2)) + (_region_map_size / 2);
|
||||
int layer_index = 0;
|
||||
if (uint(pos.x | pos.y) < uint(_region_map_size)) {
|
||||
layer_index = clamp(_region_map[ pos.y * _region_map_size + pos.x ] - 1, -1, 0) + 1;
|
||||
}
|
||||
return float(layer_index);
|
||||
}
|
||||
|
||||
// Takes in UV2 region space coordinates, returns a blend value (0 - 1 range) between empty, and valid regions
|
||||
float get_region_blend(vec2 uv2) {
|
||||
uv2 -= 0.5;
|
||||
const vec2 offset = vec2(0.0, 1.0);
|
||||
float a = check_region(uv2 + offset.xy);
|
||||
float b = check_region(uv2 + offset.yy);
|
||||
float c = check_region(uv2 + offset.yx);
|
||||
float d = check_region(uv2 + offset.xx);
|
||||
vec2 w = smoothstep(vec2(0.0), vec2(1.0), fract(uv2));
|
||||
float blend = mix(mix(d, c, w.x), mix(a, b, w.x), w.y);
|
||||
return 1.0 - blend;
|
||||
}
|
||||
|
||||
//INSERT: FLAT_VERTEX
|
||||
// Apply background ground level and region blend
|
||||
float ground_h = ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2));
|
||||
h += ground_h;
|
||||
bg_ddxy.x = ground_h - ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2 + vec2(_region_texel_size, 0.)));
|
||||
bg_ddxy.y = ground_h - ground_level * smoothstep(1.0 - region_blend, 1.0, get_region_blend(UV2 + vec2(0., _region_texel_size)));
|
||||
|
||||
//INSERT: FLAT_FRAGMENT
|
||||
// Apply background normal
|
||||
u += bg_ddxy.x;
|
||||
v += bg_ddxy.y;
|
||||
|
||||
//INSERT: WORLD_NOISE_UNIFORMS
|
||||
group_uniforms world_background_noise;
|
||||
uniform float region_blend : hint_range(.001, 1., 0.001) = 0.25;
|
||||
uniform bool world_noise_fragment_normals = false;
|
||||
uniform float world_noise_region_blend : hint_range(0.05, 0.95, 0.01) = 0.33;
|
||||
uniform int world_noise_max_octaves : hint_range(0, 15) = 4;
|
||||
uniform int world_noise_min_octaves : hint_range(0, 15) = 2;
|
||||
uniform float world_noise_lod_distance : hint_range(0, 40000, 1) = 7500.;
|
||||
uniform float world_noise_lod_distance : hint_range(0., 40000., 1.) = 7500.;
|
||||
uniform float world_noise_scale : hint_range(0.25, 20, 0.01) = 5.0;
|
||||
uniform float world_noise_height : hint_range(0, 1000, 0.1) = 64.0;
|
||||
uniform float world_noise_height : hint_range(-1000., 1000., 0.1) = 32.0;
|
||||
uniform vec3 world_noise_offset = vec3(0.0);
|
||||
group_uniforms;
|
||||
varying vec2 world_noise_ddxy;
|
||||
|
|
@ -29,9 +69,9 @@ float check_region(const vec2 uv2) {
|
|||
}
|
||||
|
||||
// Takes in UV2 region space coordinates, returns a blend value (0 - 1 range) between empty, and valid regions
|
||||
float region_blend(vec2 uv2) {
|
||||
float get_region_blend(vec2 uv2) {
|
||||
uv2 -= 0.5;
|
||||
const vec2 offset = vec2(0.0,1.0);
|
||||
const vec2 offset = vec2(0.0, 1.0);
|
||||
float a = check_region(uv2 + offset.xy);
|
||||
float b = check_region(uv2 + offset.yy);
|
||||
float c = check_region(uv2 + offset.yx);
|
||||
|
|
@ -95,16 +135,16 @@ float world_noise(vec2 p) {
|
|||
}
|
||||
|
||||
float get_noise_height(const vec2 uv) {
|
||||
float weight = region_blend(uv);
|
||||
// only calculate world noise when it could be visibile.
|
||||
if (weight <= 1.0 - world_noise_region_blend) {
|
||||
float weight = get_region_blend(uv);
|
||||
// Only calculate world noise when it would be visible.
|
||||
if (weight <= 1.0 - region_blend) {
|
||||
return 0.0;
|
||||
}
|
||||
//TODO: Offset/scale UVs are semi-dependent upon region size 1024. Base on v_vertex.xz instead
|
||||
float noise = world_noise((uv + world_noise_offset.xz * 1024. / _region_size) * world_noise_scale * _region_size / 1024. * .1) *
|
||||
world_noise_height * 10. + world_noise_offset.y * 100.;
|
||||
weight = smoothstep(1.0 - world_noise_region_blend, 1.0, weight);
|
||||
return mix(0.0, noise, weight);
|
||||
weight = smoothstep(1.0 - region_blend, 1.0, weight);
|
||||
return mix(0.0, noise, weight);
|
||||
}
|
||||
|
||||
// World Noise Functions End
|
||||
|
|
@ -114,11 +154,11 @@ float get_noise_height(const vec2 uv) {
|
|||
if (_background_mode == 2u) {
|
||||
vec2 nuv_a = fma(start_pos, vec2(_region_texel_size), vec2(0.5 * _region_texel_size));
|
||||
vec2 nuv_b = fma(end_pos, vec2(_region_texel_size), vec2(0.5 * _region_texel_size));
|
||||
float nh = mix(get_noise_height(nuv_a),get_noise_height(nuv_b),vertex_lerp);
|
||||
float nh = mix(get_noise_height(nuv_a), get_noise_height(nuv_b), vertex_lerp);
|
||||
float nu = mix(get_noise_height(nuv_a + vec2(_region_texel_size, 0.0)),
|
||||
get_noise_height(nuv_b + vec2(_region_texel_size, 0.0)),vertex_lerp);
|
||||
get_noise_height(nuv_b + vec2(_region_texel_size, 0.0)), vertex_lerp);
|
||||
float nv = mix(get_noise_height(nuv_a + vec2(0.0, _region_texel_size)),
|
||||
get_noise_height(nuv_b + vec2(0.0, _region_texel_size)),vertex_lerp);
|
||||
get_noise_height(nuv_b + vec2(0.0, _region_texel_size)), vertex_lerp);
|
||||
world_noise_ddxy = vec2(nh - nu, nh - nv);
|
||||
h += nh;
|
||||
}
|
||||
|
|
@ -72,6 +72,7 @@ uniform highp sampler2DArray _control_maps : repeat_disable;
|
|||
// Public uniforms
|
||||
|
||||
group_uniforms general;
|
||||
//INSERT: FLAT_UNIFORMS
|
||||
uniform bool flat_terrain_normals = false;
|
||||
uniform float blend_sharpness : hint_range(0, 1) = 0.5;
|
||||
uniform bool vertical_projection = true;
|
||||
|
|
@ -150,6 +151,7 @@ vec3 get_index_uv(const vec2 uv2) {
|
|||
return vec3(uv2 - _region_locations[layer_index], float(layer_index));
|
||||
}
|
||||
|
||||
//INSERT: FLAT_FUNCTIONS
|
||||
//INSERT: WORLD_NOISE_FUNCTIONS
|
||||
void vertex() {
|
||||
// Get vertex of flat plane in world coordinates and set world UV
|
||||
|
|
@ -194,7 +196,8 @@ void vertex() {
|
|||
// Set final vertex height & calculate vertex normals. 3 lookups
|
||||
ivec3 coord_a = get_index_coord(start_pos, VERTEX_PASS);
|
||||
ivec3 coord_b = get_index_coord(end_pos, VERTEX_PASS);
|
||||
float h = mix(texelFetch(_height_maps, coord_a, 0).r,texelFetch(_height_maps, coord_b, 0).r,vertex_lerp);
|
||||
float h = mix(texelFetch(_height_maps, coord_a, 0).r, texelFetch(_height_maps, coord_b, 0).r, vertex_lerp);
|
||||
//INSERT: FLAT_VERTEX
|
||||
//INSERT: WORLD_NOISE_VERTEX
|
||||
v_vertex.y = h;
|
||||
}
|
||||
|
|
@ -406,10 +409,11 @@ void fragment() {
|
|||
// Terrain normals
|
||||
vec3 index_normal[4];
|
||||
float h[4];
|
||||
// allows additional derivatives, eg world noise, brush previews etc
|
||||
// Allows for additional derivatives, eg world background, brush previews etc
|
||||
float u = 0.0;
|
||||
float v = 0.0;
|
||||
|
||||
|
||||
//INSERT: FLAT_FRAGMENT
|
||||
//INSERT: WORLD_NOISE_FRAGMENT
|
||||
// Re-use index[] for the first lookups, skipping some math. 3 lookups
|
||||
h[3] = texelFetch(_height_maps, index[3], 0).r; // 0 (0,0)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ void Terrain3DMaterial::_preload_shaders() {
|
|||
#include "shaders/samplers.glsl"
|
||||
, "samplers");
|
||||
_parse_shader(
|
||||
#include "shaders/world_noise.glsl"
|
||||
, "world_noise");
|
||||
#include "shaders/backgrounds.glsl"
|
||||
, "backgrounds");
|
||||
_parse_shader(
|
||||
#include "shaders/auto_shader.glsl"
|
||||
, "auto_shader");
|
||||
|
|
@ -124,6 +124,12 @@ String Terrain3DMaterial::_apply_inserts(const String &p_shader, const Array &p_
|
|||
String Terrain3DMaterial::_generate_shader_code() const {
|
||||
LOG(INFO, "Generating default shader code");
|
||||
Array excludes;
|
||||
if (_world_background != FLAT) {
|
||||
excludes.push_back("FLAT_UNIFORMS");
|
||||
excludes.push_back("FLAT_FUNCTIONS");
|
||||
excludes.push_back("FLAT_VERTEX");
|
||||
excludes.push_back("FLAT_FRAGMENT");
|
||||
}
|
||||
if (_world_background != NOISE) {
|
||||
excludes.push_back("WORLD_NOISE_UNIFORMS");
|
||||
excludes.push_back("WORLD_NOISE_FUNCTIONS");
|
||||
|
|
|
|||
Loading…
Reference in New Issue