Greedy messhing for shadows.

This commit is contained in:
Joshua Yanovski 2020-05-19 17:22:06 +02:00
parent a4d87e1875
commit 560501df05
18 changed files with 435 additions and 83 deletions

View File

@ -76,6 +76,7 @@ void main() {
// f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
gl_Position = all_mat * vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -62,6 +62,7 @@ void main() {
gl_Position =
all_mat *
vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -32,10 +32,13 @@ float attenuation_strength(vec3 rpos) {
uniform samplerCubeShadow t_shadow_maps;
// uniform samplerCube t_shadow_maps;
// uniform sampler2DArray t_directed_shadow_maps;
float VectorToDepth (vec3 Vec)
{
vec3 AbsVec = abs(Vec);
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
// float LocalZcomp = length(Vec);
// Replace f and n with the far and near plane values you used when
// you drew your cube map.
@ -43,8 +46,15 @@ float VectorToDepth (vec3 Vec)
// const float n = 1.0;
// float NormZComp = (screen_res.w+screen_res.z) / (screen_res.w-screen_res.z) - (2*screen_res.w*screen_res.z)/(screen_res.w-screen_res.z)/LocalZcomp;
// float NormZComp = 1.0 - shadow_proj_factors.y / shadow_proj_factors.x / LocalZcomp;
float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp;
// NormZComp = -1000.0 / (NormZComp + 10000.0);
return (NormZComp + 1.0) * 0.5;
// float NormZComp = length(LocalZcomp);
// NormZComp = -NormZComp / screen_res.w;
// // return (NormZComp + 1.0) * 0.5;
// return NormZComp;
}
const vec3 sampleOffsetDirections[20] = vec3[]
@ -59,27 +69,34 @@ const vec3 sampleOffsetDirections[20] = vec3[]
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{
// float shadow = 0.0;
float bias = 0.0;//-0.1;//0.0;//0.1
// int samples = 20;
if (lightIndex != 0u) {
return 1.0;
};
float shadow = 0.0;
float bias = -0.015;//-0.05;//-0.1;//0.0;//0.1
int samples = 20;
// float lightDistance = length(fragToLight);
// float viewDistance = length(cam_pos.xyz - fragPos);
// // float diskRadius = 0.00001;
// // float diskRadius = 1.0;
// float diskRadius = (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 2.0;
// // float diskRadius = lightDistance;
// for(int i = 0; i < samples; ++i)
// {
// float currentDepth = VectorToDepth(fragToLight + sampleOffsetDirections[i] * diskRadius) + bias;
// // float closestDepth = texture(depthMap, fragToLight).r;
// // closestDepth *= far_plane; // Undo mapping [0;1]
// /* if(currentDepth - bias > closestDepth)
// shadow += 1.0;*/
// float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));
// shadow += visibility;
// }
// shadow /= float(samples);
// // shadow = shadow * shadow * (3.0 - 2.0 * shadow);
float viewDistance = length(cam_pos.xyz - fragPos);
// float diskRadius = 0.00001;
// float diskRadius = 1.0;
// float diskRadius = 0.05;
float diskRadius = (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 25.0;
// float diskRadius = lightDistance;
for(int i = 0; i < samples; ++i)
{
float currentDepth = VectorToDepth(fragToLight + sampleOffsetDirections[i] * diskRadius) + bias;
// float closestDepth = texture(depthMap, fragToLight).r;
// closestDepth *= far_plane; // Undo mapping [0;1]
/* if(currentDepth - bias > closestDepth)
shadow += 1.0;*/
float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth)/*, -2.5*/);
shadow += visibility;
// float closestDepth = texture(t_shadow_maps, vec3(fragToLight)/*, -2.5*/).r;
// shadow += closestDepth > currentDepth ? 1.0 : 0.0;
}
shadow /= float(samples);
// shadow = shadow * shadow * (3.0 - 2.0 * shadow);
// use the light to fragment vector to sample from the depth map
// float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
@ -95,15 +112,11 @@ float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*
// currentDepth += bias;
// currentDepth = -1000.0 / (currentDepth + 10000.0);
// currentDepth /= screen_res.w;
float currentDepth = VectorToDepth(fragToLight) + bias;
if (lightIndex != 0u) {
return 1.0;
};
// float currentDepth = VectorToDepth(fragToLight) + bias;
float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
return visibility;
// return shadow;
// float visibility = texture(t_shadow_maps, vec4(fragToLight, 0.0), currentDepth);// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
// return visibility;
return shadow;
}
#else
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
@ -284,7 +297,7 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
// mix(cam_strength, strength, cam_distance_2 / (cam_distance_2 + distance_2));
// max(cam_strength, strength);//mix(cam_strength, strength, clamp(distance_2 / /*pos_distance_2*/cam_distance_2, 0.0, 1.0));
// float both_strength = mix(cam_strength, strength, cam_distance_2 / sqrt(cam_distance_2 + distance_2));
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*/computed_shadow * both_strength * square_factor * square_factor * PI * color;
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*//*computed_shadow * */both_strength * square_factor * square_factor * PI * color;
// max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*/max(cam_strength, 1.0/*, strength*//*1.0*/) * square_factor * square_factor * PI * color;
// light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIENCE);
// Compute emiittance.

View File

@ -26,7 +26,7 @@
// Currently, we only need lights for the light position
#include <light.glsl>
// in vec3 FragPos; // FragPos from GS (output per emitvertex)
in vec3 FragPos; // FragPos from GS (output per emitvertex)
// flat in int FragLayer;
void main()
@ -35,14 +35,14 @@ void main()
// distance.
/*if (FragLayer > 0) */{
// get distance between fragment and light source
// float lightDistance = length(FragPos - lights[((FragLayer - 1) & 31)].light_pos.xyz);
// float lightDistance = length(FragPos - lights[((/*FragLayer*/1 - 1) & 31)].light_pos.xyz);
// map to [0;1] range by dividing by far_plane
// lightDistance = lightDistance / /*FragPos.w;*/screen_res.w;
// // map to [0;1] range by dividing by far_plane
// lightDistance = lightDistance / screen_res.w;//FragPos.w;//screen_res.w;
// write this as modified depth
// lightDistance = -1000.0 / (lightDistance + 10000.0);
// lightDistance /= screen_res.w;
// // write this as modified depth
// // lightDistance = -1000.0 / (lightDistance + 10000.0);
// // lightDistance /= screen_res.w;
// gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance
}
}

View File

@ -169,7 +169,7 @@
layout (triangles/*, invocations = 6*/) in;
layout (triangle_strip, max_vertices = /*MAX_LAYER_VERTICES_PER_FACE*/96) out;
layout (triangle_strip, max_vertices = /*MAX_LAYER_VERTICES_PER_FACE*//*96*/18) out;
struct ShadowLocals {
mat4 shadowMatrices;
@ -245,6 +245,10 @@ void main() {
int layer_face = layer_base + face;
gl_Layer = face;//layer_face; // built-in variable that specifies to which face we render.
gl_Position = shadowMats[layer_face].shadowMatrices * vec4(FragPos, 1.0);
// gl_Position.z = -((gl_Position.z + screen_res.z) / (screen_res.w - screen_res.z)) * lightDistance;
// gl_Position.z = gl_Position.z / screen_res.w;
// gl_Position.z = gl_Position.z / gl_Position.w;
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// lightDistance = -(lightDistance + screen_res.z) / (screen_res.w - screen_res.z);
// gl_Position.z = lightDistance;
EmitVertex();

View File

@ -27,7 +27,8 @@
* */
in uint v_pos_norm;
in uint v_col_light;
// in uint v_col_light;
// in vec4 v_pos;
// Light projection matrices.
layout (std140)
@ -42,11 +43,12 @@ const int EXTRA_NEG_Z = 32768;
void main() {
vec3 f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
// f_pos = f_chunk_pos + model_offs;
// f_pos = v_pos;
vec3 f_pos = f_chunk_pos + model_offs;
// f_pos = v_pos;
// vec3 f_pos = f_chunk_pos + model_offs;
gl_Position = /*all_mat * */vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*/uintBitsToFloat(v_pos_norm)/*1.0*/);
// gl_Position = v_pos + vec4(model_offs, 0.0);
gl_Position = /*all_mat * */vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0);
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
// vec4(v_pos, 0.0, 1.0);
}

View File

@ -298,9 +298,13 @@ void main() {
// f_ao = 1.0;
// f_ao = dot(f_ao_vec, sqrt(1.0 - delta_sides * delta_sides));
f_ao = sqrt(dot(f_ao_vec * abs(voxel_norm), sqrt(1.0 - delta_sides * delta_sides)) / 3.0);
// f_ao = dot(abs(voxel_norm), f_ao_vec);
// voxel_norm = f_norm;
// vec3 ao_pos2 = min(fract(f_pos), 1.0 - fract(f_pos));
// f_ao = sqrt(dot(ao_pos2, ao_pos2));
// // f_ao = dot(abs(voxel_norm), f_ao_vec);
// // voxel_norm = f_norm;
// Note: because voxels, we reduce the normal for reflections to just its z component, dpendng on distance to camera.
// Idea: the closer we are to facing top-down, the more the norm should tend towards up-z.

View File

@ -95,6 +95,7 @@ void main() {
proj_mat *
view_mat *
vec4(f_pos/*newRay*/, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -70,6 +70,8 @@ void main() {
gl_Position =
all_mat *
vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -38,6 +38,15 @@ out vec4 tgt_color;
#include <lod.glsl>
void main() {
// vec4 light_col = vec4(
// hash(floor(vec4(f_pos.x, 0, 0, 0))),
// hash(floor(vec4(0, f_pos.y, 0, 1))),
// hash(floor(vec4(0, 0, f_pos.z, 2))),
// 1.0
// );
// vec3 f_col = light_col.rgb;//vec4(1.0, 0.0, 0.0, 1.0);
// tgt_color = vec4(f_col, 1.0);
// return;
// tgt_color = vec4(0.0, 0.0, 0.0, 1.0);
// float sum = 0.0;
// for (uint i = 0u; i < /* 6 * */light_shadow_count.x; i ++) {
@ -62,10 +71,13 @@ void main() {
// // vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
// // use the light to fragment vector to sample from the depth map
// float bias = 0.05;//0.05;
// float bias = 0.0;//0.05;//0.05;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, i)/*, 0.0*//*, bias*/).r;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// float closestDepth = texture(t_shadow_maps, vec4(fragToLight, i + 1)/*, bias*/).r;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, i + 1)/*, bias*/).r;
// float currentDepth = VectorToDepth(fragToLight) + bias;
// float closestDepth = texture(t_shadow_maps, vec3(fragToLight)/*, -2.5*/).r;
//
// // float visibility = texture(t_shadow_maps, vec4(fragToLight, i + 1), -(length(fragToLight) - bias)/* / screen_res.w*/);
// // it is currently in linear range between [0,1]. Re-transform back to original value
// // closestDepth *= screen_res.w; // far plane
@ -74,7 +86,8 @@ void main() {
// // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
// // tgt_color += light_col * vec4(vec3(/*closestDepth*/visibility/* + bias*//* / screen_res.w */) * 1.0 / light_shadow_count.x, 0.0);
// tgt_color.rgb += light_col * vec3(closestDepth + 0.05 / screen_res.w) * 1.0 /*/ light_shadow_count.x*/ * light_strength;
// // tgt_color.rgb += light_col * vec3(closestDepth + 0.05 / screen_res.w) * 1.0 /*/ light_shadow_count.x*/ * light_strength;
// tgt_color.rgb += light_col * vec3(closestDepth) * 1.0 / screen_res.w /*/ light_shadow_count.x*/ * light_strength;
// sum += light_strength;
// }

View File

@ -99,6 +99,8 @@ void main() {
gl_Position =
all_mat *
vec4(f_pos/*newRay*/, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -7,11 +7,16 @@ use crate::render::{self, Mesh};
pub trait Meshable<'a, P: render::Pipeline, T: render::Pipeline> {
type Pipeline: render::Pipeline;
type TranslucentPipeline: render::Pipeline;
type ShadowPipeline: render::Pipeline;
type Supplement;
// Generate meshes - one opaque, one translucent
// Generate meshes - one opaque, one translucent, one shadow
fn generate_mesh(
&'a self,
supp: Self::Supplement,
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>);
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
);
}

View File

@ -20,13 +20,20 @@ where
* &'a V: BaseVol<Vox=Cell>, */
{
type Pipeline = FigurePipeline;
type ShadowPipeline = FigurePipeline;
type Supplement = (Vec3<f32>, Vec3<f32>);
type TranslucentPipeline = FigurePipeline;
// TODO: Make sprites cast shadows?
fn generate_mesh(
&'a self,
(offs, scale): Self::Supplement,
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
) {
let mut mesh = Mesh::new();
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
@ -74,7 +81,7 @@ where
}
}
(mesh, Mesh::new())
(mesh, Mesh::new(), Mesh::new())
}
}
@ -86,13 +93,20 @@ where
* &'a V: BaseVol<Vox=Cell>, */
{
type Pipeline = SpritePipeline;
type ShadowPipeline = SpritePipeline;
type Supplement = (Vec3<f32>, Vec3<f32>);
type TranslucentPipeline = SpritePipeline;
// TODO: Make sprites cast shadows?
fn generate_mesh(
&'a self,
(offs, scale): Self::Supplement,
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
) {
let mut mesh = Mesh::new();
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
@ -139,7 +153,7 @@ where
}
}
(mesh, Mesh::new())
(mesh, Mesh::new(), Mesh::new())
}
}

View File

@ -1,6 +1,6 @@
use crate::{
mesh::{vol, Meshable},
render::{self, FluidPipeline, Mesh, TerrainPipeline},
render::{self, mesh::Quad, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
};
use common::{
terrain::{Block, BlockKind},
@ -12,6 +12,7 @@ use vek::*;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
type FluidVertex = <FluidPipeline as render::Pipeline>::Vertex;
type ShadowVertex = <ShadowPipeline as render::Pipeline>::Vertex;
trait Blendable {
fn is_blended(&self) -> bool;
@ -202,13 +203,18 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
Meshable<'a, TerrainPipeline, FluidPipeline> for VolGrid2d<V>
{
type Pipeline = TerrainPipeline;
type ShadowPipeline = ShadowPipeline;
type Supplement = Aabb<i32>;
type TranslucentPipeline = FluidPipeline;
fn generate_mesh(
&'a self,
range: Self::Supplement,
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
) {
let mut light = calc_light(range, self);
let mut lowest_opaque = range.size().d;
@ -463,7 +469,84 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
// opaque_mesh
// });
(opaque_mesh, fluid_mesh)
let mut shadow_mesh = Mesh::new();
let x_size = (range.size().w - 2) as usize;
let y_size = (range.size().h - 2) as usize;
let z_size = (z_end - z_start + 1) as usize;
let draw_delta = Vec3::new(1, 1, z_start);
let mesh_delta = Vec3::new(0, 0, z_start + range.min.z);
// x (u = y, v = z)
greedy_mesh_cross_section(
Vec3::new(y_size, z_size, x_size),
|pos| {
should_draw_greedy(
Vec3::new(pos.z, pos.x, pos.y),
draw_delta,
Vec3::unit_x(), /* , pos.z, 0, x_size */
|pos| flat_get(pos),
)
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.z, pos.x, pos.y),
mesh_delta,
dim,
Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
Vec3::unit_x(),
faces_forward,
));
},
);
// y (u = z, v = x)
greedy_mesh_cross_section(
Vec3::new(z_size, x_size, y_size),
|pos| {
should_draw_greedy(
Vec3::new(pos.y, pos.z, pos.x),
draw_delta,
Vec3::unit_y(), /* , pos.z, 0, y_size */
|pos| flat_get(pos),
)
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.y, pos.z, pos.x),
mesh_delta,
dim,
Vec2::new(Vec3::unit_z(), Vec3::unit_x()),
Vec3::unit_y(),
faces_forward,
));
},
);
// z (u = x, v = y)
greedy_mesh_cross_section(
Vec3::new(x_size, y_size, z_size),
|pos| {
should_draw_greedy(
Vec3::new(pos.x, pos.y, pos.z),
draw_delta,
Vec3::unit_z(), /* , pos.z, 0, z_size */
|pos| flat_get(pos),
)
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.x, pos.y, pos.z),
mesh_delta,
dim,
Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
Vec3::unit_z(),
faces_forward,
));
},
);
(opaque_mesh, fluid_mesh, shadow_mesh)
}
}
@ -493,6 +576,154 @@ fn faces_to_make<M: Clone>(
]
}
// Greedy meshing.
fn greedy_mesh_cross_section(
/* mask: &mut [bool], */
dims: Vec3<usize>,
// Should we draw a face here (below this vertex)? If so, is it front or back facing?
draw_face: impl Fn(Vec3<usize>) -> Option<bool>,
// Vertex, width and height, and whether it's front facing (face is implicit from the cross
// section).
mut push_quads: impl FnMut(Vec3<usize>, Vec2<usize>, bool),
) {
// mask represents which faces are either set while the other is unset, or unset
// while the other is set.
let mut mask = vec![None; dims.y * dims.x];
(0..dims.z + 1).for_each(|d| {
// Compute mask
mask.iter_mut().enumerate().for_each(|(posi, mask)| {
let i = posi % dims.x;
let j = posi / dims.x;
*mask = draw_face(Vec3::new(i, j, d));
});
(0..dims.y).for_each(|j| {
let mut i = 0;
while i < dims.x {
// Compute width (number of set x bits for this row and layer, starting at the
// current minimum column).
if let Some(ori) = mask[j * dims.x + i] {
let width = 1 + mask[j * dims.x + i + 1..j * dims.x + dims.x]
.iter()
.take_while(move |&&mask| mask == Some(ori))
.count();
let max_x = i + width;
// Compute height (number of rows having w set x bits for this layer, starting
// at the current minimum column and row).
let height = 1
+ (j + 1..dims.y)
.take_while(|h| {
mask[h * dims.x + i..h * dims.x + max_x]
.iter()
.all(|&mask| mask == Some(ori))
})
.count();
let max_y = j + height;
// Add quad.
push_quads(Vec3::new(i, j, d /* + 1 */), Vec2::new(width, height), ori);
// Unset mask bits in drawn region, so we don't try to re-draw them.
(j..max_y).for_each(|l| {
mask[l * dims.x + i..l * dims.x + max_x]
.iter_mut()
.for_each(|mask| {
*mask = None;
});
});
// Update x value.
i = max_x;
} else {
i += 1;
}
}
});
});
}
fn create_quad_greedy(
origin: Vec3<usize>,
mesh_delta: Vec3<i32>,
dim: Vec2<usize>,
uv: Vec2<Vec3<f32>>,
norm: Vec3<f32>,
faces_forward: bool,
) -> Quad<ShadowPipeline> {
let origin = origin.map(|e| e as i32) + mesh_delta;
// let origin = (uv.x * origin.x + uv.y * origin.y + norm * origin.z) +
// Vec3::new(0, 0, z_start + range.min.z - 1);//Vec3::new(-1, -1, z_start +
// range.min.z - 1);
let origin = origin.map(|e| e as f32); // + orientation.z;
// let origin = uv.x * origin.x + uv.y * origin.y + norm * origin.z +
// Vec3::new(0.0, 0.0, (z_start + range.min.z - 1) as f32);
/* if (origin.x < 0.0 || origin.y < 0.0) {
return;
} */
// let ori = if faces_forward { Vec3::new(u, v, norm) } else { Vec3::new(uv.y,
// uv.x, -norm) };
let dim = uv.map2(dim.map(|e| e as f32), |e, f| e * f);
let (dim, norm) = if faces_forward {
(dim, norm)
} else {
(Vec2::new(dim.y, dim.x), -norm)
};
// let (uv, norm, origin) = if faces_forward { (uv, norm, origin) } else {
// (Vec2::new(uv.y, uv.x), -norm, origin) }; let (uv, norm, origin) = if
// faces_forward { (uv, norm, origin) } else { (Vec2::new(uv.y, uv.x), -norm,
// origin/* - norm*/) }; let origin = Vec3::new(origin.x as f32., origin.y
// as f32, (origin.z + z_start) as f32); let norm = norm.map(|e| e as f32);
Quad::new(
ShadowVertex::new(origin, norm),
ShadowVertex::new(origin + dim.x, norm),
ShadowVertex::new(origin + dim.x + dim.y, norm),
ShadowVertex::new(origin + dim.y, norm),
)
}
fn should_draw_greedy(
pos: Vec3<usize>,
draw_delta: Vec3<i32>,
delta: Vec3<i32>,
/* depth, min_depth, max_depth, */ flat_get: impl Fn(Vec3<i32>) -> Block,
) -> Option<bool> {
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
//
/* if (depth as isize) <= min_depth {
// let to = flat_get(pos).is_opaque();
debug_assert!(depth <= max_depth);
/* if depth >= max_depth - 1 {
let from = flat_get(pos - delta).is_opaque();
} else {
None
} */
if flat_get(pos + delta).is_opaque() {
Some(true)
} else {
None
}
} else */
{
let from = flat_get(pos - delta).is_opaque(); // map(|v| v.is_opaque()).unwrap_or(false);
//
/* if depth > max_depth {
if from {
// Backward-facing
Some(false)
} else {
None
}
} else */
{
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
if from == to {
None
} else {
// If going from transparent to opaque, forward facing; otherwise, backward
// facing.
Some(from)
}
}
}
}
/*
impl<V: BaseVol<Vox = Block> + ReadVol + Debug> Meshable for VolGrid3d<V> {
type Pipeline = TerrainPipeline;

View File

@ -1,15 +1,20 @@
use super::{
super::{util::arr_to_mat, Pipeline, ShadowDepthStencilFmt, TerrainLocals},
terrain::Vertex,
Globals, Light, Shadow,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner,
gfx_pipeline_inner, gfx_vertex_struct_meta,
};
use vek::*;
gfx_defines! {
vertex Vertex {
// pos: [f32; 4] = "v_pos",
pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
}
constant Locals {
shadow_matrices: [[f32; 4]; 4] = "shadowMatrices",
}
@ -35,6 +40,39 @@ gfx_defines! {
}
}
impl Vertex {
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 {
if norm.y < 0.0 { 2 } else { 3 }
} else {
if norm.z < 0.0 { 4 } else { 5 }
};
// let ao = 0xFFu32;
// let light = 0xFFu32;
// let col = Rgb::new(1.0f32, 0.0, 0.0);
let meta = true;
const EXTRA_NEG_Z: f32 = 32768.0;
Self {
pos_norm: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29,
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
}
impl Locals {
pub fn new(shadow_mat: Mat4<f32>) -> Self {
Self {

View File

@ -388,7 +388,7 @@ impl Renderer {
),
RenderError,
> {
let levels = 1;
let levels = 1; //10;
/* let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
>::get_channel_type();
@ -420,7 +420,7 @@ impl Renderer {
let shadow_tex = factory
.create_texture(
gfx::texture::Kind::/*CubeArray*/Cube(size / 4 /* size * 2*//*, 32 */),
1 as gfx::texture::Level,
levels as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data,
Some(depth_stencil_cty),
@ -431,18 +431,21 @@ impl Renderer {
let mut sampler_info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Border,
gfx::texture::WrapMode::Clamp, //Border,
);
sampler_info.comparison = Some(Comparison::LessEqual);
sampler_info.comparison = Some(Comparison::Less);
// sampler_info.lod_bias = (-3.0).into();
// sampler_info.lod_range = (1.into(), (levels - 1).into());
sampler_info.border = [1.0; 4].into();
let shadow_tex_sampler = factory.create_sampler(sampler_info);
/* let tgt_shadow_view = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
let tgt_shadow_view = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(1),
0, // levels,
None, // Some(1),
gfx::texture::DepthStencilFlags::empty(),
)?; */
let tgt_shadow_view = factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
)?;
// let tgt_shadow_view =
// factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
/* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex,
(0, levels - 1),
@ -879,6 +882,7 @@ impl Renderer {
/// frame.
pub fn render_terrain_chunk(
&mut self,
// model: &Model<shadow::ShadowPipeline>,
model: &Model<terrain::TerrainPipeline>,
globals: &Consts<Globals>,
locals: &Consts<terrain::Locals>,
@ -921,7 +925,7 @@ impl Renderer {
/// Queue the rendering of the player silhouette in the upcoming frame.
pub fn render_shadow(
&mut self,
model: &Model<terrain::TerrainPipeline>,
model: &Model<shadow::ShadowPipeline>,
globals: &Consts<Globals>,
terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<shadow::Locals>,
@ -1506,14 +1510,14 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
// Second-depth shadow mapping: should help reduce z-fighting provided all objects
// are "watertight" (every triangle edge is shared with at most one other
// triangle); this *should* be true for Veloren.
cull_face: /*gfx::state::CullFace::Nothing*/match cull_face {
gfx::state::CullFace::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
},
cull_face, /*gfx::state::CullFace::Nothing*//*match cull_face {
gfx::state::CullFace::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
}*/
method: gfx::state::RasterMethod::Fill,
offset: None,//Some(gfx::state::Offset(4, /*10*/-10)),
samples:None,//Some(gfx::state::MultiSample),
offset: None, //Some(gfx::state::Offset(2, 10)),
samples: None, // Some(gfx::state::MultiSample),
},
pipe,
)?,

