mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Working LoD shader
This commit is contained in:
parent
f13d98ee3e
commit
63d1b2bb22
@ -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);
|
||||
}
|
||||
|
46
assets/voxygen/shaders/include/lod.glsl
Normal file
46
assets/voxygen/shaders/include/lod.glsl
Normal 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;
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
uniform sampler2D t_noise;
|
||||
|
||||
float hash(vec4 p) {
|
||||
p = fract( p*0.3183099+.1);
|
||||
p *= 17.0;
|
||||
|
@ -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);
|
||||
}
|
||||
|
28
assets/voxygen/shaders/lod-terrain-frag.glsl
Normal file
28
assets/voxygen/shaders/lod-terrain-frag.glsl
Normal 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);
|
||||
}
|
@ -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 *
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user