diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 5e1a47303..1468e20e5 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -12,8 +12,14 @@ const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265f, 0.833149f, -0.163704f); const float DIRECTIONAL_LIGHT_FACTOR = 0.3f; -// forward declaration for helper used below -static inline void expand_aabb(AABB& aabb, bool& init, const glm::vec3& p); +namespace { +static constexpr float kChunkCenterBias = 0.5f; +static constexpr float kAoNormalPush = 0.75f; +static constexpr float kFaceOffsetEps = 1e-3f; + +static inline void expandAabbPoint(AABB& aabb, bool& init, const glm::vec3& p) { + if (!init) { aabb.a = aabb.b = p; init = true; } else { aabb.addPoint(p); } +} static inline float applyDirectionalFactor(float d) { return (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR; @@ -24,10 +30,10 @@ static inline void expandAabb4( const glm::vec3& p0, const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3 ) { - expand_aabb(aabb, init, p0); - expand_aabb(aabb, init, p1); - expand_aabb(aabb, init, p2); - expand_aabb(aabb, init, p3); + expandAabbPoint(aabb, init, p0); + expandAabbPoint(aabb, init, p1); + expandAabbPoint(aabb, init, p2); + expandAabbPoint(aabb, init, p3); } static inline void fillTexfaces( @@ -37,6 +43,7 @@ static inline void fillTexfaces( ) { for (int f = 0; f < 6; ++f) out[f] = cache.getRegion(id, variantId, f, densePass); } +} BlocksRenderer::BlocksRenderer( size_t capacity, @@ -127,7 +134,7 @@ void BlocksRenderer::face( auto X = axisX * w; auto Y = axisY * h; auto Z = axisZ * d; - float s = 0.5f; + float s = kChunkCenterBias; auto p0 = coord + (-X - Y + Z) * s; auto p1 = coord + ( X - Y + Z) * s; auto p2 = coord + ( X + Y + Z) * s; @@ -177,16 +184,17 @@ void BlocksRenderer::faceAO( return; } - float s = 0.5f; + float s = kChunkCenterBias; if (lights) { - float d = applyDirectionalFactor(glm::dot(glm::normalize(Z), SUN_VECTOR)); + const auto nZ = glm::normalize(Z); + float d = applyDirectionalFactor(glm::dot(nZ, SUN_VECTOR)); auto axisX = glm::normalize(X); auto axisY = glm::normalize(Y); - auto axisZ = glm::normalize(Z); + auto axisZ = nZ; glm::vec4 tint(d); - const float nh = 0.75f; // push AO sample a bit farther along normal + const float nh = kAoNormalPush; // push AO sample a bit farther along normal auto p0 = coord + (-X - Y + Z) * s; auto p1 = coord + ( X - Y + Z) * s; auto p2 = coord + ( X + Y + Z) * s; @@ -230,15 +238,17 @@ void BlocksRenderer::face( return; } - float s = 0.5f; + float s = kChunkCenterBias; + const auto nZ = glm::normalize(Z); if (lights) { - float d = applyDirectionalFactor(glm::dot(glm::normalize(Z), SUN_VECTOR)); + float d = applyDirectionalFactor(glm::dot(nZ, SUN_VECTOR)); tint *= d; } - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z, lights ? 0 : 1); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z, lights ? 0 : 1); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z, lights ? 0 : 1); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z, lights ? 0 : 1); + const auto nZ2 = lights ? nZ : Z; + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, nZ2, lights ? 0 : 1); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, nZ2, lights ? 0 : 1); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, nZ2, lights ? 0 : 1); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, nZ2, lights ? 0 : 1); index(0, 1, 2, 0, 2, 3); } diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index eca366748..f5c95a29c 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -21,6 +21,12 @@ size_t ChunksRenderer::visibleChunks = 0; namespace { struct CullingBounds { glm::vec3 min; glm::vec3 max; }; +static constexpr float kChunkCenterBias = 0.5f; + +static inline bool hasVolume(const AABB& aabb) { + auto s = aabb.size(); + return s.x > 0.0f || s.y > 0.0f || s.z > 0.0f; +} static inline CullingBounds computeChunkCullingBounds( const Chunk& chunk, @@ -35,14 +41,13 @@ static inline CullingBounds computeChunkCullingBounds( auto it = meshes.find({chunk.x, chunk.z}); if (it != meshes.end()) { const auto& aabb = it->second.localAabb; - auto size = aabb.size(); - if (size.x > 0.0f || size.y > 0.0f || size.z > 0.0f) { - min = glm::vec3(chunk.x * CHUNK_W + aabb.min().x + 0.5f, - (std::max)(static_cast(chunk.bottom), aabb.min().y + 0.5f), - chunk.z * CHUNK_D + aabb.min().z + 0.5f); - max = glm::vec3(chunk.x * CHUNK_W + aabb.max().x + 0.5f, - (std::min)(static_cast(chunk.top), aabb.max().y + 0.5f), - chunk.z * CHUNK_D + aabb.max().z + 0.5f); + if (hasVolume(aabb)) { + min = glm::vec3(chunk.x * CHUNK_W + aabb.min().x + kChunkCenterBias, + (std::max)(static_cast(chunk.bottom), aabb.min().y + kChunkCenterBias), + chunk.z * CHUNK_D + aabb.min().z + kChunkCenterBias); + max = glm::vec3(chunk.x * CHUNK_W + aabb.max().x + kChunkCenterBias, + (std::min)(static_cast(chunk.top), aabb.max().y + kChunkCenterBias), + chunk.z * CHUNK_D + aabb.max().z + kChunkCenterBias); } } return {min, max}; @@ -239,7 +244,7 @@ void ChunksRenderer::drawShadowsPass( } glm::vec3 coord( - pos.x * CHUNK_W + 0.5f, 0.5f, pos.y * CHUNK_D + 0.5f + pos.x * CHUNK_W + kChunkCenterBias, kChunkCenterBias, pos.y * CHUNK_D + kChunkCenterBias ); const auto bounds = computeChunkCullingBounds(*chunk, meshes); @@ -297,7 +302,7 @@ void ChunksRenderer::drawChunks( if (mesh) { glm::vec3 coord( - chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f + chunk->x * CHUNK_W + kChunkCenterBias, kChunkCenterBias, chunk->z * CHUNK_D + kChunkCenterBias ); glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); shader.uniformMatrix("u_model", model); @@ -361,18 +366,8 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) { } if (culling) { - glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); - glm::vec3 max(chunk->x * CHUNK_W + CHUNK_W, chunk->top, chunk->z * CHUNK_D + CHUNK_D); - const auto& aabb = found->second.localAabb; - if (aabb.size().x > 0.0f || aabb.size().y > 0.0f || aabb.size().z > 0.0f) { - min = glm::vec3(chunk->x * CHUNK_W + aabb.min().x + 0.5f, - (std::max)(static_cast(chunk->bottom), aabb.min().y + 0.5f), - chunk->z * CHUNK_D + aabb.min().z + 0.5f); - max = glm::vec3(chunk->x * CHUNK_W + aabb.max().x + 0.5f, - (std::min)(static_cast(chunk->top), aabb.max().y + 0.5f), - chunk->z * CHUNK_D + aabb.max().z + 0.5f); - } - if (!frustum.isBoxVisible(min, max)) continue; + const auto bounds = computeChunkCullingBounds(*chunk, meshes); + if (!frustum.isBoxVisible(bounds.min, bounds.max)) continue; } long long nearest = LLONG_MAX;