diff --git a/assets/cubyz/shaders/block_selection_fragment.fs b/assets/cubyz/shaders/block_selection_fragment.fs index 508e298f1..f212820d2 100644 --- a/assets/cubyz/shaders/block_selection_fragment.fs +++ b/assets/cubyz/shaders/block_selection_fragment.fs @@ -6,5 +6,4 @@ layout(location = 0) out vec4 fragColor; void main() { fragColor = vec4(0, 0, 0, 1); - fragColor.rgb /= 4; } diff --git a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs index 9cd404163..5703f2db4 100644 --- a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs +++ b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs @@ -17,6 +17,6 @@ vec3 linearSample(ivec2 start) { void main() { vec3 bufferData = linearSample(ivec2(texCoords)); - float bloomFactor = max(max(bufferData.x, max(bufferData.y, bufferData.z))*4 - 1.0, 0); + float bloomFactor = max(max(bufferData.x, max(bufferData.y, bufferData.z)) - 1.0, 0); fragColor = vec4(bufferData*bloomFactor, 1); } \ No newline at end of file diff --git a/assets/cubyz/shaders/chunks/chunk_fragment.fs b/assets/cubyz/shaders/chunks/chunk_fragment.fs index 00dbc51da..23bc6c6d0 100644 --- a/assets/cubyz/shaders/chunks/chunk_fragment.fs +++ b/assets/cubyz/shaders/chunks/chunk_fragment.fs @@ -73,7 +73,6 @@ const vec3[6] normals = vec3[6]( uniform Fog fog; uniform Fog waterFog; // TODO: Select fog from texture -uniform bool renderedToItemTexture; vec4 calcFog(vec3 pos, vec4 color, Fog fog) { float distance = length(pos); @@ -217,8 +216,5 @@ void main() { if (fog.activ) { fragColor = calcFog(mvVertexPos, fragColor, fog); } - if(!renderedToItemTexture) { - fragColor.rgb /= 4; - } // TODO: Update the depth. } diff --git a/assets/cubyz/shaders/chunks/transparent_fragment.fs b/assets/cubyz/shaders/chunks/transparent_fragment.fs index 45c15ac55..83e9af259 100644 --- a/assets/cubyz/shaders/chunks/transparent_fragment.fs +++ b/assets/cubyz/shaders/chunks/transparent_fragment.fs @@ -62,7 +62,6 @@ const vec3[6] normals = vec3[6]( uniform Fog fog; uniform Fog waterFog; // TODO: Select fog from texture -uniform bool renderedToItemTexture; vec4 calcFog(vec3 pos, vec4 color, Fog fog) { float distance = length(pos); @@ -196,8 +195,5 @@ void main() { blendColor.rgb *= fragColor.a; fragColor.a = 1; } - if(!renderedToItemTexture) { - fragColor.rgb /= 4; - } // TODO: Update the depth. } diff --git a/assets/cubyz/shaders/deferred_render_pass.fs b/assets/cubyz/shaders/deferred_render_pass.fs index 3e1856603..8659a4cb7 100644 --- a/assets/cubyz/shaders/deferred_render_pass.fs +++ b/assets/cubyz/shaders/deferred_render_pass.fs @@ -7,6 +7,6 @@ uniform sampler2D color; void main() { fragColor = texture(color, texCoords); - float maxColor = max(0.25, max(fragColor.r, max(fragColor.g, fragColor.b))); + float maxColor = max(1.0, max(fragColor.r, max(fragColor.g, fragColor.b))); fragColor.rgb = fragColor.rgb/maxColor; } \ No newline at end of file diff --git a/assets/cubyz/shaders/entity_fragment.fs b/assets/cubyz/shaders/entity_fragment.fs index 027972987..8b0a2b026 100644 --- a/assets/cubyz/shaders/entity_fragment.fs +++ b/assets/cubyz/shaders/entity_fragment.fs @@ -45,5 +45,4 @@ void main() { if (fog.activ) { fragColor = calcFog(mvVertexPos, fragColor, fog); } - fragColor.rgb /= 4; } diff --git a/assets/cubyz/shaders/fog_fragment.fs b/assets/cubyz/shaders/fog_fragment.fs index 7f540a20a..326c73c70 100644 --- a/assets/cubyz/shaders/fog_fragment.fs +++ b/assets/cubyz/shaders/fog_fragment.fs @@ -24,5 +24,4 @@ vec4 calcFog(vec3 pos, vec4 color, Fog fog) { void main() { // TODO: Reconstruct position from the depth value. fragColor = calcFog(texture(position, texCoords).xyz, texture(color, texCoords)*vec4(4, 4, 4, 1), fog); - fragColor.rgb /= 4; } \ No newline at end of file diff --git a/src/chunk.zig b/src/chunk.zig index b37cc16c6..312c28598 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -404,7 +404,6 @@ pub const meshing = struct { time: c_int, visibilityMask: c_int, voxelSize: c_int, - renderedToItemTexture: c_int, }; pub var uniforms: UniformStruct = undefined; pub var transparentUniforms: UniformStruct = undefined; @@ -463,8 +462,6 @@ pub const meshing = struct { c.glUniform1i(uniforms.time, @as(u31, @truncate(time))); - c.glUniform1i(uniforms.renderedToItemTexture, 0); - c.glBindVertexArray(vao); } @@ -486,8 +483,6 @@ pub const meshing = struct { c.glUniform1i(transparentUniforms.time, @as(u31, @truncate(time))); - c.glUniform1i(transparentUniforms.renderedToItemTexture, 0); - c.glBindVertexArray(vao); } diff --git a/src/graphics.zig b/src/graphics.zig index 3dc6c9038..a37cf1faf 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -7,6 +7,7 @@ const freetype = @import("freetype"); const harfbuzz = @import("harfbuzz"); const Vec4i = @import("vec.zig").Vec4i; +const Vec4f = @import("vec.zig").Vec4f; const Vec2f = @import("vec.zig").Vec2f; const Vec2i = @import("vec.zig").Vec2i; const Vec3f = @import("vec.zig").Vec3f; @@ -1264,55 +1265,55 @@ pub const FrameBuffer = struct { frameBuffer: c_uint, texture: c_uint, hasDepthBuffer: bool, - renderBuffer: c_uint, + depthBuffer: c_uint, - pub fn init(self: *FrameBuffer, hasDepthBuffer: bool) void { + pub fn init(self: *FrameBuffer, hasDepthBuffer: bool, textureFilter: c_int, textureWrap: c_int) void { self.* = FrameBuffer{ .frameBuffer = undefined, .texture = undefined, - .renderBuffer = undefined, + .depthBuffer = undefined, .hasDepthBuffer = hasDepthBuffer, }; c.glGenFramebuffers(1, &self.frameBuffer); + c.glBindFramebuffer(c.GL_FRAMEBUFFER, self.frameBuffer); if(hasDepthBuffer) { - c.glGenRenderbuffers(1, &self.renderBuffer); + c.glGenRenderbuffers(1, &self.depthBuffer); + c.glBindRenderbuffer(c.GL_RENDERBUFFER, self.depthBuffer); + c.glFramebufferRenderbuffer(c.GL_FRAMEBUFFER, c.GL_DEPTH_ATTACHMENT, c.GL_RENDERBUFFER, self.depthBuffer); } c.glGenTextures(1, &self.texture); - } - - pub fn deinit(self: *FrameBuffer) void { - c.glDeleteFramebuffers(1, &self.frameBuffer); - if(self.hasDepthBuffer) { - c.glDeleteRenderbuffers(1, &self.renderBuffer); - } - c.glDeleteTextures(1, &self.texture); - } - - pub fn updateSize(self: *FrameBuffer, width: u31, height: u31, textureFilter: c_int, textureWrap: c_int) void { - c.glBindFramebuffer(c.GL_FRAMEBUFFER, self.frameBuffer); - if(self.hasDepthBuffer) { - c.glBindRenderbuffer(c.GL_RENDERBUFFER, self.renderBuffer); - c.glRenderbufferStorage(c.GL_RENDERBUFFER, c.GL_DEPTH24_STENCIL8, width, height); - c.glFramebufferRenderbuffer(c.GL_FRAMEBUFFER, c.GL_DEPTH_STENCIL_ATTACHMENT, c.GL_RENDERBUFFER, self.renderBuffer); - } - c.glBindTexture(c.GL_TEXTURE_2D, self.texture); - c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_RGBA8, width, height, 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, null); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, textureFilter); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, textureFilter); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_WRAP_S, textureWrap); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_WRAP_T, textureWrap); c.glFramebufferTexture2D(c.GL_FRAMEBUFFER, c.GL_COLOR_ATTACHMENT0, c.GL_TEXTURE_2D, self.texture, 0); + + c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); } - pub fn clear(_: FrameBuffer, clearColor: Color) void { - c.glClearColor( - @as(f32, @floatFromInt(clearColor.r))/255, - @as(f32, @floatFromInt(clearColor.g))/255, - @as(f32, @floatFromInt(clearColor.b))/255, - @as(f32, @floatFromInt(clearColor.a))/255, - ); - c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT); + pub fn deinit(self: *FrameBuffer) void { + c.glDeleteFramebuffers(1, &self.frameBuffer); + if(self.hasDepthBuffer) { + c.glDeleteRenderbuffers(1, &self.depthBuffer); + } + c.glDeleteTextures(1, &self.texture); + } + + pub fn updateSize(self: *FrameBuffer, width: u31, height: u31, internalFormat: c_int) void { + c.glBindFramebuffer(c.GL_FRAMEBUFFER, self.frameBuffer); + if(self.hasDepthBuffer) { + c.glBindRenderbuffer(c.GL_RENDERBUFFER, self.depthBuffer); + c.glRenderbufferStorage(c.GL_RENDERBUFFER, c.GL_DEPTH_COMPONENT32F, width, height); + } + + c.glBindTexture(c.GL_TEXTURE_2D, self.texture); + c.glTexImage2D(c.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, null); + } + + pub fn clear(_: FrameBuffer, clearColor: Vec4f) void { + c.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT); } pub fn validate(self: *FrameBuffer) bool { @@ -1325,11 +1326,16 @@ pub const FrameBuffer = struct { return true; } + pub fn bindTexture(self: *FrameBuffer, target: c_uint) void { + c.glActiveTexture(target); + c.glBindTexture(c.GL_TEXTURE_2D, self.texture); + } + pub fn bind(self: *FrameBuffer) void { c.glBindFramebuffer(c.GL_FRAMEBUFFER, self.frameBuffer); } - pub fn unbind() void { + pub fn unbind(_: *FrameBuffer) void { c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); } }; diff --git a/src/gui/windows/_windowlist.zig b/src/gui/windows/_windowlist.zig index b783b9591..6e25fd5f9 100644 --- a/src/gui/windows/_windowlist.zig +++ b/src/gui/windows/_windowlist.zig @@ -5,6 +5,7 @@ pub const controls = @import("controls.zig"); pub const creative_inventory = @import("creative_inventory.zig"); pub const crosshair = @import("crosshair.zig"); pub const debug = @import("debug.zig"); +pub const gpu_performance_measuring = @import("gpu_performance_measuring.zig"); pub const graphics = @import("graphics.zig"); pub const healthbar = @import("healthbar.zig"); pub const hotbar = @import("hotbar.zig"); diff --git a/src/gui/windows/gpu_performance_measuring.zig b/src/gui/windows/gpu_performance_measuring.zig new file mode 100644 index 000000000..3d1de9dc1 --- /dev/null +++ b/src/gui/windows/gpu_performance_measuring.zig @@ -0,0 +1,90 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; + +const main = @import("root"); +const c = main.c; +const graphics = main.graphics; +const draw = graphics.draw; +const Texture = graphics.Texture; +const Vec2f = main.vec.Vec2f; + +const gui = @import("../gui.zig"); +const GuiWindow = gui.GuiWindow; +const GuiComponent = gui.GuiComponent; + +pub const Samples = enum(u8) { + screenbuffer_clear, + clear, + chunk_rendering, + entity_rendering, + transparent_rendering, + bloom, + final_copy, +}; + +const names = [_][]const u8 { + "Screenbuffer clear", + "Clear", + "Chunk Rendering", + "Entity Rendering", + "Transparent Rendering", + "Bloom", + "Copy to screen", +}; + +var queryObjects: [@typeInfo(Samples).Enum.fields.len]c_uint = undefined; + +var activeSample: ?Samples = null; + +pub fn init() !void { + c.glGenQueries(queryObjects.len, &queryObjects); + for(0..queryObjects.len) |i| { // Start them to get an initial value. + c.glBeginQuery(c.GL_TIME_ELAPSED, queryObjects[i]); + c.glEndQuery(c.GL_TIME_ELAPSED); + } +} + +pub fn deinit() void { + c.glDeleteQueries(queryObjects.len, &queryObjects); +} + +pub fn startQuery(sample: Samples) void { + std.debug.assert(activeSample == null); // There can be at most one active measurement at a time. + activeSample = sample; + c.glBeginQuery(c.GL_TIME_ELAPSED, queryObjects[@intFromEnum(sample)]); +} + +pub fn stopQuery() void { + std.debug.assert(activeSample != null); // There must be an active measurement to stop. + activeSample = null; + c.glEndQuery(c.GL_TIME_ELAPSED); +} + +pub var window = GuiWindow { + .contentSize = Vec2f{128, 16}, + .id = "gpu_performance_measuring", + .isHud = false, + .showTitleBar = false, + .hasBackground = false, + .hideIfMouseIsGrabbed = false, +}; + +fn flawedRender() !void { + draw.setColor(0xffffffff); + var sum: isize = 0; + var y: f32 = 8; + inline for(0..queryObjects.len) |i| { + var result: i64 = undefined; + c.glGetQueryObjecti64v(queryObjects[i], c.GL_QUERY_RESULT, &result); + try draw.print("{s}: {} ns", .{names[i], result}, 0, y, 8, .left); + sum += result; + y += 8; + } + try draw.print("Total: {} ns", .{sum}, 0, 0, 8, .left); +} + +pub fn render() Allocator.Error!void { + flawedRender() catch |err| { + std.log.err("Encountered error while drawing debug window: {s}", .{@errorName(err)}); + }; +} \ No newline at end of file diff --git a/src/items.zig b/src/items.zig index a6b96fe21..44f543be3 100644 --- a/src/items.zig +++ b/src/items.zig @@ -130,10 +130,10 @@ pub const BaseItem = struct { c.glEnable(c.GL_CULL_FACE); defer if(cullFace == 0) c.glDisable(c.GL_CULL_FACE); - frameBuffer.init(false); - frameBuffer.updateSize(128, 128, c.GL_NEAREST, c.GL_REPEAT); + frameBuffer.init(false, c.GL_NEAREST, c.GL_REPEAT); + frameBuffer.updateSize(128, 128, c.GL_RGBA8); frameBuffer.bind(); - frameBuffer.clear(.{.r = 255, .g = 255, .b = 255, .a = 0}); + frameBuffer.clear(.{1, 1, 1, 0}); self.texture = graphics.Texture{.textureID = frameBuffer.texture}; defer c.glDeleteFramebuffers(1, &frameBuffer.frameBuffer); @@ -157,7 +157,6 @@ pub const BaseItem = struct { faceData[2] = chunk.meshing.ChunkMesh.constructFaceData(block, chunk.Neighbors.dirPosZ, 1, 1, 1+1); chunk.meshing.faceBuffer.bufferSubData(allocation.start, chunk.meshing.FaceData, &faceData); - c.glUniform1i(uniforms.renderedToItemTexture, 1); c.glUniform3f(uniforms.modelPosition, -65.5 - 1.5, -92.631 - 1.5, -65.5 - 1.5); c.glUniform1i(uniforms.visibilityMask, 0xff); c.glUniform1i(uniforms.voxelSize, 1); diff --git a/src/main.zig b/src/main.zig index c272dea86..dcaa2c28a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -334,6 +334,11 @@ fn togglePerformanceOverlay() void { std.log.err("Got error while opening the performance_graph overlay: {s}", .{@errorName(err)}); }; } +fn toggleGPUPerformanceOverlay() void { + gui.toggleWindow("gpu_performance_measuring") catch |err| { + std.log.err("Got error while opening the gpu performance overlay: {s}", .{@errorName(err)}); + }; +} pub const KeyBoard = struct { pub var keys = [_]Key { @@ -374,6 +379,7 @@ pub const KeyBoard = struct { // debug: Key{.name = "debugOverlay", .key = c.GLFW_KEY_F3, .releaseAction = &toggleDebugOverlay}, Key{.name = "performanceOverlay", .key = c.GLFW_KEY_F4, .releaseAction = &togglePerformanceOverlay}, + Key{.name = "gpuPerformanceOverlay", .key = c.GLFW_KEY_F5, .releaseAction = &toggleGPUPerformanceOverlay}, }; pub fn key(name: []const u8) *const Key { // TODO: Maybe I should use a hashmap here? @@ -721,8 +727,10 @@ pub fn main() !void { } c.glfwSwapBuffers(Window.window); Window.handleEvents(); + gui.windowlist.gpu_performance_measuring.startQuery(.screenbuffer_clear); c.glClearColor(0.5, 1, 1, 1); - c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); + c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); // TODO: It appears that this is only needed, in the menu, if we don't have a background scene. + gui.windowlist.gpu_performance_measuring.stopQuery(); var newTime = std.time.nanoTimestamp(); var deltaTime = @as(f64, @floatFromInt(newTime -% lastTime))/1e9; lastFrameTime.store(deltaTime, .Monotonic); diff --git a/src/renderer.zig b/src/renderer.zig index 9ce766c4f..38eb825d8 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -18,6 +18,7 @@ const network = @import("network.zig"); const settings = @import("settings.zig"); const utils = @import("utils.zig"); const vec = @import("vec.zig"); +const gpu_performance_measuring = main.gui.windowlist.gpu_performance_measuring; const Vec2f = vec.Vec2f; const Vec3i = vec.Vec3i; const Vec3f = vec.Vec3f; @@ -46,7 +47,8 @@ pub var activeFrameBuffer: c_uint = 0; pub fn init() !void { fogShader = try Shader.initAndGetUniforms("assets/cubyz/shaders/fog_vertex.vs", "assets/cubyz/shaders/fog_fragment.fs", &fogUniforms); deferredRenderPassShader = try Shader.initAndGetUniforms("assets/cubyz/shaders/deferred_render_pass.vs", "assets/cubyz/shaders/deferred_render_pass.fs", &deferredUniforms); - buffers.init(); + worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); + worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGBA16F); try Bloom.init(); try MeshSelection.init(); try MenuBackGround.init(); @@ -55,80 +57,13 @@ pub fn init() !void { pub fn deinit() void { fogShader.deinit(); deferredRenderPassShader.deinit(); - buffers.deinit(); + worldFrameBuffer.deinit(); Bloom.deinit(); MeshSelection.deinit(); MenuBackGround.deinit(); } -const buffers = struct { - var buffer: c_uint = undefined; - var colorTexture: c_uint = undefined; - var depthBuffer: c_uint = undefined; - fn init() void { - c.glGenFramebuffers(1, &buffer); - c.glGenRenderbuffers(1, &depthBuffer); - c.glGenTextures(1, &colorTexture); - - updateBufferSize(Window.width, Window.height); - - c.glBindFramebuffer(c.GL_FRAMEBUFFER, buffer); - - c.glFramebufferTexture2D(c.GL_FRAMEBUFFER, c.GL_COLOR_ATTACHMENT0, c.GL_TEXTURE_2D, colorTexture, 0); - - c.glFramebufferRenderbuffer(c.GL_FRAMEBUFFER, c.GL_DEPTH_ATTACHMENT, c.GL_RENDERBUFFER, depthBuffer); - - c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); - } - - fn deinit() void { - c.glDeleteFramebuffers(1, &buffer); - c.glDeleteRenderbuffers(1, &depthBuffer); - c.glDeleteTextures(1, &colorTexture); - } - - fn regenTexture(texture: c_uint, internalFormat: c_int, format: c_uint, width: u31, height: u31) void { - c.glBindTexture(c.GL_TEXTURE_2D, texture); - c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_NEAREST); - c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_NEAREST); - c.glTexImage2D(c.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, c.GL_UNSIGNED_BYTE, null); - c.glBindTexture(c.GL_TEXTURE_2D, 0); - } - - fn updateBufferSize(width: u31, height: u31) void { - c.glBindFramebuffer(c.GL_FRAMEBUFFER, buffer); - - regenTexture(colorTexture, c.GL_RGB10_A2, c.GL_RGB, width, height); - - c.glBindRenderbuffer(c.GL_RENDERBUFFER, depthBuffer); - c.glRenderbufferStorage(c.GL_RENDERBUFFER, c.GL_DEPTH_COMPONENT32F, width, height); - c.glBindRenderbuffer(c.GL_RENDERBUFFER, 0); - - const attachments = [_]c_uint{c.GL_COLOR_ATTACHMENT0}; - c.glDrawBuffers(attachments.len, &attachments); - - c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); - } - - fn bindTextures() void { - c.glActiveTexture(c.GL_TEXTURE3); - c.glBindTexture(c.GL_TEXTURE_2D, colorTexture); - } - - fn bind() void { - c.glBindFramebuffer(c.GL_FRAMEBUFFER, buffer); - } - - fn unbind() void { - c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); - } - - fn clearAndBind(clearColor: Vec4f) void { - c.glBindFramebuffer(c.GL_FRAMEBUFFER, buffer); - c.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1); - c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); - } -}; +var worldFrameBuffer: graphics.FrameBuffer = undefined; var lastWidth: u31 = 0; var lastHeight: u31 = 0; @@ -139,7 +74,8 @@ pub fn updateViewport(width: u31, height: u31, fov: f32) void { lastFov = fov; c.glViewport(0, 0, width, height); game.projectionMatrix = Mat4f.perspective(std.math.degreesToRadians(f32, fov), @as(f32, @floatFromInt(width))/@as(f32, @floatFromInt(height)), zNear); - buffers.updateBufferSize(width, height); + worldFrameBuffer.updateSize(width, height, c.GL_RGBA16F); + worldFrameBuffer.unbind(); } pub fn render(playerPosition: Vec3d) !void { @@ -178,7 +114,6 @@ pub fn render(playerPosition: Vec3d) !void { // TODO: // Cubyz.fog.setActive(ClientSettings.FOG_COEFFICIENT != 0); // Cubyz.fog.setDensity(1 / (ClientSettings.EFFECTIVE_RENDER_DISTANCE*ClientSettings.FOG_COEFFICIENT)); - skyColor *= @splat(0.25); try renderWorld(world, ambient, skyColor, playerPosition); try RenderStructure.updateMeshes(startTime + maximumMeshTime); @@ -194,7 +129,10 @@ pub fn render(playerPosition: Vec3d) !void { pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPos: Vec3d) !void { _ = world; - buffers.clearAndBind(Vec4f{skyColor[0], skyColor[1], skyColor[2], 1}); + worldFrameBuffer.bind(); + gpu_performance_measuring.startQuery(.clear); + worldFrameBuffer.clear(Vec4f{skyColor[0], skyColor[1], skyColor[2], 1}); + gpu_performance_measuring.stopQuery(); game.camera.updateViewMatrix(); // Uses FrustumCulling on the chunks. @@ -230,6 +168,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo // visibleReduced.add((ReducedChunkMesh)mesh); // } // } + gpu_performance_measuring.startQuery(.chunk_rendering); MeshSelection.select(playerPos, game.camera.direction); MeshSelection.render(game.projectionMatrix, game.camera.viewMatrix, playerPos); @@ -242,24 +181,30 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo for(meshes) |mesh| { mesh.render(playerPos); } + gpu_performance_measuring.stopQuery(); // for(int i = 0; i < visibleReduced.size; i++) { // ReducedChunkMesh mesh = visibleReduced.array[i]; // mesh.render(playerPosition); // } + gpu_performance_measuring.startQuery(.entity_rendering); entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, .{1, 0.5, 0.25}, playerPos); try itemdrop.ItemDropRenderer.renderItemDrops(game.projectionMatrix, ambientLight, playerPos, time); + gpu_performance_measuring.stopQuery(); // Render transparent chunk meshes: + gpu_performance_measuring.startQuery(.transparent_rendering); chunk.meshing.bindTransparentShaderAndUniforms(game.projectionMatrix, ambientLight, time); c.glUniform1i(chunk.meshing.transparentUniforms.@"waterFog.activ", if(waterFog.active) 1 else 0); c.glUniform3fv(chunk.meshing.transparentUniforms.@"waterFog.color", 1, @ptrCast(&waterFog.color)); c.glUniform1f(chunk.meshing.transparentUniforms.@"waterFog.density", waterFog.density); c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_SRC1_COLOR); + c.glDepthFunc(c.GL_LEQUAL); + c.glDepthMask(c.GL_FALSE); { var i: usize = meshes.len; while(true) { @@ -268,10 +213,13 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo try meshes[i].renderTransparent(playerPos); } } + c.glDepthMask(c.GL_TRUE); + c.glDepthFunc(c.GL_LESS); c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA); + gpu_performance_measuring.stopQuery(); // NormalChunkMesh.bindTransparentShader(ambientLight, directionalLight.getDirection(), time); - buffers.bindTextures(); + worldFrameBuffer.bindTexture(c.GL_TEXTURE3); // NormalChunkMesh.transparentShader.setUniform(NormalChunkMesh.TransparentUniforms.loc_waterFog_activ, waterFog.isActive()); // NormalChunkMesh.transparentShader.setUniform(NormalChunkMesh.TransparentUniforms.loc_waterFog_color, waterFog.getColor()); @@ -313,11 +261,15 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // } // } + + gpu_performance_measuring.startQuery(.bloom); if(settings.bloom) { Bloom.render(lastWidth, lastHeight); } - buffers.unbind(); - buffers.bindTextures(); + gpu_performance_measuring.stopQuery(); + gpu_performance_measuring.startQuery(.final_copy); + worldFrameBuffer.unbind(); + worldFrameBuffer.bindTexture(c.GL_TEXTURE3); deferredRenderPassShader.bind(); c.glUniform1i(deferredUniforms.color, 3); @@ -331,6 +283,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); try entity.ClientEntityManager.renderNames(game.projectionMatrix, playerPos); + gpu_performance_measuring.stopQuery(); } /// Sorts the chunks based on their distance from the player to reduce overdraw. @@ -390,8 +343,8 @@ const Bloom = struct { var upscaleShader: graphics.Shader = undefined; pub fn init() !void { - buffer1.init(false); - buffer2.init(false); + buffer1.init(false, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); + buffer2.init(false, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); firstPassShader = try graphics.Shader.init("assets/cubyz/shaders/bloom/first_pass.vs", "assets/cubyz/shaders/bloom/first_pass.fs"); secondPassShader = try graphics.Shader.init("assets/cubyz/shaders/bloom/second_pass.vs", "assets/cubyz/shaders/bloom/second_pass.fs"); colorExtractAndDownsampleShader = try graphics.Shader.init("assets/cubyz/shaders/bloom/color_extractor_downsample.vs", "assets/cubyz/shaders/bloom/color_extractor_downsample.fs"); @@ -408,7 +361,7 @@ const Bloom = struct { fn extractImageDataAndDownsample() void { colorExtractAndDownsampleShader.bind(); - buffers.bindTextures(); + worldFrameBuffer.bindTexture(c.GL_TEXTURE3); buffer1.bind(); c.glBindVertexArray(graphics.draw.rectVAO); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); @@ -416,8 +369,7 @@ const Bloom = struct { fn firstPass() void { firstPassShader.bind(); - c.glActiveTexture(c.GL_TEXTURE3); - c.glBindTexture(c.GL_TEXTURE_2D, buffer1.texture); + buffer1.bindTexture(c.GL_TEXTURE3); buffer2.bind(); c.glBindVertexArray(graphics.draw.rectVAO); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); @@ -425,8 +377,7 @@ const Bloom = struct { fn secondPass() void { secondPassShader.bind(); - c.glActiveTexture(c.GL_TEXTURE3); - c.glBindTexture(c.GL_TEXTURE_2D, buffer2.texture); + buffer2.bindTexture(c.GL_TEXTURE3); buffer1.bind(); c.glBindVertexArray(graphics.draw.rectVAO); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); @@ -434,9 +385,8 @@ const Bloom = struct { fn upscale() void { upscaleShader.bind(); - c.glActiveTexture(c.GL_TEXTURE3); - c.glBindTexture(c.GL_TEXTURE_2D, buffer1.texture); - buffers.bind(); + buffer1.bindTexture(c.GL_TEXTURE3); + worldFrameBuffer.bind(); c.glBindVertexArray(graphics.draw.rectVAO); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); } @@ -445,9 +395,9 @@ const Bloom = struct { if(width != currentWidth or height != currentHeight) { width = currentWidth; height = currentHeight; - buffer1.updateSize(width/2, height/2, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); + buffer1.updateSize(width/2, height/2, c.GL_RGB16F); std.debug.assert(buffer1.validate()); - buffer2.updateSize(width/2, height/2, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); + buffer2.updateSize(width/2, height/2, c.GL_RGB16F); std.debug.assert(buffer2.validate()); } c.glDisable(c.GL_DEPTH_TEST); @@ -591,9 +541,9 @@ pub const MenuBackGround = struct { defer updateViewport(Window.width, Window.height, settings.fov); var buffer: graphics.FrameBuffer = undefined; - buffer.init(true); + buffer.init(true, c.GL_NEAREST, c.GL_REPEAT); defer buffer.deinit(); - buffer.updateSize(size, size, c.GL_NEAREST, c.GL_REPEAT); + buffer.updateSize(size, size, c.GL_RGBA8); activeFrameBuffer = buffer.frameBuffer; defer activeFrameBuffer = 0;