Working LoD shader

This commit is contained in:
Joshua Barretto 2019-11-21 20:57:46 +00:00
parent f13d98ee3e
commit 63d1b2bb22
10 changed files with 223 additions and 47 deletions

View File

@ -1,3 +1,5 @@
#include <srgb.glsl>
struct Light {
vec4 light_pos;
vec4 light_col;
@ -17,13 +19,6 @@ uniform u_shadows {
Shadow shadows[24];
};
#include <srgb.glsl>
vec3 illuminate(vec3 color, vec3 light, vec3 diffuse, vec3 ambience) {
float avg_col = (color.r + color.g + color.b) / 3.0;
return ((color - avg_col) * light + (diffuse + ambience) * avg_col) * (diffuse + ambience);
}
float attenuation_strength(vec3 rpos) {
return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z);
}

View File

@ -0,0 +1,46 @@
#include <random.glsl>
float alt_at(vec2 pos) {
return 0.0
+ pow(texture(t_noise, pos * 0.00005).x * 1.4, 3.0) * 1000.0
+ texture(t_noise, pos * 0.001).x * 100.0
+ texture(t_noise, pos * 0.003).x * 30.0;
}
vec2 splay(vec2 pos, float e) {
return pos * pow(length(pos), e);
}
vec3 lod_pos(vec2 v_pos) {
vec2 hpos = focus_pos.xy + splay(v_pos, 3.0) * 20000.0;
return vec3(hpos, alt_at(hpos));
}
vec3 lod_norm(vec2 pos) {
float alt00 = alt_at(pos);
float alt10 = alt_at(pos + vec2(100, 0));
float alt01 = alt_at(pos + vec2(0, 100));
float slope = abs(alt00 - alt10) + abs(alt00 - alt01);
return normalize(vec3(
(alt00 - alt10) / 100,
(alt00 - alt01) / 100,
100 / slope
));
}
vec3 lod_col(vec2 pos) {
vec3 warmth = mix(
vec3(0.05, 0.4, 0.15),
vec3(0.5, 0.4, 0.0),
(texture(t_noise, pos * 0.0002).x - 0.5) * 2.0 + 0.5
);
vec3 color = mix(
warmth,
vec3(0.5, 0.5, 0.5),
alt_at(pos) / 1200.0
);
return color;
}

View File