View File

@ -43,8 +43,8 @@ const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not
// const NEAR_PLANE: f32 = 0.5;
// const FAR_PLANE: f32 = 100000.0;
const SHADOW_NEAR: f32 = 1.0; //1.0; //0.5;//1.0; // Near plane for shadow map rendering.
const SHADOW_FAR: f32 = 128.0; //25.0; //100000.0;//25.0; // Far plane for shadow map rendering.
const SHADOW_NEAR: f32 = 0.25; //1.0; //0.5;//1.0; // Near plane for shadow map rendering.
const SHADOW_FAR: f32 = 128.0; //100000.0;//128.0; //25.0; //100000.0;//25.0; // Far plane for shadow map rendering.
/// Above this speed is considered running
/// Used for first person camera effects

View File

@ -2,7 +2,8 @@ use crate::{
mesh::Meshable,
render::{
Consts, FluidPipeline, Globals, Instances, Light, Mesh, Model, Renderer, Shadow,
ShadowLocals, SpriteInstance, SpritePipeline, TerrainLocals, TerrainPipeline, Texture,
ShadowLocals, ShadowPipeline, SpriteInstance, SpritePipeline, TerrainLocals,
TerrainPipeline, Texture,
},
};
@ -27,10 +28,12 @@ struct TerrainChunkData {
load_time: f32,
opaque_model: Model<TerrainPipeline>,
fluid_model: Option<Model<FluidPipeline>>,
shadow_model: Model<ShadowPipeline>,
sprite_instances: HashMap<(BlockKind, usize), Instances<SpriteInstance>>,
locals: Consts<TerrainLocals>,
visible: bool,
can_shadow: bool,
z_bounds: (f32, f32),
frustum_last_plane_index: u8,
}
@ -48,6 +51,7 @@ struct MeshWorkerResponse {
z_bounds: (f32, f32),
opaque_mesh: Mesh<TerrainPipeline>,
fluid_mesh: Mesh<FluidPipeline>,
shadow_mesh: Mesh<ShadowPipeline>,
sprite_instances: HashMap<(BlockKind, usize), Vec<SpriteInstance>>,
started_tick: u64,
}
@ -254,12 +258,13 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample,
range: Aabb<i32>,
) -> MeshWorkerResponse {
let (opaque_mesh, fluid_mesh) = volume.generate_mesh(range);
let (opaque_mesh, fluid_mesh, shadow_mesh) = volume.generate_mesh(range);
MeshWorkerResponse {
pos,
z_bounds,
opaque_mesh,
fluid_mesh,
shadow_mesh,
// Extract sprite locations from volume
sprite_instances: {
let mut instances = HashMap::new();
@ -2106,6 +2111,9 @@ impl<V: RectRasterableVol> Terrain<V> {
} else {
None
},
shadow_model: renderer
.create_model(&response.shadow_mesh)
.expect("Failed to upload chunk mesh to the GPU!"),
sprite_instances: response
.sprite_instances
.into_iter()
@ -2130,6 +2138,7 @@ impl<V: RectRasterableVol> Terrain<V> {
}])
.expect("Failed to upload chunk locals to the GPU!"),
visible: false,
can_shadow: false,
z_bounds: response.z_bounds,
frustum_last_plane_index: 0,
});
@ -2155,8 +2164,8 @@ impl<V: RectRasterableVol> Terrain<V> {
// Limit focus_pos to chunk bounds and ensure the chunk is within the fog
// boundary
let nearest_in_chunk = Vec2::from(focus_pos).clamped(chunk_pos, chunk_pos + chunk_sz);
let in_range = Vec2::<f32>::from(focus_pos).distance_squared(nearest_in_chunk)
< loaded_distance.powf(2.0);
let distance_2 = Vec2::<f32>::from(focus_pos).distance_squared(nearest_in_chunk);
let in_range = distance_2 < loaded_distance.powf(2.0);
if !in_range {
chunk.visible = in_range;
@ -2176,6 +2185,9 @@ impl<V: RectRasterableVol> Terrain<V> {
chunk.frustum_last_plane_index = last_plane_index;
chunk.visible = in_frustum;
// FIXME: Hack that only works when only the lantern casts point shadows
// (and hardcodes the shadow distance). Should ideally exist per-light, too.
chunk.can_shadow = distance_2 < (128.0 * 128.0);
}
}
@ -2207,11 +2219,12 @@ impl<V: RectRasterableVol> Terrain<V> {
.take(self.chunks.len());
// Shadows
// let mut shadow_vertex_count = 0;
for (_, chunk) in chunk_iter.clone() {
/* if chunk.visible */
{
if chunk.can_shadow {
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
renderer.render_shadow(
&chunk.opaque_model,
&chunk.shadow_model,
globals,
&chunk.locals,
shadow_mats,
@ -2227,10 +2240,13 @@ impl<V: RectRasterableVol> Terrain<V> {
renderer.flush_shadows();
// Terrain
// let mut terrain_vertex_count = 0;
for (_, chunk) in chunk_iter {
// terrain_vertex_count += chunk.opaque_model.vertex_range.len();
if chunk.visible {
renderer.render_terrain_chunk(
&chunk.opaque_model,
// &chunk.shadow_model,
globals,
&chunk.locals,
lights,
@ -2240,6 +2256,7 @@ impl<V: RectRasterableVol> Terrain<V> {
);
}
}
// println!("Vertex count (shadow / terrain / ratio): {:?} / {:?} / {:?}", shadow_vertex_count, terrain_vertex_count, shadow_vertex_count as f64 / terrain_vertex_count as f64);
}
pub fn render_translucent(