diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index 1b6d7c24e6..9f2d0fb7f0 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -14,6 +14,8 @@ uniform u_locals { float load_time; }; +uniform sampler2D t_waves; + out vec4 tgt_color; #include <sky.glsl> @@ -46,7 +48,25 @@ void main() { hex_pos = floor(hex_pos); */ - vec3 norm = warp_normal(f_norm, f_pos, tick.x); + vec3 b_norm; + if (f_norm.z > 0.0) { + b_norm = vec3(1, 0, 0); + } else if (f_norm.x > 0.0) { + b_norm = vec3(0, 1, 0); + } else { + b_norm = vec3(0, 0, 1); + } + vec3 c_norm = cross(f_norm, b_norm); + + vec3 nmap = normalize( + (texture(t_waves, fract(f_pos.xy * 0.3 + tick.x * 0.04)).rgb - 0.0) * 0.05 + + (texture(t_waves, fract(f_pos.xy * 0.1 - tick.x * 0.08)).rgb - 0.0) * 0.1 + + (texture(t_waves, fract(-f_pos.yx * 0.06 - tick.x * 0.1)).rgb - 0.0) * 0.1 + + (texture(t_waves, fract(-f_pos.yx * 0.03 - tick.x * 0.01)).rgb - 0.0) * 0.2 + + vec3(0, 0, 0.1) + ); + + vec3 norm = f_norm * nmap.z + b_norm * nmap.x + c_norm * nmap.y; vec3 light, diffuse_light, ambient_light; get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 0.0); @@ -67,10 +87,11 @@ void main() { reflect_ray_dir.z = max(reflect_ray_dir.z, 0.05); vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, false) * f_light; + //reflect_color = vec3(reflect_color.r + reflect_color.g + reflect_color.b) / 3.0; // 0 = 100% reflection, 1 = translucent water - float passthrough = pow(dot(faceforward(norm, norm, cam_to_frag), -cam_to_frag), 1.0); + float passthrough = pow(dot(faceforward(norm, norm, cam_to_frag), -cam_to_frag), 0.5); - vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 3.0 / (1.0 + diffuse_light * 2.0)), passthrough); + vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 4.0 / (1.0 + diffuse_light * 2.0)), passthrough); tgt_color = mix(color, vec4(fog_color, 0.0), fog_level); } diff --git a/assets/voxygen/texture/waves.png b/assets/voxygen/texture/waves.png new file mode 100644 index 0000000000..dd0e758836 Binary files /dev/null and b/assets/voxygen/texture/waves.png differ diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 89c05bd882..e387437da1 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -29,6 +29,8 @@ gfx_defines! { lights: gfx::ConstantBuffer<Light> = "u_lights", shadows: gfx::ConstantBuffer<Shadow> = "u_shadows", + waves: gfx::TextureSampler<[f32; 4]> = "t_waves", + tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_TEST, } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 3597444726..94c2330915 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -354,8 +354,10 @@ impl Renderer { pub fn create_texture<P: Pipeline>( &mut self, image: &image::DynamicImage, + filter_method: Option<gfx::texture::FilterMethod>, + wrap_mode: Option<gfx::texture::WrapMode>, ) -> Result<Texture<P>, RenderError> { - Texture::new(&mut self.factory, image) + Texture::new(&mut self.factory, image, filter_method, wrap_mode) } /// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the specified dimensions. @@ -518,6 +520,7 @@ impl Renderer { locals: &Consts<terrain::Locals>, lights: &Consts<Light>, shadows: &Consts<Shadow>, + waves: &Texture<fluid::FluidPipeline>, ) { self.encoder.draw( &gfx::Slice { @@ -534,6 +537,7 @@ impl Renderer { globals: globals.buf.clone(), lights: lights.buf.clone(), shadows: shadows.buf.clone(), + waves: (waves.srv.clone(), waves.sampler.clone()), tgt_color: self.tgt_color_view.clone(), tgt_depth: self.tgt_depth_view.clone(), }, diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index e4c528efbf..66d0af88c4 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -24,6 +24,8 @@ impl<P: Pipeline> Texture<P> { pub fn new( factory: &mut gfx_backend::Factory, image: &DynamicImage, + filter_method: Option<gfx::texture::FilterMethod>, + wrap_mode: Option<gfx::texture::WrapMode>, ) -> Result<Self, RenderError> { let (tex, srv) = factory .create_texture_immutable_u8::<ShaderFormat>( @@ -41,12 +43,13 @@ impl<P: Pipeline> Texture<P> { tex, srv, sampler: factory.create_sampler(gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Scale, - gfx::texture::WrapMode::Clamp, + filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), + wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), )), _phantom: PhantomData, }) } + pub fn new_dynamic( factory: &mut gfx_backend::Factory, width: u16, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 2831d2785b..1567f65f57 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -2,7 +2,7 @@ use crate::{ mesh::Meshable, render::{ Consts, FluidPipeline, Globals, Instances, Light, Mesh, Model, Renderer, Shadow, - SpriteInstance, SpritePipeline, TerrainLocals, TerrainPipeline, + SpriteInstance, SpritePipeline, TerrainLocals, TerrainPipeline, Texture, }, }; @@ -208,6 +208,7 @@ pub struct Terrain<V: RectRasterableVol> { // GPU data sprite_models: HashMap<(BlockKind, usize), Model<SpritePipeline>>, + waves: Texture<FluidPipeline>, phantom: PhantomData<V>, } @@ -656,6 +657,13 @@ impl<V: RectRasterableVol> Terrain<V> { ] .into_iter() .collect(), + waves: renderer + .create_texture( + &assets::load_expect("voxygen.texture.waves"), + Some(gfx::texture::FilterMethod::Bilinear), + Some(gfx::texture::WrapMode::Tile), + ) + .expect("Failed to create wave texture"), phantom: PhantomData, } } @@ -1024,7 +1032,7 @@ impl<V: RectRasterableVol> Terrain<V> { .map(|model| (model, &chunk.locals)) }) .for_each(|(model, locals)| { - renderer.render_fluid_chunk(model, globals, locals, lights, shadows) + renderer.render_fluid_chunk(model, globals, locals, lights, shadows, &self.waves) }); } }