@ -1,3 +1,5 @@
uniform sampler2D t_noise;
float hash(vec4 p) {
p = fract( p*0.3183099+.1);
p *= 17.0;

View File

@ -1,7 +1,6 @@
#include <random.glsl>
#include <cloud.glsl>
const float PI = 3.141592;
const vec3 SKY_DAY_TOP = vec3(0.1, 0.2, 0.9);
@ -105,6 +104,79 @@ float is_star_at(vec3 dir) {
return 0.0;
}
const float CLOUD_AVG_HEIGHT = 1025.0;
const float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 35.0;
const float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 35.0;
const float CLOUD_THRESHOLD = 0.3;
const float CLOUD_SCALE = 1.0;
const float CLOUD_DENSITY = 100.0;
float vsum(vec3 v) {
return v.x + v.y + v.z;
}
vec2 cloud_at(vec3 pos) {
float tick_offs = 0.0
+ texture(t_noise, pos.xy * 0.0001 + tick.x * 0.001).x * 1.0
+ texture(t_noise, pos.xy * 0.000003).x * 5.0;
float value = (
0.0
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0003 + tick_offs).x
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0009 - tick_offs).x * 0.5
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0025 - tick.x * 0.01).x * 0.25
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.008 + tick.x * 0.02).x * 0.1
) / 3.0;
float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - CLOUD_AVG_HEIGHT) / 500.0, 0.0) * CLOUD_DENSITY;
float shade = ((pos.z - CLOUD_AVG_HEIGHT) / (CLOUD_AVG_HEIGHT - CLOUD_HEIGHT_MIN) + 0.5);
return vec2(shade, density / (1.0 + vsum(abs(pos - cam_pos.xyz)) / 5000));
}
vec4 get_cloud_color(vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) {
const float INCR = 0.06;
float mind = (CLOUD_HEIGHT_MIN - origin.z) / dir.z;
float maxd = (CLOUD_HEIGHT_MAX - origin.z) / dir.z;
float start = max(min(mind, maxd), 0.0);
float delta = min(abs(mind - maxd), max_dist);
bool do_cast = true;
if (mind < 0.0 && maxd < 0.0) {
do_cast = false;
}
float incr = INCR;
float fuzz = sin(texture(t_noise, dir.xz * 100000.0).x * 100.0) * incr * delta;
float cloud_shade = 1.0;
float passthrough = 1.0;
if (do_cast) {
for (float d = 0.0; d < 1.0; d += incr) {
float dist = start + d * delta;
dist += fuzz * min(pow(dist * 0.005, 2.0), 1.0);
vec3 pos = origin + dir * min(dist, max_dist);
vec2 sample = cloud_at(pos);
float integral = sample.y * incr;
passthrough *= max(1.0 - integral, 0.0);
cloud_shade = mix(cloud_shade, sample.x, passthrough * integral);
}
}
float total_density = 1.0 - passthrough;// / (1.0 + max(max_dist, start) * 0.0001);
total_density = max(total_density - 1.0 / pow(max_dist, 0.25), 0.0); // Hack
return vec4(vec3(cloud_shade), total_density);
}
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) {
// Sky color
vec3 sun_dir = get_sun_dir(time_of_day);
@ -211,3 +283,8 @@ float fog(vec3 f_pos, vec3 focus_pos, uint medium) {
return pow(clamp((max(fog, mist) - min_fog) / (max_fog - min_fog), 0.0, 1.0), 1.7);
}
vec3 illuminate(vec3 color, vec3 light, vec3 diffuse, vec3 ambience) {
float avg_col = (color.r + color.g + color.b) / 3.0;
return ((color - avg_col) * light + (diffuse + ambience) * avg_col) * (diffuse + ambience);
}

View File

@ -0,0 +1,28 @@
#version 330 core
#include <globals.glsl>
#include <sky.glsl>
#include <srgb.glsl>
#include <lod.glsl>
in vec3 f_pos;
out vec4 tgt_color;
#include <sky.glsl>
void main() {
vec3 f_norm = lod_norm(f_pos.xy);
vec3 f_col = lod_col(f_pos.xy);
vec3 light, diffuse_light, ambient_light;
get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x, cam_pos.xyz, f_pos, 1.0, true, clouds);
vec3 color = mix(mix(surf_color, fog_color, 0.0), clouds.rgb, clouds.a);
tgt_color = vec4(color, 1.0);
}

View File

@ -2,8 +2,7 @@
#include <globals.glsl>
#include <srgb.glsl>
uniform sampler2D t_noise;
#include <lod.glsl>
in vec2 v_pos;
@ -13,23 +12,15 @@ uniform u_locals {
};
out vec3 f_pos;
out vec3 f_norm;
out vec3 f_col;
out float f_light;
void main() {
vec2 pos = v_pos * 1000.0;
f_pos = lod_pos(v_pos);
f_pos = vec3(pos, texture(t_noise, pos * 0.001).x * 1000.0);
//f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
f_col = vec3(0.5, 1.0, 0.3);
f_pos.z -= 25.0 / pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
f_light = 1.0;
f_norm = vec3(0, 0, 1);
gl_Position =
proj_mat *
view_mat *

View File

@ -36,7 +36,7 @@ void main() {
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x, cam_pos.xyz, f_pos, 1.0, true, clouds);
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
vec3 color = mix(mix(surf_color, fog_color, 0.0), clouds.rgb, clouds.a);
tgt_color = vec4(color, 1.0);
}

View File

