mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00
Switch to f16 frame buffers in preparation for volumetric fog.
Also display some performance data using OpenGL's queries.
This commit is contained in:
parent
0d69e9965c
commit
840d62177c
@ -6,5 +6,4 @@ layout(location = 0) out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0, 0, 0, 1);
|
||||
fragColor.rgb /= 4;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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.
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -45,5 +45,4 @@ void main() {
|
||||
if (fog.activ) {
|
||||
fragColor = calcFog(mvVertexPos, fragColor, fog);
|
||||
}
|
||||
fragColor.rgb /= 4;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -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");
|
||||
|
90
src/gui/windows/gpu_performance_measuring.zig
Normal file
90
src/gui/windows/gpu_performance_measuring.zig
Normal 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)});
|
||||
};
|
||||
}
|
@ -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);
|
||||
|
10
src/main.zig
10
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);
|
||||
|
130
src/renderer.zig
130
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user