diff --git a/src/Renderer.zig b/src/Renderer.zig index ed60269..14b665b 100644 --- a/src/Renderer.zig +++ b/src/Renderer.zig @@ -12,20 +12,14 @@ buffer: gl.Buffer, color: [4]f32 = .{ 0, 0, 0, 0 }, // There's a vbo for each shader program -vbo: [nPrograms][max_objects]f32 = .{.{0.0} ** max_objects} ** nPrograms, -vbo_index: [nPrograms]usize = .{0} ** nPrograms, +vbo: [max_objects]f32 = .{0.0} ** max_objects, +vbo_index: usize = 0, // The index of the program is the enum converted to int -programs: [nPrograms]gl.Program = .{undefined} ** nPrograms, textures: [max_objects]Texture = .{undefined} ** max_objects, const max_objects: usize = 16384; - -const shaderProgram = enum { - color, - texture, -}; -const nPrograms = std.meta.fields(shaderProgram).len; +const quadSize: usize = 9 * 6; fn glGetProcAddress(p: []const u8, proc: [:0]const u8) ?*const anyopaque { _ = p; @@ -58,6 +52,7 @@ pub fn init() !Self { std.debug.print("WARNING: Unable to configure the swap interval.\n", .{}); }; + // Activate blending and configure it gl.enable(.blend); gl.blendFunc(.src_alpha, .one_minus_src_alpha); @@ -67,22 +62,23 @@ pub fn init() !Self { var renderer = Self{ .window = window, .context = ctx, .buffer = buf }; // Load the shader programs according to the names in the enum - inline for (std.meta.fields(shaderProgram)) |programEnum| { - renderer.programs[programEnum.value] = renderer.loadProgram(programEnum.name); - } + _ = renderer.loadProgram("texture").use(); var vertex_array = gl.VertexArray.gen(); vertex_array.bind(); - gl.vertexAttribPointer(0, 2, .float, false, @sizeOf(f32) * 8, @sizeOf(f32) * 0); + gl.vertexAttribPointer(0, 2, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 0); gl.enableVertexAttribArray(0); - gl.vertexAttribPointer(1, 4, .float, false, @sizeOf(f32) * 8, @sizeOf(f32) * 2); + gl.vertexAttribPointer(1, 4, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 2); gl.enableVertexAttribArray(1); - gl.vertexAttribPointer(2, 2, .float, false, @sizeOf(f32) * 8, @sizeOf(f32) * 6); + gl.vertexAttribPointer(2, 2, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 6); gl.enableVertexAttribArray(2); + gl.vertexAttribPointer(3, 1, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 8); + gl.enableVertexAttribArray(3); + gl.clearColor(0.91, 0.85, 0.65, 1.00); return renderer; @@ -125,32 +121,20 @@ fn loadProgram(self: Self, comptime name: []const u8) gl.Program { } pub fn render(self: *Self) void { - // Render with each of the defined shader programs - for (self.programs) |_, program_i| { - self.programs[program_i].use(); + // TODO: Submit with SubData instead to not pass the whole buffer + self.buffer.data(f32, &self.vbo, .static_draw); - self.buffer.data(f32, &(self.vbo[program_i]), .static_draw); - - switch (@intToEnum(shaderProgram, program_i)) { - .color => { - gl.drawArrays(.triangles, 0, self.vbo_index[program_i]); - }, - .texture => { - var i: usize = 0; - const amount = self.vbo_index[program_i] / 48; - while (i < amount) : (i += 1) { - gl.bindTexture(self.textures[i].texture, .@"2d"); - gl.drawArrays(.triangles, i * 6, 6); - } - }, - } - - self.vbo_index[program_i] = 0; - - // Clear the vbo, this really shouldn't be necessary as the index is set to zero, - // but otherwise it leads to bugs - self.vbo[program_i] = .{0.0} ** max_objects; + var i: usize = 0; + const amount = self.vbo_index / quadSize; + while (i < amount) : (i += 1) { + gl.bindTexture(self.textures[i].texture, .@"2d"); + gl.drawArrays(.triangles, i * 6, 6); } + self.vbo_index = 0; + + // Clear the vbo, this really shouldn't be necessary as the index is set to zero, + // but otherwise it leads to bugs + self.vbo = .{0.0} ** max_objects; sdl.gl.swapWindow(self.window); gl.clear(.{ .color = true }); @@ -158,6 +142,9 @@ pub fn render(self: *Self) void { pub fn deinit(self: *Self) void { gl.disableVertexAttribArray(0); + gl.disableVertexAttribArray(1); + gl.disableVertexAttribArray(2); + gl.disableVertexAttribArray(3); sdl.quit(); sdl.ttf.quit(); self.window.destroy(); @@ -192,19 +179,15 @@ pub fn fillRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32) void { } pub fn fillRectangleEx(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32) void { - renderRectangle(self, x, y, w, h, skew_x, shaderProgram.color); + renderRectangle(self, x, y, w, h, skew_x, 0); } pub fn renderTexture(self: *Self, texture: Texture, x: i32, y: i32) void { - const programEnum = shaderProgram.texture; - - self.textures[self.vbo_index[@enumToInt(programEnum)] / 48] = texture; - renderRectangle(self, x, y, @intCast(i32, texture.width), @intCast(i32, texture.height), 0, programEnum); + self.textures[self.vbo_index / quadSize] = texture; + renderRectangle(self, x, y, @intCast(i32, texture.width), @intCast(i32, texture.height), 0, 1); } -fn renderRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32, program: shaderProgram) void { - const program_i = @enumToInt(program); - +fn renderRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32, unit: f32) void { var xf = @intToFloat(f32, x); var yf = @intToFloat(f32, y); var wf = @intToFloat(f32, w); @@ -212,35 +195,41 @@ fn renderRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32, pro const skew_x_offset = @intToFloat(f32, skew_x) * hf / 100; - const i = self.vbo_index[program_i]; + const i = self.vbo_index; const vertex_data = [_]f32{ xf + skew_x_offset, yf, // up-left self.color[0], self.color[1], self.color[2], self.color[3], - 0.0, 0.0, + 0, 0, + unit, xf + wf + skew_x_offset, yf, // up-right self.color[0], self.color[1], self.color[2], self.color[3], - 1.0, 0.0, + 1, 0, + unit, xf - skew_x_offset, yf + hf, // down-left self.color[0], self.color[1], self.color[2], self.color[3], - 0.0, 1.0, + 0, 1, + unit, xf + wf - skew_x_offset, yf + hf, // down-right self.color[0], self.color[1], self.color[2], self.color[3], - 1.0, 1.0, + 1, 1, + unit, xf + wf + skew_x_offset, yf, // up-right self.color[0], self.color[1], self.color[2], self.color[3], - 1.0, 0.0, + 1, 0, + unit, xf - skew_x_offset, yf + hf, // down-left self.color[0], self.color[1], self.color[2], self.color[3], - 0.0, 1.0, + 0, 1, + unit, }; - std.mem.copy(f32, self.vbo[program_i][i..], &vertex_data); - self.vbo_index[program_i] += vertex_data.len; + std.mem.copy(f32, self.vbo[i..], &vertex_data); + self.vbo_index += vertex_data.len; } pub const OutputSize = struct { width: c_int, height: c_int }; diff --git a/src/shaders/texture.frag b/src/shaders/texture.frag index e25c68a..9d5b4f3 100644 --- a/src/shaders/texture.frag +++ b/src/shaders/texture.frag @@ -1,9 +1,17 @@ #version 330 core -in vec2 texcoord; in vec4 color; +in vec2 texCoord; +in float texId; + uniform sampler2D tex; void main(){ - gl_FragColor = texture(tex, texcoord) * color; + vec4 finalColor = color; + + if (int(texId) == 1) { + finalColor *= texture(tex, texCoord); + } + + gl_FragColor = finalColor; } diff --git a/src/shaders/texture.vert b/src/shaders/texture.vert index c6225f7..57fec25 100644 --- a/src/shaders/texture.vert +++ b/src/shaders/texture.vert @@ -2,14 +2,17 @@ layout (location = 0) in vec2 pos; layout (location = 1) in vec4 vColor; +layout (location = 2) in vec2 vTexCoord; +layout (location = 3) in float vTexId; out vec4 color; -layout (location = 2) in vec2 vTexcoord; -out vec2 texcoord; +out vec2 texCoord; +out float texId; uniform mat4 mvp; void main() { - texcoord = vTexcoord; + texCoord = vTexCoord; color = vColor; + texId = vTexId; gl_Position = mvp * vec4((pos + vec2(0.5, 0.5)), 0, 1); }