@ -18,11 +18,60 @@ impl From<gfx::PipelineStateError<String>> for RenderError {
impl From<gfx::PipelineStateError<&str>> for RenderError {
fn from(err: gfx::PipelineStateError<&str>) -> Self {
// This is horrid. We do it to get rid of the `&str`'s lifetime bound by turning it into a `String`.
match err {
gfx::PipelineStateError::DescriptorInit(err) => {
gfx::PipelineStateError::DescriptorInit(err.into())
gfx::PipelineStateError::DescriptorInit(match err {
gfx::pso::InitError::VertexImport(s, x) => {
gfx::pso::InitError::VertexImport(s.to_string(), x)
}
gfx::pso::InitError::ConstantBuffer(s, x) => {
gfx::pso::InitError::ConstantBuffer(
s.to_string(),
x.map(|x| match x {
gfx::pso::ElementError::NotFound(s) => {
gfx::pso::ElementError::NotFound(s.to_string())
}
gfx::pso::ElementError::Offset {
name,
shader_offset,
code_offset,
} => gfx::pso::ElementError::Offset {
name: name.to_string(),
shader_offset,
code_offset,
},
err => err,
gfx::pso::ElementError::Format {
name,
shader_format,
code_format,
} => gfx::pso::ElementError::Format {
name: name.to_string(),
shader_format,
code_format,
},
}),
)
}
gfx::pso::InitError::GlobalConstant(s, x) => {
gfx::pso::InitError::GlobalConstant(s.to_string(), x)
}
gfx::pso::InitError::ResourceView(s, x) => {
gfx::pso::InitError::ResourceView(s.to_string(), x)
}
gfx::pso::InitError::UnorderedView(s, x) => {
gfx::pso::InitError::UnorderedView(s.to_string(), x)
}
gfx::pso::InitError::Sampler(s, x) => {
gfx::pso::InitError::Sampler(s.to_string(), x)
}
gfx::pso::InitError::PixelExport(s, x) => {
gfx::pso::InitError::PixelExport(s.to_string(), x)
}
})
}
gfx::PipelineStateError::Program(p) => gfx::PipelineStateError::Program(p),
gfx::PipelineStateError::DeviceCreate(c) => gfx::PipelineStateError::DeviceCreate(c),
}
.into()
}

View File

@ -760,8 +760,6 @@ fn create_pipelines(
),
RenderError,
> {
dbg!("start");
let globals =
assets::load_watched::<String>("voxygen.shaders.include.globals", shader_reload_indicator)
.unwrap();
@ -777,6 +775,9 @@ fn create_pipelines(
let random =
assets::load_watched::<String>("voxygen.shaders.include.random", shader_reload_indicator)
.unwrap();
let lod =
assets::load_watched::<String>("voxygen.shaders.include.lod", shader_reload_indicator)
.unwrap();
let anti_alias = assets::load_watched::<String>(
&["voxygen.shaders.antialias.", match aa_mode {
@ -807,6 +808,7 @@ fn create_pipelines(
include_ctx.include("light.glsl", &light);
include_ctx.include("srgb.glsl", &srgb);
include_ctx.include("random.glsl", &random);
include_ctx.include("lod.glsl", &lod);
include_ctx.include("anti-aliasing.glsl", &anti_alias);
include_ctx.include("cloud.glsl", &cloud);
@ -898,14 +900,15 @@ fn create_pipelines(
shader_reload_indicator,
)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.terrain-frag", shader_reload_indicator)
&assets::load_watched::<String>(
"voxygen.shaders.lod-terrain-frag",
shader_reload_indicator,
)
.unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
dbg!("created lod pipeline");
// Construct a pipeline for rendering our post-processing
let postprocess_pipeline = create_pipeline(
factory,
@ -924,8 +927,6 @@ fn create_pipelines(
gfx::state::CullFace::Back,
)?;
dbg!("created pipelines");
Ok((
skybox_pipeline,
figure_pipeline,
@ -947,22 +948,11 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
ctx: &IncludeContext,
cull_face: gfx::state::CullFace,
) -> Result<GfxPipeline<P>, RenderError> {
dbg!("Expanding context...");
let vs = ctx.expand(vs)?;
dbg!("expanded vs!");
let fs = ctx.expand(fs)?;
dbg!("expanded fs!");
dbg!("vs = {}, fs = {}", vs.as_bytes().len(), fs.as_bytes().len());
let program = factory.link_program(vs.as_bytes(), fs.as_bytes())?;
dbg!("linked");
let result = Ok(GfxPipeline {
pso: factory.create_pipeline_from_program(
&program,
@ -978,7 +968,5 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
)?,
});
dbg!("finished pipeline");
result
}

View File

@ -13,7 +13,7 @@ impl Lod {
pub fn new(renderer: &mut Renderer) -> Self {
Self {
model: renderer
.create_model(&create_lod_terrain_mesh(256))
.create_model(&create_lod_terrain_mesh(100))
.unwrap(),
locals: renderer.create_consts(&[Locals::default()]).unwrap(),
}
@ -25,7 +25,7 @@ impl Lod {
}
fn create_lod_terrain_mesh(detail: usize) -> Mesh<LodTerrainPipeline> {
let transform = |x| (2.0 * x as f32) / detail as f32 - 2.0;
let transform = |x| (2.0 * x as f32) / detail as f32 - 1.0;
let mut mesh = Mesh::new();