mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Add a depth prepass and fix occlusion culling boxes.
more progress for #133
This commit is contained in:
parent
62320b293f
commit
8616289b47
65
assets/cubyz/shaders/chunks/depth_prepass_fragment.fs
Normal file
65
assets/cubyz/shaders/chunks/depth_prepass_fragment.fs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#version 430
|
||||||
|
|
||||||
|
in vec3 mvVertexPos;
|
||||||
|
in vec3 direction;
|
||||||
|
in vec2 uv;
|
||||||
|
flat in vec3 normal;
|
||||||
|
flat in uint textureIndexOffset;
|
||||||
|
flat in int isBackFace;
|
||||||
|
flat in int ditherSeed;
|
||||||
|
flat in uint lightBufferIndex;
|
||||||
|
flat in uvec2 lightArea;
|
||||||
|
in vec2 lightPosition;
|
||||||
|
|
||||||
|
uniform sampler2DArray texture_sampler;
|
||||||
|
uniform sampler2DArray emissionSampler;
|
||||||
|
uniform sampler2DArray reflectivityAndAbsorptionSampler;
|
||||||
|
uniform samplerCube reflectionMap;
|
||||||
|
uniform float reflectionMapSize;
|
||||||
|
uniform float contrast;
|
||||||
|
uniform vec3 ambientLight;
|
||||||
|
|
||||||
|
layout(std430, binding = 1) buffer _animatedTexture
|
||||||
|
{
|
||||||
|
float animatedTexture[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 11) buffer _textureData
|
||||||
|
{
|
||||||
|
uint textureData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
float ditherThresholds[16] = float[16] (
|
||||||
|
1/17.0, 9/17.0, 3/17.0, 11/17.0,
|
||||||
|
13/17.0, 5/17.0, 15/17.0, 7/17.0,
|
||||||
|
4/17.0, 12/17.0, 2/17.0, 10/17.0,
|
||||||
|
16/17.0, 8/17.0, 14/17.0, 6/17.0
|
||||||
|
);
|
||||||
|
|
||||||
|
ivec2 random1to2(int v) {
|
||||||
|
ivec4 fac = ivec4(11248723, 105436839, 45399083, 5412951);
|
||||||
|
int seed = v.x*fac.x ^ fac.y;
|
||||||
|
return seed*fac.zw;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool passDitherTest(float alpha) {
|
||||||
|
ivec2 screenPos = ivec2(gl_FragCoord.xy);
|
||||||
|
screenPos += random1to2(ditherSeed);
|
||||||
|
screenPos &= 3;
|
||||||
|
return alpha > ditherThresholds[screenPos.x*4 + screenPos.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint readTextureIndex() {
|
||||||
|
uint x = clamp(uint(lightPosition.x), 0, lightArea.x - 2);
|
||||||
|
uint y = clamp(uint(lightPosition.y), 0, lightArea.y - 2);
|
||||||
|
uint index = textureIndexOffset + x*(lightArea.y - 1) + y;
|
||||||
|
return textureData[index >> 1] >> 16*(index & 1u) & 65535u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
uint textureIndex = readTextureIndex();
|
||||||
|
float animatedTextureIndex = animatedTexture[textureIndex];
|
||||||
|
vec3 textureCoords = vec3(uv, animatedTextureIndex);
|
||||||
|
float alpha = texture(texture_sampler, textureCoords).a;
|
||||||
|
if(!passDitherTest(alpha)) discard;
|
||||||
|
}
|
@ -16,9 +16,10 @@ pub const Samples = enum(u8) {
|
|||||||
clear,
|
clear,
|
||||||
animation,
|
animation,
|
||||||
chunk_rendering_preparation,
|
chunk_rendering_preparation,
|
||||||
chunk_rendering_previous_visible,
|
chunk_rendering_depth_prepass_previous_visible,
|
||||||
chunk_rendering_occlusion_test,
|
chunk_rendering_occlusion_test,
|
||||||
chunk_rendering_new_visible,
|
chunk_rendering_depth_prepass_new_visible,
|
||||||
|
chunk_rendering,
|
||||||
entity_rendering,
|
entity_rendering,
|
||||||
transparent_rendering_preparation,
|
transparent_rendering_preparation,
|
||||||
transparent_rendering_occlusion_test,
|
transparent_rendering_occlusion_test,
|
||||||
@ -35,9 +36,10 @@ const names = [_][]const u8 {
|
|||||||
"Clear",
|
"Clear",
|
||||||
"Pre-processing Block Animations",
|
"Pre-processing Block Animations",
|
||||||
"Chunk Rendering Preparation",
|
"Chunk Rendering Preparation",
|
||||||
"Chunk Rendering Previous Visible",
|
"Chunk Rendering (Depth Prepass) Previous Visible",
|
||||||
"Chunk Rendering Occlusion Test",
|
"Chunk Rendering Occlusion Test",
|
||||||
"Chunk Rendering New Visible",
|
"Chunk Rendering (Depth Prepass) New Visible",
|
||||||
|
"Chunk Rendering",
|
||||||
"Entity Rendering",
|
"Entity Rendering",
|
||||||
"Transparent Rendering Preparation",
|
"Transparent Rendering Preparation",
|
||||||
"Transparent Rendering Occlusion Test",
|
"Transparent Rendering Occlusion Test",
|
||||||
|
@ -24,6 +24,7 @@ const gpu_performance_measuring = main.gui.windowlist.gpu_performance_measuring;
|
|||||||
|
|
||||||
const mesh_storage = @import("mesh_storage.zig");
|
const mesh_storage = @import("mesh_storage.zig");
|
||||||
|
|
||||||
|
var depthPrepassShader: Shader = undefined;
|
||||||
var shader: Shader = undefined;
|
var shader: Shader = undefined;
|
||||||
var transparentShader: Shader = undefined;
|
var transparentShader: Shader = undefined;
|
||||||
const UniformStruct = struct {
|
const UniformStruct = struct {
|
||||||
@ -45,6 +46,7 @@ const UniformStruct = struct {
|
|||||||
zFar: c_int,
|
zFar: c_int,
|
||||||
transparent: c_int,
|
transparent: c_int,
|
||||||
};
|
};
|
||||||
|
pub var depthPrepassUniforms: UniformStruct = undefined;
|
||||||
pub var uniforms: UniformStruct = undefined;
|
pub var uniforms: UniformStruct = undefined;
|
||||||
pub var transparentUniforms: UniformStruct = undefined;
|
pub var transparentUniforms: UniformStruct = undefined;
|
||||||
pub var commandShader: Shader = undefined;
|
pub var commandShader: Shader = undefined;
|
||||||
@ -77,6 +79,7 @@ pub var transparentQuadsDrawn: usize = 0;
|
|||||||
|
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
lighting.init();
|
lighting.init();
|
||||||
|
depthPrepassShader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/depth_prepass_fragment.fs", &depthPrepassUniforms);
|
||||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/chunk_fragment.fs", &uniforms);
|
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/chunk_fragment.fs", &uniforms);
|
||||||
transparentShader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/transparent_fragment.fs", &transparentUniforms);
|
transparentShader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/transparent_fragment.fs", &transparentUniforms);
|
||||||
commandShader = Shader.initComputeAndGetUniforms("assets/cubyz/shaders/chunks/fillIndirectBuffer.glsl", &commandUniforms);
|
commandShader = Shader.initComputeAndGetUniforms("assets/cubyz/shaders/chunks/fillIndirectBuffer.glsl", &commandUniforms);
|
||||||
@ -106,6 +109,7 @@ pub fn init() void {
|
|||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit() void {
|
||||||
lighting.deinit();
|
lighting.deinit();
|
||||||
|
depthPrepassShader.deinit();
|
||||||
shader.deinit();
|
shader.deinit();
|
||||||
transparentShader.deinit();
|
transparentShader.deinit();
|
||||||
commandShader.deinit();
|
commandShader.deinit();
|
||||||
@ -160,6 +164,15 @@ fn bindCommonUniforms(locations: *UniformStruct, projMatrix: Mat4f, ambient: Vec
|
|||||||
c.glUniform3f(locations.playerPositionFraction, @floatCast(@mod(playerPos[0], 1)), @floatCast(@mod(playerPos[1], 1)), @floatCast(@mod(playerPos[2], 1)));
|
c.glUniform3f(locations.playerPositionFraction, @floatCast(@mod(playerPos[0], 1)), @floatCast(@mod(playerPos[1], 1)), @floatCast(@mod(playerPos[2], 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bindPrepassShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d) void {
|
||||||
|
depthPrepassShader.bind();
|
||||||
|
|
||||||
|
bindCommonUniforms(&depthPrepassUniforms, projMatrix, ambient, playerPos);
|
||||||
|
c.glUniform1i(depthPrepassUniforms.transparent, 0);
|
||||||
|
|
||||||
|
c.glBindVertexArray(vao);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bindShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d) void {
|
pub fn bindShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d) void {
|
||||||
shader.bind();
|
shader.bind();
|
||||||
|
|
||||||
@ -195,7 +208,7 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
c.glUniform1i(commandUniforms.isTransparent, @intFromBool(transparent));
|
c.glUniform1i(commandUniforms.isTransparent, @intFromBool(transparent));
|
||||||
c.glUniform3i(commandUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
c.glUniform3i(commandUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
||||||
if(!transparent) {
|
if(!transparent) {
|
||||||
gpu_performance_measuring.startQuery(.chunk_rendering_previous_visible);
|
gpu_performance_measuring.startQuery(.chunk_rendering_depth_prepass_previous_visible);
|
||||||
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 0);
|
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 0);
|
||||||
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
||||||
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT | c.GL_COMMAND_BARRIER_BIT);
|
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT | c.GL_COMMAND_BARRIER_BIT);
|
||||||
@ -203,7 +216,8 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
if(transparent) {
|
if(transparent) {
|
||||||
bindTransparentShaderAndUniforms(projMatrix, ambient, playerPos);
|
bindTransparentShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||||
} else {
|
} else {
|
||||||
bindShaderAndUniforms(projMatrix, ambient, playerPos);
|
bindPrepassShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||||
|
c.glColorMask(c.GL_FALSE, c.GL_FALSE, c.GL_FALSE, c.GL_FALSE);
|
||||||
}
|
}
|
||||||
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
||||||
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
||||||
@ -220,14 +234,18 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
c.glDepthMask(c.GL_FALSE);
|
c.glDepthMask(c.GL_FALSE);
|
||||||
c.glColorMask(c.GL_FALSE, c.GL_FALSE, c.GL_FALSE, c.GL_FALSE);
|
c.glColorMask(c.GL_FALSE, c.GL_FALSE, c.GL_FALSE, c.GL_FALSE);
|
||||||
c.glBindVertexArray(vao);
|
c.glBindVertexArray(vao);
|
||||||
|
var oldDepthFunc: c_uint = undefined;
|
||||||
|
c.glGetIntegerv(c.GL_DEPTH_FUNC, @ptrCast(&oldDepthFunc));
|
||||||
|
c.glDepthFunc(c.GL_LEQUAL);
|
||||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(6*6*chunkIDs.len), c.GL_UNSIGNED_INT, null, chunkIDAllocation.start*24);
|
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(6*6*chunkIDs.len), c.GL_UNSIGNED_INT, null, chunkIDAllocation.start*24);
|
||||||
|
c.glDepthFunc(oldDepthFunc);
|
||||||
c.glDepthMask(c.GL_TRUE);
|
c.glDepthMask(c.GL_TRUE);
|
||||||
c.glColorMask(c.GL_TRUE, c.GL_TRUE, c.GL_TRUE, c.GL_TRUE);
|
c.glColorMask(c.GL_TRUE, c.GL_TRUE, c.GL_TRUE, c.GL_TRUE);
|
||||||
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT);
|
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
gpu_performance_measuring.stopQuery();
|
gpu_performance_measuring.stopQuery();
|
||||||
|
|
||||||
// Draw again:
|
// Draw again:
|
||||||
gpu_performance_measuring.startQuery(if(transparent) .transparent_rendering else .chunk_rendering_new_visible);
|
gpu_performance_measuring.startQuery(if(transparent) .transparent_rendering else .chunk_rendering_depth_prepass_new_visible);
|
||||||
commandShader.bind();
|
commandShader.bind();
|
||||||
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 1);
|
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 1);
|
||||||
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
||||||
@ -237,11 +255,31 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
bindTransparentShaderAndUniforms(projMatrix, ambient, playerPos);
|
bindTransparentShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||||
c.glDepthMask(c.GL_FALSE);
|
c.glDepthMask(c.GL_FALSE);
|
||||||
} else {
|
} else {
|
||||||
bindShaderAndUniforms(projMatrix, ambient, playerPos);
|
bindPrepassShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||||
|
c.glColorMask(c.GL_FALSE, c.GL_FALSE, c.GL_FALSE, c.GL_FALSE);
|
||||||
}
|
}
|
||||||
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
||||||
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
||||||
gpu_performance_measuring.stopQuery();
|
gpu_performance_measuring.stopQuery();
|
||||||
|
|
||||||
|
if(!transparent) {
|
||||||
|
gpu_performance_measuring.startQuery(.chunk_rendering);
|
||||||
|
// Draw after the depth prepass
|
||||||
|
commandShader.bind();
|
||||||
|
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 0);
|
||||||
|
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
||||||
|
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT | c.GL_COMMAND_BARRIER_BIT);
|
||||||
|
|
||||||
|
bindShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||||
|
c.glDepthFunc(c.GL_EQUAL);
|
||||||
|
c.glDepthMask(c.GL_FALSE);
|
||||||
|
c.glColorMask(c.GL_TRUE, c.GL_TRUE, c.GL_TRUE, c.GL_TRUE);
|
||||||
|
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
||||||
|
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
||||||
|
c.glDepthFunc(c.GL_LESS);
|
||||||
|
c.glDepthMask(c.GL_TRUE);
|
||||||
|
gpu_performance_measuring.stopQuery();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FaceData = extern struct {
|
pub const FaceData = extern struct {
|
||||||
@ -430,9 +468,20 @@ const PrimitiveMesh = struct {
|
|||||||
@floatFromInt(face.position.y),
|
@floatFromInt(face.position.y),
|
||||||
@floatFromInt(face.position.z),
|
@floatFromInt(face.position.z),
|
||||||
};
|
};
|
||||||
for(main.models.quads.items[face.blockAndQuad.quadIndex].corners) |cornerPos| {
|
|
||||||
self.min = @min(self.min, basePos + cornerPos);
|
for(0..2) |x| {
|
||||||
self.max = @max(self.max, basePos + cornerPos);
|
for(0..2) |y| {
|
||||||
|
const quadIndex = face.blockAndQuad.quadIndex;
|
||||||
|
var vertexPos = models.quads.items[quadIndex].corners[0];
|
||||||
|
vertexPos += (models.quads.items[quadIndex].corners[2] - models.quads.items[quadIndex].corners[0])*@as(Vec3f, @splat(@floatFromInt(x*(face.position.xSizeMinusOne + 1))));
|
||||||
|
if(x != 0) {
|
||||||
|
vertexPos += (models.quads.items[quadIndex].corners[3] - models.quads.items[quadIndex].corners[2])*@as(Vec3f, @splat(@floatFromInt(y*(face.position.ySizeMinusOne + 1))));
|
||||||
|
} else {
|
||||||
|
vertexPos += (models.quads.items[quadIndex].corners[1] - models.quads.items[quadIndex].corners[0])*@as(Vec3f, @splat(@floatFromInt(y*(face.position.ySizeMinusOne + 1))));
|
||||||
|
}
|
||||||
|
self.min = @min(self.min, basePos + vertexPos);
|
||||||
|
self.max = @max(self.max, basePos + vertexPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parent.lightingData[0].lock.unlockRead();
|
parent.lightingData[0].lock.unlockRead();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user