mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Add an abstraction for the Graphics pipeline (#1405)
* Add the vulkan headers from the new Cubyz-libs version * Add a GraphicsPipeline abstraction that's based on Vulkan's pipeline parameters. This will help get rid of all the glEnable implicit state, and it will make #102 easier. * I'm leaving out the viewport for now, it seems that it would make migration difficult * Small fixes and rename graphics.GraphicsPipeline to just graphics.Pipeline * Pipelinify the UI shaders * Fix formatting * Pipelines everywhere * Fix the crosshair and remove remaining glEnable and related calls * fix format * How many more things does it need to clear the thing correctly? * Fix selection * Fix bloom
This commit is contained in:
parent
2991febe3f
commit
c2b03ff437
@ -9,37 +9,37 @@
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_headers = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_headers.tar.gz",
|
||||
.hash = "N-V-__8AADG8MwD98GEQXXNawTiaQfCUrV7vK4ldKsWhfwvI",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_headers.tar.gz",
|
||||
.hash = "N-V-__8AALzzRgA7omQPNlE657Y60UmkCdNdXsMES8VvMC6D",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_macos = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-macos-none.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_aarch64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AANwbIwJ6ad1lQFbXKAwT6VwXJY4oLyjZwOfz4LUx",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_linux = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-linux-musl.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_aarch64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAG6FdQLSQL-LHeF5o7k3vRCnIdl0n2I0R0UO18K-",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_windows = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-windows-gnu.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_aarch64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AANCHkQIGwA8SWUxMHaxnVnkTwBO0yei3HwBLOd2T",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_macos = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-macos-none.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_x86_64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AAIh5HAKP8i_TwkyD-6H_EL31J6Ereu9Kdx83J7Ks",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_linux = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-linux-musl.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_x86_64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAAy-cwLTBDz5YQSt3h-PdE4Cm-NDI9RGnrAz_onE",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_windows = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-windows-gnu.tar.gz",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/5/cubyz_deps_x86_64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AAMzGtQKYP6AdoTC84UjbvypxwtagkWBMqrPc8Uhx",
|
||||
.lazy = true,
|
||||
},
|
||||
|
@ -94,13 +94,21 @@ pub const ClientEntityManager = struct {
|
||||
var modelBuffer: main.graphics.SSBO = undefined;
|
||||
var modelSize: c_int = 0;
|
||||
var modelTexture: main.graphics.Texture = undefined;
|
||||
var shader: graphics.Shader = undefined; // Entities are sometimes small and sometimes big. Therefor it would mean a lot of work to still use smooth lighting. Therefor the non-smooth shader is used for those.
|
||||
var pipeline: graphics.Pipeline = undefined; // Entities are sometimes small and sometimes big. Therefor it would mean a lot of work to still use smooth lighting. Therefor the non-smooth shader is used for those.
|
||||
pub var entities: main.utils.VirtualList(ClientEntity, 1 << 20) = undefined;
|
||||
pub var mutex: std.Thread.Mutex = .{};
|
||||
|
||||
pub fn init() void {
|
||||
entities = .init();
|
||||
shader = graphics.Shader.initAndGetUniforms("assets/cubyz/shaders/entity_vertex.vs", "assets/cubyz/shaders/entity_fragment.fs", "", &uniforms);
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/entity_vertex.vs",
|
||||
"assets/cubyz/shaders/entity_fragment.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{},
|
||||
.{.depthTest = true},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
|
||||
modelTexture = main.graphics.Texture.initFromFile("assets/cubyz/entity/textures/snail_player.png");
|
||||
const modelFile = main.files.read(main.stackAllocator, "assets/cubyz/entity/models/snail_player.obj") catch |err| blk: {
|
||||
@ -120,7 +128,7 @@ pub const ClientEntityManager = struct {
|
||||
ent.deinit(main.globalAllocator);
|
||||
}
|
||||
entities.deinit();
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
}
|
||||
|
||||
pub fn clear() void {
|
||||
@ -170,7 +178,7 @@ pub const ClientEntityManager = struct {
|
||||
mutex.lock();
|
||||
defer mutex.unlock();
|
||||
update();
|
||||
shader.bind();
|
||||
pipeline.bind(null);
|
||||
c.glBindVertexArray(main.renderer.chunk_meshing.vao);
|
||||
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&projMatrix));
|
||||
modelTexture.bindTo(0);
|
||||
|
554
src/graphics.zig
554
src/graphics.zig
@ -31,6 +31,7 @@ const NeverFailingAllocator = main.heap.NeverFailingAllocator;
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("glad/glad.h");
|
||||
@cInclude("vulkan/vulkan.h");
|
||||
});
|
||||
|
||||
pub const stb_image = @cImport({
|
||||
@ -102,23 +103,29 @@ pub const draw = struct { // MARK: draw
|
||||
}
|
||||
newClip[2] = @max(newClip[2], 0);
|
||||
newClip[3] = @max(newClip[3], 0);
|
||||
} else {
|
||||
c.glEnable(c.GL_SCISSOR_TEST);
|
||||
}
|
||||
c.glScissor(newClip[0], newClip[1], newClip[2], newClip[3]);
|
||||
const oldClip = clip;
|
||||
clip = newClip;
|
||||
return oldClip;
|
||||
}
|
||||
|
||||
pub fn getScissor() ?c.VkRect2D {
|
||||
const clipRect = clip orelse return null;
|
||||
return .{
|
||||
.offset = .{
|
||||
.x = clipRect[0],
|
||||
.y = clipRect[1],
|
||||
},
|
||||
.extent = .{
|
||||
.width = @intCast(clipRect[2]),
|
||||
.height = @intCast(clipRect[3]),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// Should be used to restore the old clip when leaving the render function.
|
||||
pub fn restoreClip(previousClip: ?Vec4i) void {
|
||||
clip = previousClip;
|
||||
if(clip) |clipRef| {
|
||||
c.glScissor(clipRef[0], clipRef[1], clipRef[2], clipRef[3]);
|
||||
} else {
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -129,12 +136,20 @@ pub const draw = struct { // MARK: draw
|
||||
size: c_int,
|
||||
rectColor: c_int,
|
||||
} = undefined;
|
||||
var rectShader: Shader = undefined;
|
||||
var rectPipeline: Pipeline = undefined;
|
||||
pub var rectVAO: c_uint = undefined;
|
||||
var rectVBO: c_uint = undefined;
|
||||
|
||||
fn initRect() void {
|
||||
rectShader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/Rect.vs", "assets/cubyz/shaders/graphics/Rect.fs", "", &rectUniforms);
|
||||
rectPipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Rect.vs",
|
||||
"assets/cubyz/shaders/graphics/Rect.fs",
|
||||
"",
|
||||
&rectUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
const rawData = [_]f32{
|
||||
0, 0,
|
||||
0, 1,
|
||||
@ -152,7 +167,7 @@ pub const draw = struct { // MARK: draw
|
||||
}
|
||||
|
||||
fn deinitRect() void {
|
||||
rectShader.deinit();
|
||||
rectPipeline.deinit();
|
||||
c.glDeleteVertexArrays(1, &rectVAO);
|
||||
c.glDeleteBuffers(1, &rectVBO);
|
||||
}
|
||||
@ -164,7 +179,7 @@ pub const draw = struct { // MARK: draw
|
||||
pos += translation;
|
||||
dim *= @splat(scale);
|
||||
|
||||
rectShader.bind();
|
||||
rectPipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(rectUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(rectUniforms.start, pos[0], pos[1]);
|
||||
@ -184,12 +199,20 @@ pub const draw = struct { // MARK: draw
|
||||
rectColor: c_int,
|
||||
lineWidth: c_int,
|
||||
} = undefined;
|
||||
var rectBorderShader: Shader = undefined;
|
||||
var rectBorderPipeline: Pipeline = undefined;
|
||||
var rectBorderVAO: c_uint = undefined;
|
||||
var rectBorderVBO: c_uint = undefined;
|
||||
|
||||
fn initRectBorder() void {
|
||||
rectBorderShader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/RectBorder.vs", "assets/cubyz/shaders/graphics/RectBorder.fs", "", &rectBorderUniforms);
|
||||
rectBorderPipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/RectBorder.vs",
|
||||
"assets/cubyz/shaders/graphics/RectBorder.fs",
|
||||
"",
|
||||
&rectBorderUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
const rawData = [_]f32{
|
||||
0, 0, 0, 0,
|
||||
0, 0, 1, 1,
|
||||
@ -213,7 +236,7 @@ pub const draw = struct { // MARK: draw
|
||||
}
|
||||
|
||||
fn deinitRectBorder() void {
|
||||
rectBorderShader.deinit();
|
||||
rectBorderPipeline.deinit();
|
||||
c.glDeleteVertexArrays(1, &rectBorderVAO);
|
||||
c.glDeleteBuffers(1, &rectBorderVBO);
|
||||
}
|
||||
@ -227,7 +250,7 @@ pub const draw = struct { // MARK: draw
|
||||
dim *= @splat(scale);
|
||||
width *= scale;
|
||||
|
||||
rectBorderShader.bind();
|
||||
rectBorderPipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(rectBorderUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(rectBorderUniforms.start, pos[0], pos[1]);
|
||||
@ -247,12 +270,20 @@ pub const draw = struct { // MARK: draw
|
||||
direction: c_int,
|
||||
lineColor: c_int,
|
||||
} = undefined;
|
||||
var lineShader: Shader = undefined;
|
||||
var linePipeline: Pipeline = undefined;
|
||||
var lineVAO: c_uint = undefined;
|
||||
var lineVBO: c_uint = undefined;
|
||||
|
||||
fn initLine() void {
|
||||
lineShader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/Line.vs", "assets/cubyz/shaders/graphics/Line.fs", "", &lineUniforms);
|
||||
linePipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Line.vs",
|
||||
"assets/cubyz/shaders/graphics/Line.fs",
|
||||
"",
|
||||
&lineUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
const rawData = [_]f32{
|
||||
0, 0,
|
||||
1, 1,
|
||||
@ -268,7 +299,7 @@ pub const draw = struct { // MARK: draw
|
||||
}
|
||||
|
||||
fn deinitLine() void {
|
||||
lineShader.deinit();
|
||||
linePipeline.deinit();
|
||||
c.glDeleteVertexArrays(1, &lineVAO);
|
||||
c.glDeleteBuffers(1, &lineVBO);
|
||||
}
|
||||
@ -281,7 +312,7 @@ pub const draw = struct { // MARK: draw
|
||||
pos2 *= @splat(scale);
|
||||
pos2 += translation;
|
||||
|
||||
lineShader.bind();
|
||||
linePipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(lineUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(lineUniforms.start, pos1[0], pos1[1]);
|
||||
@ -327,7 +358,7 @@ pub const draw = struct { // MARK: draw
|
||||
pos += translation;
|
||||
dim *= @splat(scale);
|
||||
|
||||
lineShader.bind();
|
||||
linePipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(lineUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(lineUniforms.start, pos[0], pos[1]); // Move the coordinates, so they are in the center of a pixel.
|
||||
@ -346,12 +377,20 @@ pub const draw = struct { // MARK: draw
|
||||
radius: c_int,
|
||||
circleColor: c_int,
|
||||
} = undefined;
|
||||
var circleShader: Shader = undefined;
|
||||
var circlePipeline: Pipeline = undefined;
|
||||
var circleVAO: c_uint = undefined;
|
||||
var circleVBO: c_uint = undefined;
|
||||
|
||||
fn initCircle() void {
|
||||
circleShader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/Circle.vs", "assets/cubyz/shaders/graphics/Circle.fs", "", &circleUniforms);
|
||||
circlePipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Circle.vs",
|
||||
"assets/cubyz/shaders/graphics/Circle.fs",
|
||||
"",
|
||||
&circleUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
const rawData = [_]f32{
|
||||
-1, -1,
|
||||
-1, 1,
|
||||
@ -369,7 +408,7 @@ pub const draw = struct { // MARK: draw
|
||||
}
|
||||
|
||||
fn deinitCircle() void {
|
||||
circleShader.deinit();
|
||||
circlePipeline.deinit();
|
||||
c.glDeleteVertexArrays(1, &circleVAO);
|
||||
c.glDeleteBuffers(1, &circleVBO);
|
||||
}
|
||||
@ -380,7 +419,7 @@ pub const draw = struct { // MARK: draw
|
||||
center *= @splat(scale);
|
||||
center += translation;
|
||||
radius *= scale;
|
||||
circleShader.bind();
|
||||
circlePipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(circleUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(circleUniforms.center, center[0], center[1]); // Move the coordinates, so they are in the center of a pixel.
|
||||
@ -402,36 +441,28 @@ pub const draw = struct { // MARK: draw
|
||||
uvOffset: c_int,
|
||||
uvDim: c_int,
|
||||
} = undefined;
|
||||
var imageShader: Shader = undefined;
|
||||
var imagePipeline: Pipeline = undefined;
|
||||
|
||||
fn initImage() void {
|
||||
imageShader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/Image.vs", "assets/cubyz/shaders/graphics/Image.fs", "", &imageUniforms);
|
||||
imagePipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Image.vs",
|
||||
"assets/cubyz/shaders/graphics/Image.fs",
|
||||
"",
|
||||
&imageUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
}
|
||||
|
||||
fn deinitImage() void {
|
||||
imageShader.deinit();
|
||||
imagePipeline.deinit();
|
||||
}
|
||||
|
||||
pub fn boundImage(_pos: Vec2f, _dim: Vec2f) void {
|
||||
var pos = _pos;
|
||||
var dim = _dim;
|
||||
pos *= @splat(scale);
|
||||
pos += translation;
|
||||
dim *= @splat(scale);
|
||||
pos = @floor(pos);
|
||||
dim = @ceil(dim);
|
||||
imagePipeline.bind(getScissor());
|
||||
|
||||
imageShader.bind();
|
||||
|
||||
c.glUniform2f(imageUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(imageUniforms.start, pos[0], pos[1]);
|
||||
c.glUniform2f(imageUniforms.size, dim[0], dim[1]);
|
||||
c.glUniform1i(imageUniforms.color, @bitCast(color));
|
||||
c.glUniform2f(imageUniforms.uvOffset, 0, 0);
|
||||
c.glUniform2f(imageUniforms.uvDim, 1, 1);
|
||||
|
||||
c.glBindVertexArray(rectVAO);
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
customShadedImage(&imageUniforms, _pos, _dim);
|
||||
}
|
||||
|
||||
pub fn boundSubImage(_pos: Vec2f, _dim: Vec2f, uvOffset: Vec2f, uvDim: Vec2f) void {
|
||||
@ -443,7 +474,7 @@ pub const draw = struct { // MARK: draw
|
||||
pos = @floor(pos);
|
||||
dim = @ceil(dim);
|
||||
|
||||
imageShader.bind();
|
||||
imagePipeline.bind(getScissor());
|
||||
|
||||
c.glUniform2f(imageUniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(imageUniforms.start, pos[0], pos[1]);
|
||||
@ -456,6 +487,26 @@ pub const draw = struct { // MARK: draw
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
pub fn customShadedImage(uniforms: anytype, _pos: Vec2f, _dim: Vec2f) void {
|
||||
var pos = _pos;
|
||||
var dim = _dim;
|
||||
pos *= @splat(scale);
|
||||
pos += translation;
|
||||
dim *= @splat(scale);
|
||||
pos = @floor(pos);
|
||||
dim = @ceil(dim);
|
||||
|
||||
c.glUniform2f(uniforms.screen, @floatFromInt(Window.width), @floatFromInt(Window.height));
|
||||
c.glUniform2f(uniforms.start, pos[0], pos[1]);
|
||||
c.glUniform2f(uniforms.size, dim[0], dim[1]);
|
||||
c.glUniform1i(uniforms.color, @bitCast(color));
|
||||
c.glUniform2f(uniforms.uvOffset, 0, 0);
|
||||
c.glUniform2f(uniforms.uvDim, 1, 1);
|
||||
|
||||
c.glBindVertexArray(rectVAO);
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MARK: customShadedRect()
|
||||
|
||||
@ -928,7 +979,7 @@ pub const TextBuffer = struct { // MARK: TextBuffer
|
||||
defer draw.restoreScale(oldScale);
|
||||
var x: f32 = 0;
|
||||
var y: f32 = 0;
|
||||
TextRendering.shader.bind();
|
||||
TextRendering.pipeline.bind(draw.getScissor());
|
||||
c.glUniform2f(TextRendering.uniforms.scene, @floatFromInt(main.Window.width), @floatFromInt(main.Window.height));
|
||||
c.glUniform1f(TextRendering.uniforms.ratio, draw.scale);
|
||||
c.glUniform1f(TextRendering.uniforms.alpha, @as(f32, @floatFromInt(draw.color >> 24))/255.0);
|
||||
@ -994,7 +1045,7 @@ pub const TextBuffer = struct { // MARK: TextBuffer
|
||||
defer draw.restoreScale(oldScale);
|
||||
var x: f32 = 0;
|
||||
var y: f32 = 0;
|
||||
TextRendering.shader.bind();
|
||||
TextRendering.pipeline.bind(draw.getScissor());
|
||||
c.glUniform2f(TextRendering.uniforms.scene, @floatFromInt(main.Window.width), @floatFromInt(main.Window.height));
|
||||
c.glUniform1f(TextRendering.uniforms.ratio, draw.scale);
|
||||
c.glUniform1f(TextRendering.uniforms.alpha, @as(f32, @floatFromInt(draw.color >> 24))/255.0);
|
||||
@ -1051,7 +1102,7 @@ const TextRendering = struct { // MARK: TextRendering
|
||||
bearing: Vec2i,
|
||||
advance: f32,
|
||||
};
|
||||
var shader: Shader = undefined;
|
||||
var pipeline: Pipeline = undefined;
|
||||
var uniforms: struct {
|
||||
texture_rect: c_int,
|
||||
scene: c_int,
|
||||
@ -1081,9 +1132,17 @@ const TextRendering = struct { // MARK: TextRendering
|
||||
}
|
||||
|
||||
fn init() !void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/Text.vs", "assets/cubyz/shaders/graphics/Text.fs", "", &uniforms);
|
||||
shader.bind();
|
||||
errdefer shader.deinit();
|
||||
pipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Text.vs",
|
||||
"assets/cubyz/shaders/graphics/Text.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
pipeline.bind(null);
|
||||
errdefer pipeline.deinit();
|
||||
c.glUniform1f(uniforms.alpha, 1.0);
|
||||
c.glUniform2f(uniforms.fontSize, @floatFromInt(textureWidth), @floatFromInt(textureHeight));
|
||||
try ftError(hbft.FT_Init_FreeType(&freetypeLib));
|
||||
@ -1110,7 +1169,7 @@ const TextRendering = struct { // MARK: TextRendering
|
||||
}
|
||||
|
||||
fn deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
ftError(hbft.FT_Done_FreeType(freetypeLib)) catch {};
|
||||
glyphMapping.deinit();
|
||||
glyphData.deinit();
|
||||
@ -1127,7 +1186,7 @@ const TextRendering = struct { // MARK: TextRendering
|
||||
c.glBindTexture(c.GL_TEXTURE_2D, glyphTexture[0]);
|
||||
c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_R8, newWidth, textureHeight, 0, c.GL_RED, c.GL_UNSIGNED_BYTE, null);
|
||||
c.glCopyImageSubData(glyphTexture[1], c.GL_TEXTURE_2D, 0, 0, 0, 0, glyphTexture[0], c.GL_TEXTURE_2D, 0, 0, 0, 0, textureOffset, textureHeight, 1);
|
||||
shader.bind();
|
||||
pipeline.bind(draw.getScissor());
|
||||
c.glUniform2f(uniforms.fontSize, @floatFromInt(textureWidth), @floatFromInt(textureHeight));
|
||||
}
|
||||
|
||||
@ -1334,22 +1393,20 @@ pub const Shader = struct { // MARK: Shader
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(vertex: []const u8, fragment: []const u8, defines: []const u8) Shader {
|
||||
fn init(vertex: []const u8, fragment: []const u8, defines: []const u8, uniformStruct: anytype) Shader {
|
||||
const shader = Shader{.id = c.glCreateProgram()};
|
||||
shader.addShader(vertex, defines, c.GL_VERTEX_SHADER) catch return shader;
|
||||
shader.addShader(fragment, defines, c.GL_FRAGMENT_SHADER) catch return shader;
|
||||
shader.link(fragment) catch return shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
pub fn initAndGetUniforms(vertex: []const u8, fragment: []const u8, defines: []const u8, ptrToUniformStruct: anytype) Shader {
|
||||
const self = Shader.init(vertex, fragment, defines);
|
||||
inline for(@typeInfo(@TypeOf(ptrToUniformStruct.*)).@"struct".fields) |field| {
|
||||
if(field.type == c_int) {
|
||||
@field(ptrToUniformStruct, field.name) = c.glGetUniformLocation(self.id, field.name[0..]);
|
||||
if(@TypeOf(uniformStruct) != @TypeOf(null)) {
|
||||
inline for(@typeInfo(@TypeOf(uniformStruct.*)).@"struct".fields) |field| {
|
||||
if(field.type == c_int) {
|
||||
@field(uniformStruct, field.name) = c.glGetUniformLocation(shader.id, field.name[0..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
return shader;
|
||||
}
|
||||
|
||||
pub fn initCompute(compute: []const u8, defines: []const u8) Shader {
|
||||
@ -1378,6 +1435,345 @@ pub const Shader = struct { // MARK: Shader
|
||||
}
|
||||
};
|
||||
|
||||
pub const Pipeline = struct { // MARK: Pipeline
|
||||
shader: Shader,
|
||||
rasterState: RasterizationState,
|
||||
multisampleState: MultisampleState = .{}, // TODO: Not implemented
|
||||
depthStencilState: DepthStencilState,
|
||||
blendState: ColorBlendState,
|
||||
|
||||
const RasterizationState = struct {
|
||||
depthClamp: bool = true,
|
||||
rasterizerDiscard: bool = false,
|
||||
polygonMode: PolygonMode = .fill,
|
||||
cullMode: CullModeFlags = .back,
|
||||
frontFace: FrontFace = .counterClockwise,
|
||||
depthBias: ?DepthBias = null,
|
||||
lineWidth: f32 = 1,
|
||||
|
||||
const PolygonMode = enum(c.VkPolygonMode) {
|
||||
fill = c.VK_POLYGON_MODE_FILL,
|
||||
line = c.VK_POLYGON_MODE_LINE,
|
||||
point = c.VK_POLYGON_MODE_POINT,
|
||||
fillRectangleNV = c.VK_POLYGON_MODE_FILL_RECTANGLE_NV,
|
||||
};
|
||||
|
||||
const CullModeFlags = enum(c.VkCullModeFlags) {
|
||||
none = c.VK_CULL_MODE_NONE,
|
||||
front = c.VK_CULL_MODE_FRONT_BIT,
|
||||
back = c.VK_CULL_MODE_BACK_BIT,
|
||||
frontAndBack = c.VK_CULL_MODE_FRONT_AND_BACK,
|
||||
};
|
||||
|
||||
const FrontFace = enum(c.VkFrontFace) {
|
||||
counterClockwise = c.VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||
clockwise = c.VK_FRONT_FACE_CLOCKWISE,
|
||||
};
|
||||
|
||||
const DepthBias = struct {
|
||||
constantFactor: f32,
|
||||
clamp: f32,
|
||||
slopeFactor: f32,
|
||||
};
|
||||
};
|
||||
|
||||
const MultisampleState = struct {
|
||||
rasterizationSamples: Count = .@"1",
|
||||
sampleShading: bool = false,
|
||||
minSampleShading: f32 = undefined,
|
||||
sampleMask: [*]const c.VkSampleMask = &.{0, 0},
|
||||
alphaToCoverage: bool = false,
|
||||
alphaToOne: bool = false,
|
||||
|
||||
const Count = enum(c.VkSampleCountFlags) {
|
||||
@"1" = c.VK_SAMPLE_COUNT_1_BIT,
|
||||
@"2" = c.VK_SAMPLE_COUNT_2_BIT,
|
||||
@"4" = c.VK_SAMPLE_COUNT_4_BIT,
|
||||
@"8" = c.VK_SAMPLE_COUNT_8_BIT,
|
||||
@"16" = c.VK_SAMPLE_COUNT_16_BIT,
|
||||
@"32" = c.VK_SAMPLE_COUNT_32_BIT,
|
||||
@"64" = c.VK_SAMPLE_COUNT_64_BIT,
|
||||
};
|
||||
};
|
||||
|
||||
const DepthStencilState = struct {
|
||||
depthTest: bool,
|
||||
depthWrite: bool = true,
|
||||
depthCompare: CompareOp = .less,
|
||||
depthBoundsTest: ?DepthBoundsTest = null,
|
||||
stencilTest: ?StencilTest = null,
|
||||
|
||||
const CompareOp = enum(c.VkCompareOp) {
|
||||
never = c.VK_COMPARE_OP_NEVER,
|
||||
less = c.VK_COMPARE_OP_LESS,
|
||||
equal = c.VK_COMPARE_OP_EQUAL,
|
||||
lessOrEqual = c.VK_COMPARE_OP_LESS_OR_EQUAL,
|
||||
greater = c.VK_COMPARE_OP_GREATER,
|
||||
notEqual = c.VK_COMPARE_OP_NOT_EQUAL,
|
||||
greateOrEqual = c.VK_COMPARE_OP_GREATER_OR_EQUAL,
|
||||
always = c.VK_COMPARE_OP_ALWAYS,
|
||||
};
|
||||
|
||||
const StencilTest = struct {
|
||||
front: StencilOpState,
|
||||
back: StencilOpState,
|
||||
|
||||
const StencilOpState = struct {
|
||||
failOp: StencilOp,
|
||||
passOp: StencilOp,
|
||||
depthFailOp: StencilOp,
|
||||
compareOp: CompareOp,
|
||||
compareMask: u32,
|
||||
writeMask: u32,
|
||||
reference: u32,
|
||||
|
||||
const StencilOp = enum(c.VkStencilOp) {
|
||||
keep = c.VK_STENCIL_OP_KEEP,
|
||||
zero = c.VK_STENCIL_OP_ZERO,
|
||||
replace = c.VK_STENCIL_OP_REPLACE,
|
||||
incrementAndClamp = c.VK_STENCIL_OP_INCREMENT_AND_CLAMP,
|
||||
decrementAndClamp = c.VK_STENCIL_OP_DECREMENT_AND_CLAMP,
|
||||
invert = c.VK_STENCIL_OP_INVERT,
|
||||
incrementAndWrap = c.VK_STENCIL_OP_INCREMENT_AND_WRAP,
|
||||
decrementAndWrap = c.VK_STENCIL_OP_DECREMENT_AND_WRAP,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const DepthBoundsTest = struct {
|
||||
min: f32,
|
||||
max: f32,
|
||||
};
|
||||
};
|
||||
|
||||
const ColorBlendAttachmentState = struct {
|
||||
enabled: bool = true,
|
||||
srcColorBlendFactor: BlendFactor,
|
||||
dstColorBlendFactor: BlendFactor,
|
||||
colorBlendOp: BlendOp,
|
||||
srcAlphaBlendFactor: BlendFactor,
|
||||
dstAlphaBlendFactor: BlendFactor,
|
||||
alphaBlendOp: BlendOp,
|
||||
colorWriteMask: ColorComponentFlags = .all,
|
||||
|
||||
pub const alphaBlending: ColorBlendAttachmentState = .{
|
||||
.srcColorBlendFactor = .srcAlpha,
|
||||
.dstColorBlendFactor = .oneMinusSrcAlpha,
|
||||
.colorBlendOp = .add,
|
||||
.srcAlphaBlendFactor = .srcAlpha,
|
||||
.dstAlphaBlendFactor = .oneMinusSrcAlpha,
|
||||
.alphaBlendOp = .add,
|
||||
};
|
||||
pub const noBlending: ColorBlendAttachmentState = .{
|
||||
.enabled = false,
|
||||
.srcColorBlendFactor = undefined,
|
||||
.dstColorBlendFactor = undefined,
|
||||
.colorBlendOp = undefined,
|
||||
.srcAlphaBlendFactor = undefined,
|
||||
.dstAlphaBlendFactor = undefined,
|
||||
.alphaBlendOp = undefined,
|
||||
};
|
||||
|
||||
const BlendFactor = enum(c.VkBlendFactor) {
|
||||
zero = c.VK_BLEND_FACTOR_ZERO,
|
||||
one = c.VK_BLEND_FACTOR_ONE,
|
||||
srcColor = c.VK_BLEND_FACTOR_SRC_COLOR,
|
||||
oneMinusSrcColor = c.VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
|
||||
dstColor = c.VK_BLEND_FACTOR_DST_COLOR,
|
||||
oneMinusDstColor = c.VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
|
||||
srcAlpha = c.VK_BLEND_FACTOR_SRC_ALPHA,
|
||||
oneMinusSrcAlpha = c.VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
dstAlpha = c.VK_BLEND_FACTOR_DST_ALPHA,
|
||||
oneMinusDstAlpha = c.VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
|
||||
constantColor = c.VK_BLEND_FACTOR_CONSTANT_COLOR,
|
||||
oneMinusConstantColor = c.VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
|
||||
constantAlpha = c.VK_BLEND_FACTOR_CONSTANT_ALPHA,
|
||||
oneMinusConstantAlpha = c.VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
|
||||
srcAlphaSaturate = c.VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
|
||||
src1Color = c.VK_BLEND_FACTOR_SRC1_COLOR,
|
||||
oneMinusSrc1Color = c.VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
|
||||
src1Alpha = c.VK_BLEND_FACTOR_SRC1_ALPHA,
|
||||
oneMinusSrc1Alpha = c.VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
|
||||
|
||||
fn toGl(self: BlendFactor) c.GLenum {
|
||||
return switch(self) {
|
||||
.zero => c.GL_ZERO,
|
||||
.one => c.GL_ONE,
|
||||
.srcColor => c.GL_SRC_COLOR,
|
||||
.oneMinusSrcColor => c.GL_ONE_MINUS_SRC_COLOR,
|
||||
.dstColor => c.GL_DST_COLOR,
|
||||
.oneMinusDstColor => c.GL_ONE_MINUS_DST_COLOR,
|
||||
.srcAlpha => c.GL_SRC_ALPHA,
|
||||
.oneMinusSrcAlpha => c.GL_ONE_MINUS_SRC_ALPHA,
|
||||
.dstAlpha => c.GL_DST_ALPHA,
|
||||
.oneMinusDstAlpha => c.GL_ONE_MINUS_DST_ALPHA,
|
||||
.constantColor => c.GL_CONSTANT_COLOR,
|
||||
.oneMinusConstantColor => c.GL_ONE_MINUS_CONSTANT_COLOR,
|
||||
.constantAlpha => c.GL_CONSTANT_ALPHA,
|
||||
.oneMinusConstantAlpha => c.GL_ONE_MINUS_CONSTANT_ALPHA,
|
||||
.srcAlphaSaturate => c.GL_SRC_ALPHA_SATURATE,
|
||||
.src1Color => c.GL_SRC1_COLOR,
|
||||
.oneMinusSrc1Color => c.GL_ONE_MINUS_SRC1_COLOR,
|
||||
.src1Alpha => c.GL_SRC1_ALPHA,
|
||||
.oneMinusSrc1Alpha => c.GL_ONE_MINUS_SRC1_ALPHA,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const BlendOp = enum(c.VkBlendOp) {
|
||||
add = c.VK_BLEND_OP_ADD,
|
||||
subtract = c.VK_BLEND_OP_SUBTRACT,
|
||||
reverseSubtract = c.VK_BLEND_OP_REVERSE_SUBTRACT,
|
||||
min = c.VK_BLEND_OP_MIN,
|
||||
max = c.VK_BLEND_OP_MAX,
|
||||
|
||||
fn toGl(self: BlendOp) c.GLenum {
|
||||
return switch(self) {
|
||||
.add => c.GL_FUNC_ADD,
|
||||
.subtract => c.GL_FUNC_SUBTRACT,
|
||||
.reverseSubtract => c.GL_FUNC_REVERSE_SUBTRACT,
|
||||
.min => c.GL_MIN,
|
||||
.max => c.GL_MAX,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const ColorComponentFlags = packed struct {
|
||||
r: bool,
|
||||
g: bool,
|
||||
b: bool,
|
||||
a: bool,
|
||||
pub const all: ColorComponentFlags = .{.r = true, .g = true, .b = true, .a = true};
|
||||
pub const none: ColorComponentFlags = .{.r = false, .g = false, .b = false, .a = false};
|
||||
};
|
||||
};
|
||||
|
||||
const ColorBlendState = struct {
|
||||
logicOp: ?LogicOp = null,
|
||||
attachments: []const ColorBlendAttachmentState,
|
||||
blendConstants: [4]f32 = .{0, 0, 0, 0},
|
||||
|
||||
const LogicOp = enum(c.VkLogicOp) {
|
||||
clear = c.VK_LOGIC_OP_CLEAR,
|
||||
@"and" = c.VK_LOGIC_OP_AND,
|
||||
andReverse = c.VK_LOGIC_OP_AND_REVERSE,
|
||||
copy = c.VK_LOGIC_OP_COPY,
|
||||
andInverted = c.VK_LOGIC_OP_AND_INVERTED,
|
||||
noOp = c.VK_LOGIC_OP_NO_OP,
|
||||
xor = c.VK_LOGIC_OP_XOR,
|
||||
@"or" = c.VK_LOGIC_OP_OR,
|
||||
nor = c.VK_LOGIC_OP_NOR,
|
||||
equivalent = c.VK_LOGIC_OP_EQUIVALENT,
|
||||
invert = c.VK_LOGIC_OP_INVERT,
|
||||
orReverse = c.VK_LOGIC_OP_OR_REVERSE,
|
||||
copyInverted = c.VK_LOGIC_OP_COPY_INVERTED,
|
||||
orInverted = c.VK_LOGIC_OP_OR_INVERTED,
|
||||
nand = c.VK_LOGIC_OP_NAND,
|
||||
set = c.VK_LOGIC_OP_SET,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn init(vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, uniformStruct: anytype, rasterState: RasterizationState, depthStencilState: DepthStencilState, blendState: ColorBlendState) Pipeline {
|
||||
std.debug.assert(depthStencilState.depthBoundsTest == null); // Only available in Vulkan 1.3
|
||||
std.debug.assert(depthStencilState.stencilTest == null); // TODO: Not yet implemented
|
||||
std.debug.assert(rasterState.lineWidth <= 1); // Larger values are poorly supported among drivers
|
||||
std.debug.assert(blendState.logicOp == null); // TODO: Not yet implemented
|
||||
return .{
|
||||
.shader = .init(vertexPath, fragmentPath, defines, uniformStruct),
|
||||
.rasterState = rasterState,
|
||||
.multisampleState = .{}, // TODO: Not implemented
|
||||
.depthStencilState = depthStencilState,
|
||||
.blendState = blendState,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: Pipeline) void {
|
||||
self.shader.deinit();
|
||||
}
|
||||
|
||||
fn conditionalEnable(typ: c.GLenum, val: bool) void {
|
||||
if(val) {
|
||||
c.glEnable(typ);
|
||||
} else {
|
||||
c.glDisable(typ);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(self: Pipeline, scissor: ?c.VkRect2D) void {
|
||||
self.shader.bind();
|
||||
if(scissor) |s| {
|
||||
c.glEnable(c.GL_SCISSOR_TEST);
|
||||
c.glScissor(s.offset.x, s.offset.y, @intCast(s.extent.width), @intCast(s.extent.height));
|
||||
} else {
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
conditionalEnable(c.GL_DEPTH_CLAMP, self.rasterState.depthClamp);
|
||||
conditionalEnable(c.GL_RASTERIZER_DISCARD, self.rasterState.rasterizerDiscard);
|
||||
conditionalEnable(c.GL_RASTERIZER_DISCARD, self.rasterState.rasterizerDiscard);
|
||||
c.glPolygonMode(c.GL_FRONT_AND_BACK, switch(self.rasterState.polygonMode) {
|
||||
.fill => c.GL_FILL,
|
||||
.line => c.GL_LINE,
|
||||
.point => c.GL_POINT,
|
||||
else => unreachable,
|
||||
});
|
||||
if(self.rasterState.cullMode != .none) {
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
c.glCullFace(switch(self.rasterState.cullMode) {
|
||||
.front => c.GL_FRONT,
|
||||
.back => c.GL_BACK,
|
||||
.frontAndBack => c.GL_FRONT_AND_BACK,
|
||||
else => unreachable,
|
||||
});
|
||||
} else {
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
}
|
||||
c.glFrontFace(switch(self.rasterState.frontFace) {
|
||||
.counterClockwise => c.GL_CCW,
|
||||
.clockwise => c.GL_CW,
|
||||
});
|
||||
if(self.rasterState.depthBias) |depthBias| {
|
||||
c.glEnable(c.GL_POLYGON_OFFSET_FILL);
|
||||
c.glEnable(c.GL_POLYGON_OFFSET_LINE);
|
||||
c.glEnable(c.GL_POLYGON_OFFSET_POINT);
|
||||
c.glPolygonOffset(depthBias.slopeFactor, depthBias.constantFactor);
|
||||
} else {
|
||||
c.glDisable(c.GL_POLYGON_OFFSET_FILL);
|
||||
c.glDisable(c.GL_POLYGON_OFFSET_LINE);
|
||||
c.glDisable(c.GL_POLYGON_OFFSET_POINT);
|
||||
}
|
||||
c.glLineWidth(self.rasterState.lineWidth);
|
||||
|
||||
// TODO: Multisampling
|
||||
|
||||
conditionalEnable(c.GL_DEPTH_TEST, self.depthStencilState.depthTest);
|
||||
c.glDepthMask(@intFromBool(self.depthStencilState.depthWrite));
|
||||
c.glDepthFunc(switch(self.depthStencilState.depthCompare) {
|
||||
.never => c.GL_NEVER,
|
||||
.less => c.GL_LESS,
|
||||
.equal => c.GL_EQUAL,
|
||||
.lessOrEqual => c.GL_LEQUAL,
|
||||
.greater => c.GL_GREATER,
|
||||
.notEqual => c.GL_NOTEQUAL,
|
||||
.greateOrEqual => c.GL_GEQUAL,
|
||||
.always => c.GL_ALWAYS,
|
||||
});
|
||||
// TODO: stencilTest
|
||||
|
||||
// TODO: logicOp
|
||||
for(self.blendState.attachments, 0..) |attachment, i| {
|
||||
if(!attachment.enabled) {
|
||||
c.glDisable(c.GL_BLEND);
|
||||
continue;
|
||||
}
|
||||
c.glEnable(c.GL_BLEND);
|
||||
c.glBlendEquationSeparatei(@intCast(i), attachment.colorBlendOp.toGl(), attachment.alphaBlendOp.toGl());
|
||||
c.glBlendFuncSeparatei(@intCast(i), attachment.srcColorBlendFactor.toGl(), attachment.dstColorBlendFactor.toGl(), attachment.srcAlphaBlendFactor.toGl(), attachment.dstAlphaBlendFactor.toGl());
|
||||
}
|
||||
c.glBlendColor(self.blendState.blendConstants[0], self.blendState.blendConstants[1], self.blendState.blendConstants[2], self.blendState.blendConstants[3]);
|
||||
}
|
||||
};
|
||||
|
||||
pub const SSBO = struct { // MARK: SSBO
|
||||
bufferID: c_uint,
|
||||
pub fn init() SSBO {
|
||||
@ -1653,6 +2049,9 @@ pub const FrameBuffer = struct { // MARK: FrameBuffer
|
||||
}
|
||||
|
||||
pub fn clear(_: FrameBuffer, clearColor: Vec4f) void {
|
||||
c.glDepthFunc(c.GL_LESS);
|
||||
c.glDepthMask(c.GL_TRUE);
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
c.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||
c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
@ -2083,12 +2482,20 @@ const block_texture = struct { // MARK: block_texture
|
||||
var uniforms: struct {
|
||||
transparent: c_int,
|
||||
} = undefined;
|
||||
var shader: Shader = undefined;
|
||||
var pipeline: Pipeline = undefined;
|
||||
var depthTexture: Texture = undefined;
|
||||
const textureSize = 128;
|
||||
|
||||
fn init() void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/item_texture_post.vs", "assets/cubyz/shaders/item_texture_post.fs", "", &uniforms);
|
||||
pipeline = Pipeline.init(
|
||||
"assets/cubyz/shaders/item_texture_post.vs",
|
||||
"assets/cubyz/shaders/item_texture_post.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
depthTexture = .init();
|
||||
depthTexture.bind();
|
||||
var data: [128*128]f32 = undefined;
|
||||
@ -2106,7 +2513,7 @@ const block_texture = struct { // MARK: block_texture
|
||||
c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_WRAP_T, c.GL_REPEAT);
|
||||
}
|
||||
fn deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
depthTexture.deinit();
|
||||
}
|
||||
};
|
||||
@ -2117,15 +2524,6 @@ pub fn generateBlockTexture(blockType: u16) Texture {
|
||||
c.glViewport(0, 0, textureSize, textureSize);
|
||||
|
||||
var frameBuffer: FrameBuffer = undefined;
|
||||
const scissor = c.glIsEnabled(c.GL_SCISSOR_TEST);
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
defer if(scissor != 0) c.glEnable(c.GL_SCISSOR_TEST);
|
||||
const depthTest = c.glIsEnabled(c.GL_DEPTH_TEST);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
defer if(depthTest != 0) c.glEnable(c.GL_DEPTH_TEST);
|
||||
const cullFace = c.glIsEnabled(c.GL_CULL_FACE);
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
defer if(cullFace != 0) c.glEnable(c.GL_CULL_FACE);
|
||||
|
||||
frameBuffer.init(false, c.GL_NEAREST, c.GL_REPEAT);
|
||||
defer frameBuffer.deinit();
|
||||
@ -2213,14 +2611,12 @@ pub fn generateBlockTexture(blockType: u16) Texture {
|
||||
finalFrameBuffer.bind();
|
||||
const texture = Texture{.textureID = finalFrameBuffer.texture};
|
||||
defer c.glDeleteFramebuffers(1, &finalFrameBuffer.frameBuffer);
|
||||
block_texture.shader.bind();
|
||||
block_texture.pipeline.bind(null);
|
||||
c.glUniform1i(block_texture.uniforms.transparent, if(block.transparent()) c.GL_TRUE else c.GL_FALSE);
|
||||
frameBuffer.bindTexture(c.GL_TEXTURE3);
|
||||
|
||||
c.glBindVertexArray(draw.rectVAO);
|
||||
c.glDisable(c.GL_BLEND);
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
c.glEnable(c.GL_BLEND);
|
||||
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
@ -86,7 +86,7 @@ var titleTexture: Texture = undefined;
|
||||
var closeTexture: Texture = undefined;
|
||||
var zoomInTexture: Texture = undefined;
|
||||
var zoomOutTexture: Texture = undefined;
|
||||
var shader: Shader = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
var windowUniforms: struct {
|
||||
screen: c_int,
|
||||
start: c_int,
|
||||
@ -94,7 +94,7 @@ var windowUniforms: struct {
|
||||
color: c_int,
|
||||
scale: c_int,
|
||||
} = undefined;
|
||||
pub var borderShader: Shader = undefined;
|
||||
pub var borderPipeline: graphics.Pipeline = undefined;
|
||||
pub var borderUniforms: struct {
|
||||
screen: c_int,
|
||||
start: c_int,
|
||||
@ -105,10 +105,24 @@ pub var borderUniforms: struct {
|
||||
} = undefined;
|
||||
|
||||
pub fn __init() void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", "", &windowUniforms);
|
||||
shader.bind();
|
||||
borderShader = Shader.initAndGetUniforms("assets/cubyz/shaders/ui/window_border.vs", "assets/cubyz/shaders/ui/window_border.fs", "", &borderUniforms);
|
||||
borderShader.bind();
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/ui/button.vs",
|
||||
"assets/cubyz/shaders/ui/button.fs",
|
||||
"",
|
||||
&windowUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
borderPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/ui/window_border.vs",
|
||||
"assets/cubyz/shaders/ui/window_border.fs",
|
||||
"",
|
||||
&borderUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
|
||||
backgroundTexture = Texture.initFromFile("assets/cubyz/ui/window_background.png");
|
||||
titleTexture = Texture.initFromFile("assets/cubyz/ui/window_title.png");
|
||||
@ -118,7 +132,7 @@ pub fn __init() void {
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
backgroundTexture.deinit();
|
||||
titleTexture.deinit();
|
||||
}
|
||||
@ -477,7 +491,7 @@ pub fn render(self: *const GuiWindow, mousePosition: Vec2f) void {
|
||||
const oldScale = draw.setScale(self.scale);
|
||||
if(self.hasBackground) {
|
||||
draw.setColor(0xff000000);
|
||||
shader.bind();
|
||||
pipeline.bind(draw.getScissor());
|
||||
backgroundTexture.bindTo(0);
|
||||
draw.customShadedRect(windowUniforms, .{0, 0}, self.size/@as(Vec2f, @splat(self.scale)));
|
||||
}
|
||||
@ -486,7 +500,7 @@ pub fn render(self: *const GuiWindow, mousePosition: Vec2f) void {
|
||||
component.render((mousePosition - self.pos)/@as(Vec2f, @splat(self.scale)));
|
||||
}
|
||||
if(self.showTitleBar or gui.reorderWindows) {
|
||||
shader.bind();
|
||||
pipeline.bind(draw.getScissor());
|
||||
titleTexture.bindTo(0);
|
||||
draw.setColor(0xff000000);
|
||||
draw.customShadedRect(windowUniforms, .{0, 0}, .{self.size[0]/self.scale, titleBarHeight});
|
||||
|
@ -44,7 +44,7 @@ const Textures = struct {
|
||||
var normalTextures: Textures = undefined;
|
||||
var hoveredTextures: Textures = undefined;
|
||||
var pressedTextures: Textures = undefined;
|
||||
pub var shader: Shader = undefined;
|
||||
pub var pipeline: graphics.Pipeline = undefined;
|
||||
pub var buttonUniforms: struct {
|
||||
screen: c_int,
|
||||
start: c_int,
|
||||
@ -61,15 +61,22 @@ onAction: gui.Callback,
|
||||
child: GuiComponent,
|
||||
|
||||
pub fn __init() void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", "", &buttonUniforms);
|
||||
shader.bind();
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/ui/button.vs",
|
||||
"assets/cubyz/shaders/ui/button.fs",
|
||||
"",
|
||||
&buttonUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
normalTextures = Textures.init("assets/cubyz/ui/button");
|
||||
hoveredTextures = Textures.init("assets/cubyz/ui/button_hovered");
|
||||
pressedTextures = Textures.init("assets/cubyz/ui/button_pressed");
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
normalTextures.deinit();
|
||||
hoveredTextures.deinit();
|
||||
pressedTextures.deinit();
|
||||
@ -136,7 +143,7 @@ pub fn render(self: *Button, mousePosition: Vec2f) void {
|
||||
normalTextures;
|
||||
draw.setColor(0xff000000);
|
||||
textures.texture.bindTo(0);
|
||||
shader.bind();
|
||||
pipeline.bind(draw.getScissor());
|
||||
self.hovered = false;
|
||||
draw.customShadedRect(buttonUniforms, self.pos + Vec2f{2, 2}, self.size - Vec2f{4, 4});
|
||||
{ // Draw the outline using the 9-slice texture.
|
||||
|
@ -112,7 +112,7 @@ pub fn render(self: *CheckBox, mousePosition: Vec2f) void {
|
||||
textureEmptyNormal.bindTo(0);
|
||||
}
|
||||
}
|
||||
Button.shader.bind();
|
||||
Button.pipeline.bind(draw.getScissor());
|
||||
self.hovered = false;
|
||||
draw.customShadedRect(Button.buttonUniforms, self.pos + Vec2f{0, self.size[1]/2 - boxSize/2}, @as(Vec2f, @splat(boxSize)));
|
||||
const textPos = self.pos + Vec2f{boxSize/2, 0} + self.size/@as(Vec2f, @splat(2.0)) - self.label.size/@as(Vec2f, @splat(2.0));
|
||||
|
@ -123,7 +123,7 @@ pub fn mainButtonReleased(self: *ContinuousSlider, _: Vec2f) void {
|
||||
|
||||
pub fn render(self: *ContinuousSlider, mousePosition: Vec2f) void {
|
||||
texture.bindTo(0);
|
||||
Button.shader.bind();
|
||||
Button.pipeline.bind(draw.getScissor());
|
||||
draw.setColor(0xff000000);
|
||||
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||
|
||||
|
@ -136,7 +136,7 @@ pub fn mainButtonReleased(self: *DiscreteSlider, _: Vec2f) void {
|
||||
|
||||
pub fn render(self: *DiscreteSlider, mousePosition: Vec2f) void {
|
||||
texture.bindTo(0);
|
||||
Button.shader.bind();
|
||||
Button.pipeline.bind(draw.getScissor());
|
||||
draw.setColor(0xff000000);
|
||||
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||
|
||||
|
@ -95,7 +95,7 @@ pub fn mainButtonReleased(self: *ScrollBar, mousePosition: Vec2f) void {
|
||||
|
||||
pub fn render(self: *ScrollBar, mousePosition: Vec2f) void {
|
||||
texture.bindTo(0);
|
||||
Button.shader.bind();
|
||||
Button.pipeline.bind(draw.getScissor());
|
||||
draw.setColor(0xff000000);
|
||||
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||
|
||||
|
@ -485,7 +485,7 @@ fn ensureCursorVisibility(self: *TextInput) void {
|
||||
|
||||
pub fn render(self: *TextInput, mousePosition: Vec2f) void {
|
||||
texture.bindTo(0);
|
||||
Button.shader.bind();
|
||||
Button.pipeline.bind(draw.getScissor());
|
||||
draw.setColor(0xff000000);
|
||||
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||
const oldTranslation = draw.setTranslation(self.pos);
|
||||
|
@ -548,7 +548,7 @@ pub fn updateAndRenderGui() void {
|
||||
if(!hideGui) {
|
||||
if(!main.Window.grabbed) {
|
||||
draw.setColor(0x80000000);
|
||||
GuiWindow.borderShader.bind();
|
||||
GuiWindow.borderPipeline.bind(draw.getScissor());
|
||||
graphics.c.glUniform2f(GuiWindow.borderUniforms.effectLength, main.Window.getWindowSize()[0]/6, main.Window.getWindowSize()[1]/6);
|
||||
draw.customShadedRect(GuiWindow.borderUniforms, .{0, 0}, main.Window.getWindowSize());
|
||||
}
|
||||
|
@ -23,21 +23,44 @@ pub var window = GuiWindow{
|
||||
};
|
||||
|
||||
var texture: Texture = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
var uniforms: struct {
|
||||
screen: c_int,
|
||||
start: c_int,
|
||||
size: c_int,
|
||||
color: c_int,
|
||||
uvOffset: c_int,
|
||||
uvDim: c_int,
|
||||
} = undefined;
|
||||
|
||||
pub fn init() void {
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/Image.vs",
|
||||
"assets/cubyz/shaders/graphics/Image.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.{
|
||||
.srcColorBlendFactor = .one,
|
||||
.dstColorBlendFactor = .one,
|
||||
.colorBlendOp = .subtract,
|
||||
.srcAlphaBlendFactor = .one,
|
||||
.dstAlphaBlendFactor = .one,
|
||||
.alphaBlendOp = .subtract,
|
||||
}}},
|
||||
);
|
||||
texture = Texture.initFromFile("assets/cubyz/ui/hud/crosshair.png");
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
pipeline.deinit();
|
||||
texture.deinit();
|
||||
}
|
||||
|
||||
pub fn render() void {
|
||||
texture.bindTo(0);
|
||||
graphics.draw.setColor(0xffffffff);
|
||||
c.glBlendFunc(c.GL_ONE, c.GL_ONE);
|
||||
c.glBlendEquation(c.GL_FUNC_SUBTRACT);
|
||||
graphics.draw.boundImage(.{0, 0}, .{size, size});
|
||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||
c.glBlendEquation(c.GL_FUNC_ADD);
|
||||
pipeline.bind(graphics.draw.getScissor());
|
||||
graphics.draw.customShadedImage(&uniforms, .{0, 0}, .{size, size});
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub var window = GuiWindow{
|
||||
var lastFrameTime: [2048]f32 = undefined;
|
||||
var index: u31 = 0;
|
||||
var ssbo: graphics.SSBO = undefined;
|
||||
var shader: graphics.Shader = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
const border: f32 = 8;
|
||||
|
||||
var uniforms: struct {
|
||||
@ -41,7 +41,15 @@ var uniforms: struct {
|
||||
|
||||
pub fn init() void {
|
||||
ssbo = graphics.SSBO.init();
|
||||
shader = graphics.Shader.initAndGetUniforms("assets/cubyz/shaders/graphics/graph.vs", "assets/cubyz/shaders/graphics/graph.fs", "", &uniforms);
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/graphics/graph.vs",
|
||||
"assets/cubyz/shaders/graphics/graph.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
@ -60,7 +68,7 @@ pub fn render() void {
|
||||
draw.line(.{border, 40}, .{window.contentSize[0] - border, 40});
|
||||
draw.line(.{border, 56}, .{window.contentSize[0] - border, 56});
|
||||
draw.setColor(0xffffffff);
|
||||
shader.bind();
|
||||
pipeline.bind(null);
|
||||
graphics.c.glUniform1i(uniforms.points, lastFrameTime.len);
|
||||
graphics.c.glUniform1i(uniforms.offset, index);
|
||||
graphics.c.glUniform3f(uniforms.lineColor, 1, 1, 1);
|
||||
|
@ -542,7 +542,7 @@ pub const ItemDisplayManager = struct { // MARK: ItemDisplayManager
|
||||
};
|
||||
|
||||
pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
|
||||
var itemShader: graphics.Shader = undefined;
|
||||
var itemPipeline: graphics.Pipeline = undefined;
|
||||
var itemUniforms: struct {
|
||||
projectionMatrix: c_int,
|
||||
modelMatrix: c_int,
|
||||
@ -648,7 +648,15 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
|
||||
};
|
||||
|
||||
pub fn init() void {
|
||||
itemShader = graphics.Shader.initAndGetUniforms("assets/cubyz/shaders/item_drop.vs", "assets/cubyz/shaders/item_drop.fs", "", &itemUniforms);
|
||||
itemPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/item_drop.vs",
|
||||
"assets/cubyz/shaders/item_drop.fs",
|
||||
"",
|
||||
&itemUniforms,
|
||||
.{},
|
||||
.{.depthTest = true},
|
||||
.{.attachments = &.{.alphaBlending}},
|
||||
);
|
||||
itemModelSSBO = .init();
|
||||
itemModelSSBO.bufferData(i32, &[3]i32{1, 1, 1});
|
||||
itemModelSSBO.bind(2);
|
||||
@ -658,7 +666,7 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
itemShader.deinit();
|
||||
itemPipeline.deinit();
|
||||
itemModelSSBO.deinit();
|
||||
modelData.deinit();
|
||||
voxelModels.clear();
|
||||
@ -676,7 +684,7 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
|
||||
}
|
||||
|
||||
fn bindCommonUniforms(projMatrix: Mat4f, viewMatrix: Mat4f, ambientLight: Vec3f) void {
|
||||
itemShader.bind();
|
||||
itemPipeline.bind(null);
|
||||
c.glUniform1f(itemUniforms.reflectionMapSize, main.renderer.reflectionCubeMapSize);
|
||||
c.glUniformMatrix4fv(itemUniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&projMatrix));
|
||||
c.glUniform3fv(itemUniforms.ambientLight, 1, @ptrCast(&ambientLight));
|
||||
|
12
src/main.zig
12
src/main.zig
@ -652,11 +652,6 @@ pub fn main() void { // MARK: main()
|
||||
|
||||
const c = Window.c;
|
||||
|
||||
c.glCullFace(c.GL_BACK);
|
||||
c.glEnable(c.GL_BLEND);
|
||||
c.glEnable(c.GL_DEPTH_CLAMP);
|
||||
c.glDepthFunc(c.GL_LESS);
|
||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||
Window.GLFWCallbacks.framebufferSize(undefined, Window.width, Window.height);
|
||||
var lastBeginRendering = std.time.nanoTimestamp();
|
||||
|
||||
@ -673,6 +668,9 @@ pub fn main() void { // MARK: main()
|
||||
c.glfwSwapBuffers(Window.window);
|
||||
// Clear may also wait on vsync, so it's done before handling events:
|
||||
gui.windowlist.gpu_performance_measuring.startQuery(.screenbuffer_clear);
|
||||
c.glDepthFunc(c.GL_LESS);
|
||||
c.glDepthMask(c.GL_TRUE);
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
c.glClearColor(0.5, 1, 1, 1);
|
||||
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
|
||||
gui.windowlist.gpu_performance_measuring.stopQuery();
|
||||
@ -707,13 +705,9 @@ pub fn main() void { // MARK: main()
|
||||
}
|
||||
|
||||
if(!isHidden) {
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
c.glEnable(c.GL_DEPTH_TEST);
|
||||
renderer.render(game.Player.getEyePosBlocking(), deltaTime);
|
||||
// Render the GUI
|
||||
gui.windowlist.gpu_performance_measuring.startQuery(.gui);
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
gui.updateAndRenderGui();
|
||||
gui.windowlist.gpu_performance_measuring.stopQuery();
|
||||
}
|
||||
|
186
src/renderer.zig
186
src/renderer.zig
@ -33,7 +33,7 @@ const maximumMeshTime = 12;
|
||||
pub const zNear = 0.1;
|
||||
pub const zFar = 65536.0; // TODO: Fix z-fighting problems.
|
||||
|
||||
var deferredRenderPassShader: graphics.Shader = undefined;
|
||||
var deferredRenderPassPipeline: graphics.Pipeline = undefined;
|
||||
var deferredUniforms: struct {
|
||||
@"fog.color": c_int,
|
||||
@"fog.density": c_int,
|
||||
@ -46,7 +46,7 @@ var deferredUniforms: struct {
|
||||
playerPositionInteger: c_int,
|
||||
playerPositionFraction: c_int,
|
||||
} = undefined;
|
||||
var fakeReflectionShader: graphics.Shader = undefined;
|
||||
var fakeReflectionPipeline: graphics.Pipeline = undefined;
|
||||
var fakeReflectionUniforms: struct {
|
||||
normalVector: c_int,
|
||||
upVector: c_int,
|
||||
@ -61,8 +61,24 @@ pub const reflectionCubeMapSize = 64;
|
||||
var reflectionCubeMap: graphics.CubeMapTexture = undefined;
|
||||
|
||||
pub fn init() void {
|
||||
deferredRenderPassShader = Shader.initAndGetUniforms("assets/cubyz/shaders/deferred_render_pass.vs", "assets/cubyz/shaders/deferred_render_pass.fs", "", &deferredUniforms);
|
||||
fakeReflectionShader = Shader.initAndGetUniforms("assets/cubyz/shaders/fake_reflection.vs", "assets/cubyz/shaders/fake_reflection.fs", "", &fakeReflectionUniforms);
|
||||
deferredRenderPassPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/deferred_render_pass.vs",
|
||||
"assets/cubyz/shaders/deferred_render_pass.fs",
|
||||
"",
|
||||
&deferredUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
fakeReflectionPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/fake_reflection.vs",
|
||||
"assets/cubyz/shaders/fake_reflection.fs",
|
||||
"",
|
||||
&fakeReflectionUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE);
|
||||
worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGB16F);
|
||||
Bloom.init();
|
||||
@ -79,8 +95,8 @@ pub fn init() void {
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
deferredRenderPassShader.deinit();
|
||||
fakeReflectionShader.deinit();
|
||||
deferredRenderPassPipeline.deinit();
|
||||
fakeReflectionPipeline.deinit();
|
||||
worldFrameBuffer.deinit();
|
||||
Bloom.deinit();
|
||||
MeshSelection.deinit();
|
||||
@ -97,7 +113,7 @@ fn initReflectionCubeMap() void {
|
||||
framebuffer.init(false, c.GL_LINEAR, c.GL_CLAMP_TO_EDGE);
|
||||
defer framebuffer.deinit();
|
||||
framebuffer.bind();
|
||||
fakeReflectionShader.bind();
|
||||
fakeReflectionPipeline.bind(null);
|
||||
c.glUniform1f(fakeReflectionUniforms.frequency, 1);
|
||||
c.glUniform1f(fakeReflectionUniforms.reflectionMapSize, reflectionCubeMapSize);
|
||||
for(0..6) |face| {
|
||||
@ -106,8 +122,6 @@ fn initReflectionCubeMap() void {
|
||||
c.glUniform3fv(fakeReflectionUniforms.rightVector, 1, @ptrCast(&graphics.CubeMapTexture.faceRight(face)));
|
||||
reflectionCubeMap.bindToFramebuffer(framebuffer, @intCast(face));
|
||||
c.glBindVertexArray(graphics.draw.rectVAO);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
}
|
||||
@ -234,10 +248,6 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
gpu_performance_measuring.startQuery(.transparent_rendering_preparation);
|
||||
c.glTextureBarrier();
|
||||
|
||||
c.glBlendEquation(c.GL_FUNC_ADD);
|
||||
c.glBlendFunc(c.GL_ONE, c.GL_SRC1_COLOR);
|
||||
c.glDepthFunc(c.GL_LEQUAL);
|
||||
c.glDepthMask(c.GL_FALSE);
|
||||
{
|
||||
chunkList.clearRetainingCapacity();
|
||||
var i: usize = meshes.len;
|
||||
@ -251,9 +261,6 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
chunk_meshing.drawChunksIndirect(chunkList.items, game.projectionMatrix, ambientLight, playerPos, true);
|
||||
}
|
||||
}
|
||||
c.glDepthMask(c.GL_TRUE);
|
||||
c.glDepthFunc(c.GL_LESS);
|
||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
c.glDepthRange(0, 0.001);
|
||||
itemdrop.ItemDropRenderer.renderDisplayItems(ambientLight, playerPos);
|
||||
@ -275,7 +282,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
worldFrameBuffer.bindTexture(c.GL_TEXTURE3);
|
||||
worldFrameBuffer.bindDepthTexture(c.GL_TEXTURE4);
|
||||
worldFrameBuffer.unbind();
|
||||
deferredRenderPassShader.bind();
|
||||
deferredRenderPassPipeline.bind(null);
|
||||
if(!blocks.meshes.hasFog(playerBlock)) {
|
||||
c.glUniform3fv(deferredUniforms.@"fog.color", 1, @ptrCast(&game.fog.skyColor));
|
||||
c.glUniform1f(deferredUniforms.@"fog.density", game.fog.density);
|
||||
@ -298,8 +305,6 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, activeFrameBuffer);
|
||||
|
||||
c.glBindVertexArray(graphics.draw.rectVAO);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0);
|
||||
@ -314,9 +319,9 @@ const Bloom = struct { // MARK: Bloom
|
||||
var emptyBuffer: graphics.Texture = undefined;
|
||||
var width: u31 = std.math.maxInt(u31);
|
||||
var height: u31 = std.math.maxInt(u31);
|
||||
var firstPassShader: graphics.Shader = undefined;
|
||||
var secondPassShader: graphics.Shader = undefined;
|
||||
var colorExtractAndDownsampleShader: graphics.Shader = undefined;
|
||||
var firstPassPipeline: graphics.Pipeline = undefined;
|
||||
var secondPassPipeline: graphics.Pipeline = undefined;
|
||||
var colorExtractAndDownsamplePipeline: graphics.Pipeline = undefined;
|
||||
var colorExtractUniforms: struct {
|
||||
zNear: c_int,
|
||||
zFar: c_int,
|
||||
@ -335,20 +340,45 @@ const Bloom = struct { // MARK: Bloom
|
||||
buffer2.init(false, c.GL_LINEAR, c.GL_CLAMP_TO_EDGE);
|
||||
emptyBuffer = .init();
|
||||
emptyBuffer.generate(graphics.Image.emptyImage);
|
||||
firstPassShader = graphics.Shader.init("assets/cubyz/shaders/bloom/first_pass.vs", "assets/cubyz/shaders/bloom/first_pass.fs", "");
|
||||
secondPassShader = graphics.Shader.init("assets/cubyz/shaders/bloom/second_pass.vs", "assets/cubyz/shaders/bloom/second_pass.fs", "");
|
||||
colorExtractAndDownsampleShader = graphics.Shader.initAndGetUniforms("assets/cubyz/shaders/bloom/color_extractor_downsample.vs", "assets/cubyz/shaders/bloom/color_extractor_downsample.fs", "", &colorExtractUniforms);
|
||||
firstPassPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/bloom/first_pass.vs",
|
||||
"assets/cubyz/shaders/bloom/first_pass.fs",
|
||||
"",
|
||||
null,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
secondPassPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/bloom/second_pass.vs",
|
||||
"assets/cubyz/shaders/bloom/second_pass.fs",
|
||||
"",
|
||||
null,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
colorExtractAndDownsamplePipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/bloom/color_extractor_downsample.vs",
|
||||
"assets/cubyz/shaders/bloom/color_extractor_downsample.fs",
|
||||
"",
|
||||
&colorExtractUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
buffer1.deinit();
|
||||
buffer2.deinit();
|
||||
firstPassShader.deinit();
|
||||
secondPassShader.deinit();
|
||||
firstPassPipeline.deinit();
|
||||
secondPassPipeline.deinit();
|
||||
colorExtractAndDownsamplePipeline.deinit();
|
||||
}
|
||||
|
||||
fn extractImageDataAndDownsample(playerBlock: blocks.Block, playerPos: Vec3d, viewMatrix: Mat4f) void {
|
||||
colorExtractAndDownsampleShader.bind();
|
||||
colorExtractAndDownsamplePipeline.bind(null);
|
||||
worldFrameBuffer.bindTexture(c.GL_TEXTURE3);
|
||||
worldFrameBuffer.bindDepthTexture(c.GL_TEXTURE4);
|
||||
buffer1.bind();
|
||||
@ -376,7 +406,7 @@ const Bloom = struct { // MARK: Bloom
|
||||
}
|
||||
|
||||
fn firstPass() void {
|
||||
firstPassShader.bind();
|
||||
firstPassPipeline.bind(null);
|
||||
buffer1.bindTexture(c.GL_TEXTURE3);
|
||||
buffer2.bind();
|
||||
c.glBindVertexArray(graphics.draw.rectVAO);
|
||||
@ -384,7 +414,7 @@ const Bloom = struct { // MARK: Bloom
|
||||
}
|
||||
|
||||
fn secondPass() void {
|
||||
secondPassShader.bind();
|
||||
secondPassPipeline.bind(null);
|
||||
buffer2.bindTexture(c.GL_TEXTURE3);
|
||||
buffer1.bind();
|
||||
c.glBindVertexArray(graphics.draw.rectVAO);
|
||||
@ -401,9 +431,6 @@ const Bloom = struct { // MARK: Bloom
|
||||
std.debug.assert(buffer2.validate());
|
||||
}
|
||||
gpu_performance_measuring.startQuery(.bloom_extract_downsample);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDepthMask(c.GL_FALSE);
|
||||
|
||||
c.glViewport(0, 0, width/4, height/4);
|
||||
extractImageDataAndDownsample(playerBlock, playerPos, viewMatrix);
|
||||
@ -417,10 +444,6 @@ const Bloom = struct { // MARK: Bloom
|
||||
c.glViewport(0, 0, width, height);
|
||||
buffer1.bindTexture(c.GL_TEXTURE5);
|
||||
|
||||
c.glDepthMask(c.GL_TRUE);
|
||||
c.glEnable(c.GL_DEPTH_TEST);
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||
gpu_performance_measuring.stopQuery();
|
||||
}
|
||||
|
||||
@ -430,7 +453,7 @@ const Bloom = struct { // MARK: Bloom
|
||||
};
|
||||
|
||||
pub const MenuBackGround = struct {
|
||||
var shader: Shader = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
var uniforms: struct {
|
||||
viewMatrix: c_int,
|
||||
projectionMatrix: c_int,
|
||||
@ -445,8 +468,15 @@ pub const MenuBackGround = struct {
|
||||
|
||||
fn init() !void {
|
||||
lastTime = std.time.nanoTimestamp();
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/background/vertex.vs", "assets/cubyz/shaders/background/fragment.fs", "", &uniforms);
|
||||
shader.bind();
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/background/vertex.vs",
|
||||
"assets/cubyz/shaders/background/fragment.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
// 4 sides of a simple cube with some panorama texture on it.
|
||||
const rawData = [_]f32{
|
||||
-1, 1, -1, 1, 1,
|
||||
@ -515,7 +545,7 @@ pub const MenuBackGround = struct {
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
c.glDeleteVertexArrays(1, &vao);
|
||||
c.glDeleteBuffers(2, &vbos);
|
||||
}
|
||||
@ -526,14 +556,13 @@ pub const MenuBackGround = struct {
|
||||
|
||||
pub fn render() void {
|
||||
if(texture.textureID == 0) return;
|
||||
c.glDisable(c.GL_CULL_FACE); // I'm not sure if my triangles are rotated correctly, and there are no triangles facing away from the player anyways.
|
||||
|
||||
// Use a simple rotation around the z axis, with a steadily increasing angle.
|
||||
const newTime = std.time.nanoTimestamp();
|
||||
angle += @as(f32, @floatFromInt(newTime - lastTime))/2e10;
|
||||
lastTime = newTime;
|
||||
const viewMatrix = Mat4f.rotationZ(angle);
|
||||
shader.bind();
|
||||
pipeline.bind(null);
|
||||
updateViewport(main.Window.width, main.Window.height, 70.0);
|
||||
|
||||
c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_TRUE, @ptrCast(&viewMatrix));
|
||||
@ -576,8 +605,9 @@ pub const MenuBackGround = struct {
|
||||
defer image.deinit(main.stackAllocator);
|
||||
|
||||
for(0..4) |i| {
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
c.glEnable(c.GL_DEPTH_TEST);
|
||||
c.glDepthFunc(c.GL_LESS);
|
||||
c.glDepthMask(c.GL_TRUE);
|
||||
c.glDisable(c.GL_SCISSOR_TEST);
|
||||
game.camera.rotation = .{0, 0, angles[i]};
|
||||
// Draw to frame buffer.
|
||||
buffer.bind();
|
||||
@ -595,8 +625,6 @@ pub const MenuBackGround = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0);
|
||||
|
||||
const fileName = std.fmt.allocPrint(main.stackAllocator.allocator, "assets/backgrounds/{s}_{}.png", .{game.world.?.name, game.world.?.gameTime.load(.monotonic)}) catch unreachable;
|
||||
@ -609,7 +637,7 @@ pub const MenuBackGround = struct {
|
||||
};
|
||||
|
||||
pub const Skybox = struct {
|
||||
var starShader: Shader = undefined;
|
||||
var starPipeline: graphics.Pipeline = undefined;
|
||||
var starUniforms: struct {
|
||||
mvp: c_int,
|
||||
starOpacity: c_int,
|
||||
@ -653,8 +681,22 @@ pub const Skybox = struct {
|
||||
};
|
||||
defer starColorImage.deinit(main.stackAllocator);
|
||||
|
||||
starShader = Shader.initAndGetUniforms("assets/cubyz/shaders/skybox/star.vs", "assets/cubyz/shaders/skybox/star.fs", "", &starUniforms);
|
||||
starShader.bind();
|
||||
starPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/skybox/star.vs",
|
||||
"assets/cubyz/shaders/skybox/star.fs",
|
||||
"",
|
||||
&starUniforms,
|
||||
.{.cullMode = .none},
|
||||
.{.depthTest = false, .depthWrite = false},
|
||||
.{.attachments = &.{.{
|
||||
.srcColorBlendFactor = .one,
|
||||
.dstColorBlendFactor = .one,
|
||||
.colorBlendOp = .add,
|
||||
.srcAlphaBlendFactor = .one,
|
||||
.dstAlphaBlendFactor = .one,
|
||||
.alphaBlendOp = .add,
|
||||
}}},
|
||||
);
|
||||
|
||||
var starData: [numStars*20]f32 = undefined;
|
||||
|
||||
@ -719,7 +761,7 @@ pub const Skybox = struct {
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
starShader.deinit();
|
||||
starPipeline.deinit();
|
||||
starSsbo.deinit();
|
||||
c.glDeleteVertexArrays(1, &starVao);
|
||||
}
|
||||
@ -744,13 +786,7 @@ pub const Skybox = struct {
|
||||
}
|
||||
|
||||
if(starOpacity != 0) {
|
||||
c.glDisable(c.GL_CULL_FACE);
|
||||
c.glDisable(c.GL_DEPTH_TEST);
|
||||
|
||||
c.glBlendFunc(c.GL_ONE, c.GL_ONE);
|
||||
c.glEnable(c.GL_BLEND);
|
||||
|
||||
starShader.bind();
|
||||
starPipeline.bind(null);
|
||||
|
||||
const starMatrix = game.projectionMatrix.mul(viewMatrix.mul(Mat4f.rotationX(@as(f32, @floatFromInt(time))/@as(f32, @floatFromInt(main.game.World.dayCycle)))));
|
||||
|
||||
@ -763,11 +799,6 @@ pub const Skybox = struct {
|
||||
c.glDrawArrays(c.GL_TRIANGLES, 0, numStars*3);
|
||||
|
||||
c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
c.glEnable(c.GL_CULL_FACE);
|
||||
c.glEnable(c.GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -808,7 +839,7 @@ pub const Frustum = struct { // MARK: Frustum
|
||||
};
|
||||
|
||||
pub const MeshSelection = struct { // MARK: MeshSelection
|
||||
var shader: Shader = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
var uniforms: struct {
|
||||
projectionMatrix: c_int,
|
||||
viewMatrix: c_int,
|
||||
@ -822,7 +853,19 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
||||
var cubeIBO: c_uint = undefined;
|
||||
|
||||
pub fn init() void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/block_selection_vertex.vs", "assets/cubyz/shaders/block_selection_fragment.fs", "", &uniforms);
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/block_selection_vertex.vs",
|
||||
"assets/cubyz/shaders/block_selection_fragment.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{.depthBias = .{
|
||||
.slopeFactor = -2,
|
||||
.clamp = 0,
|
||||
.constantFactor = 0,
|
||||
}},
|
||||
.{.depthTest = true, .depthWrite = true},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
|
||||
const rawData = [_]f32{
|
||||
0, 0, 0,
|
||||
@ -862,7 +905,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
shader.deinit();
|
||||
pipeline.deinit();
|
||||
c.glDeleteBuffers(1, &cubeIBO);
|
||||
c.glDeleteBuffers(1, &cubeVBO);
|
||||
c.glDeleteVertexArrays(1, &cubeVAO);
|
||||
@ -1107,7 +1150,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
||||
}
|
||||
|
||||
pub fn drawCube(projectionMatrix: Mat4f, viewMatrix: Mat4f, relativePositionToPlayer: Vec3d, min: Vec3f, max: Vec3f) void {
|
||||
shader.bind();
|
||||
pipeline.bind(null);
|
||||
|
||||
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&projectionMatrix));
|
||||
c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_TRUE, @ptrCast(&viewMatrix));
|
||||
@ -1122,26 +1165,19 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
||||
c.glUniform3f(uniforms.upperBounds, max[0], max[1], max[2]);
|
||||
|
||||
c.glBindVertexArray(cubeVAO);
|
||||
// c.glLineWidth(2); // TODO: Draw thicker lines so they are more visible. Maybe a simple shader + cube mesh is enough.
|
||||
// TODO: Draw thicker lines so they are more visible. Maybe a simple shader + cube mesh is enough.
|
||||
c.glDrawElements(c.GL_LINES, 12*2, c.GL_UNSIGNED_BYTE, null);
|
||||
}
|
||||
|
||||
pub fn render(projectionMatrix: Mat4f, viewMatrix: Mat4f, playerPos: Vec3d) void {
|
||||
if(main.gui.hideGui) return;
|
||||
if(selectedBlockPos) |_selectedBlockPos| {
|
||||
c.glEnable(c.GL_POLYGON_OFFSET_LINE);
|
||||
defer c.glDisable(c.GL_POLYGON_OFFSET_LINE);
|
||||
c.glPolygonOffset(-2, 0);
|
||||
drawCube(projectionMatrix, viewMatrix, @as(Vec3d, @floatFromInt(_selectedBlockPos)) - playerPos, selectionMin, selectionMax);
|
||||
}
|
||||
if(game.Player.selectionPosition1) |pos1| {
|
||||
if(game.Player.selectionPosition2) |pos2| {
|
||||
const bottomLeft: Vec3i = @min(pos1, pos2);
|
||||
const topRight: Vec3i = @max(pos1, pos2);
|
||||
|
||||
c.glEnable(c.GL_POLYGON_OFFSET_LINE);
|
||||
defer c.glDisable(c.GL_POLYGON_OFFSET_LINE);
|
||||
c.glPolygonOffset(-2, 0);
|
||||
drawCube(projectionMatrix, viewMatrix, @as(Vec3d, @floatFromInt(bottomLeft)) - playerPos, .{0, 0, 0}, @floatFromInt(topRight - bottomLeft + Vec3i{1, 1, 1}));
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ const gpu_performance_measuring = main.gui.windowlist.gpu_performance_measuring;
|
||||
|
||||
const mesh_storage = @import("mesh_storage.zig");
|
||||
|
||||
var shader: Shader = undefined;
|
||||
var transparentShader: Shader = undefined;
|
||||
var pipeline: graphics.Pipeline = undefined;
|
||||
var transparentPipeline: graphics.Pipeline = undefined;
|
||||
const UniformStruct = struct {
|
||||
projectionMatrix: c_int,
|
||||
viewMatrix: c_int,
|
||||
@ -56,7 +56,7 @@ pub var commandUniforms: struct {
|
||||
onlyDrawPreviouslyInvisible: c_int,
|
||||
lodDistance: c_int,
|
||||
} = undefined;
|
||||
pub var occlusionTestShader: Shader = undefined;
|
||||
pub var occlusionTestPipeline: graphics.Pipeline = undefined;
|
||||
pub var occlusionTestUniforms: struct {
|
||||
projectionMatrix: c_int,
|
||||
viewMatrix: c_int,
|
||||
@ -75,10 +75,50 @@ pub var transparentQuadsDrawn: usize = 0;
|
||||
|
||||
pub fn init() void {
|
||||
lighting.init();
|
||||
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", "#define transparent\n", &transparentUniforms);
|
||||
pipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/chunks/chunk_vertex.vs",
|
||||
"assets/cubyz/shaders/chunks/chunk_fragment.fs",
|
||||
"",
|
||||
&uniforms,
|
||||
.{},
|
||||
.{.depthTest = true, .depthWrite = true},
|
||||
.{.attachments = &.{.noBlending}},
|
||||
);
|
||||
transparentPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/chunks/chunk_vertex.vs",
|
||||
"assets/cubyz/shaders/chunks/transparent_fragment.fs",
|
||||
"#define transparent\n",
|
||||
&transparentUniforms,
|
||||
.{},
|
||||
.{.depthTest = true, .depthWrite = false, .depthCompare = .lessOrEqual},
|
||||
.{.attachments = &.{.{
|
||||
.srcColorBlendFactor = .one,
|
||||
.dstColorBlendFactor = .src1Color,
|
||||
.colorBlendOp = .add,
|
||||
.srcAlphaBlendFactor = .one,
|
||||
.dstAlphaBlendFactor = .src1Alpha,
|
||||
.alphaBlendOp = .add,
|
||||
}}},
|
||||
);
|
||||
commandShader = Shader.initComputeAndGetUniforms("assets/cubyz/shaders/chunks/fillIndirectBuffer.glsl", "", &commandUniforms);
|
||||
occlusionTestShader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/occlusionTestVertex.vs", "assets/cubyz/shaders/chunks/occlusionTestFragment.fs", "", &occlusionTestUniforms);
|
||||
occlusionTestPipeline = graphics.Pipeline.init(
|
||||
"assets/cubyz/shaders/chunks/occlusionTestVertex.vs",
|
||||
"assets/cubyz/shaders/chunks/occlusionTestFragment.fs",
|
||||
"",
|
||||
&occlusionTestUniforms,
|
||||
.{},
|
||||
.{.depthTest = true, .depthWrite = false},
|
||||
.{.attachments = &.{.{
|
||||
.enabled = false,
|
||||
.srcColorBlendFactor = undefined,
|
||||
.dstColorBlendFactor = undefined,
|
||||
.colorBlendOp = undefined,
|
||||
.srcAlphaBlendFactor = undefined,
|
||||
.dstAlphaBlendFactor = undefined,
|
||||
.alphaBlendOp = undefined,
|
||||
.colorWriteMask = .none,
|
||||
}}},
|
||||
);
|
||||
|
||||
var rawData: [6*3 << (3*chunk.chunkShift)]u32 = undefined; // 6 vertices per face, maximum 3 faces/block
|
||||
const lut = [_]u32{0, 2, 1, 1, 2, 3};
|
||||
@ -102,8 +142,9 @@ pub fn init() void {
|
||||
|
||||
pub fn deinit() void {
|
||||
lighting.deinit();
|
||||
shader.deinit();
|
||||
transparentShader.deinit();
|
||||
pipeline.deinit();
|
||||
transparentPipeline.deinit();
|
||||
occlusionTestPipeline.deinit();
|
||||
commandShader.deinit();
|
||||
c.glDeleteVertexArrays(1, &vao);
|
||||
c.glDeleteBuffers(1, &vbo);
|
||||
@ -151,7 +192,7 @@ fn bindCommonUniforms(locations: *UniformStruct, projMatrix: Mat4f, ambient: Vec
|
||||
}
|
||||
|
||||
pub fn bindShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d) void {
|
||||
shader.bind();
|
||||
pipeline.bind(null);
|
||||
|
||||
bindCommonUniforms(&uniforms, projMatrix, ambient, playerPos);
|
||||
|
||||
@ -159,7 +200,7 @@ pub fn bindShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d
|
||||
}
|
||||
|
||||
pub fn bindTransparentShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d) void {
|
||||
transparentShader.bind();
|
||||
transparentPipeline.bind(null);
|
||||
|
||||
c.glUniform3fv(transparentUniforms.@"fog.color", 1, @ptrCast(&game.fog.skyColor));
|
||||
c.glUniform1f(transparentUniforms.@"fog.density", game.fog.density);
|
||||
@ -203,17 +244,13 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
||||
|
||||
// Occlusion tests:
|
||||
gpu_performance_measuring.startQuery(if(transparent) .transparent_rendering_occlusion_test else .chunk_rendering_occlusion_test);
|
||||
occlusionTestShader.bind();
|
||||
occlusionTestPipeline.bind(null);
|
||||
c.glUniform3i(occlusionTestUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
||||
c.glUniform3f(occlusionTestUniforms.playerPositionFraction, @floatCast(@mod(playerPos[0], 1)), @floatCast(@mod(playerPos[1], 1)), @floatCast(@mod(playerPos[2], 1)));
|
||||
c.glUniformMatrix4fv(occlusionTestUniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&projMatrix));
|
||||
c.glUniformMatrix4fv(occlusionTestUniforms.viewMatrix, 1, c.GL_TRUE, @ptrCast(&game.camera.viewMatrix));
|
||||
c.glDepthMask(c.GL_FALSE);
|
||||
c.glColorMask(c.GL_FALSE, c.GL_FALSE, c.GL_FALSE, c.GL_FALSE);
|
||||
c.glBindVertexArray(vao);
|
||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(6*6*chunkIDs.len), c.GL_UNSIGNED_INT, null, chunkIDAllocation.start*24);
|
||||
c.glDepthMask(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);
|
||||
gpu_performance_measuring.stopQuery();
|
||||
|
||||
@ -226,7 +263,6 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
||||
|
||||
if(transparent) {
|
||||
bindTransparentShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||
c.glDepthMask(c.GL_FALSE);
|
||||
} else {
|
||||
bindShaderAndUniforms(projMatrix, ambient, playerPos);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user