Switch to f16 frame buffers in preparation for volumetric fog.

Also display some performance data using OpenGL's queries.
This commit is contained in:
IntegratedQuantum 2023-08-21 09:41:41 +02:00
parent 0d69e9965c
commit 840d62177c
14 changed files with 183 additions and 145 deletions

View File

@ -6,5 +6,4 @@ layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vec4(0, 0, 0, 1);
fragColor.rgb /= 4;
}

View File

@ -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);
}

View File

@ -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.
}

View File

@ -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.
}

View File

@ -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;
}

View File

@ -45,5 +45,4 @@ void main() {
if (fog.activ) {
fragColor = calcFog(mvVertexPos, fragColor, fog);
}
fragColor.rgb /= 4;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
};

View File

@ -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");

View File

@ -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)});
};
}

View File

@ -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);

View File

@ -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);

View File

@ -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;