diff --git a/assets/cubyz/shaders/graphics/Circle.fs b/assets/cubyz/shaders/graphics/Circle.fs new file mode 100644 index 00000000..01a64b8e --- /dev/null +++ b/assets/cubyz/shaders/graphics/Circle.fs @@ -0,0 +1,19 @@ +#version 330 + +layout (location=0) out vec4 frag_color; + +flat in vec4 color; +in vec2 unitPosition; + +// Like smooth step, but with linear interpolation instead of s-curve. +float linearstep(float edge0, float edge1, float x) { + return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); +} + +void main(){ + float distSqr = sqrt(dot(unitPosition, unitPosition)); + float delta = fwidth(distSqr)/2; + float alpha = linearstep(1+delta, 1-delta, distSqr); + frag_color = color; + frag_color.a *= alpha; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Circle.vs b/assets/cubyz/shaders/graphics/Circle.vs new file mode 100644 index 00000000..7750993c --- /dev/null +++ b/assets/cubyz/shaders/graphics/Circle.vs @@ -0,0 +1,29 @@ +#version 330 core + +layout (location=0) in vec2 vertex_pos; + +flat out vec4 color; +out vec2 unitPosition; + + +//in pixel +uniform vec2 center; +uniform float radius; +uniform vec2 screen; + +uniform int circleColor; + + +void main() { + + // Convert to opengl coordinates: + vec2 position_percentage = (center + vertex_pos*radius)/screen; + + vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); + + color = vec4((circleColor & 0xff0000)>>16, (circleColor & 0xff00)>>8, circleColor & 0xff, (circleColor>>24) & 255)/255.0; + + unitPosition = vertex_pos; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Image.fs b/assets/cubyz/shaders/graphics/Image.fs new file mode 100644 index 00000000..51840172 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Image.fs @@ -0,0 +1,11 @@ +#version 330 + +layout (location=0) out vec4 frag_color; +uniform sampler2D image; + +flat in vec4 fColor; +in vec2 uv; + +void main() { + frag_color = texture(image, uv) * fColor; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Image.vs b/assets/cubyz/shaders/graphics/Image.vs new file mode 100644 index 00000000..72baf42a --- /dev/null +++ b/assets/cubyz/shaders/graphics/Image.vs @@ -0,0 +1,26 @@ +#version 330 core + +layout (location=0) in vec2 vertex_pos; + +out vec2 uv; +flat out vec4 fColor; + +//in pixel +uniform vec2 start; +uniform vec2 size; +uniform vec2 screen; + +uniform int color; + +void main() { + + // Convert to opengl coordinates: + vec2 position_percentage = (start + vertex_pos*size)/screen; + + vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); + + fColor = vec4((color & 0xff0000)>>16, (color & 0xff00)>>8, color & 0xff, (color>>24) & 255)/255.0; + uv = vertex_pos; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Line.fs b/assets/cubyz/shaders/graphics/Line.fs new file mode 100644 index 00000000..feb40e64 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Line.fs @@ -0,0 +1,11 @@ +#version 330 + +layout (location=0) out vec4 frag_color; + +flat in vec4 color; + +uniform sampler2D texture_sampler; + +void main() { + frag_color = color; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Line.vs b/assets/cubyz/shaders/graphics/Line.vs new file mode 100644 index 00000000..befa8dad --- /dev/null +++ b/assets/cubyz/shaders/graphics/Line.vs @@ -0,0 +1,26 @@ +#version 330 core + +layout (location=0) in vec2 vertex_pos; + +flat out vec4 color; + + +//in pixel +uniform vec2 start; +uniform vec2 direction; +uniform vec2 screen; + +uniform int lineColor; + + +void main() { + + // Convert to opengl coordinates: + vec2 position_percentage = (start + vertex_pos*direction)/screen; + + vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); + + color = vec4((lineColor & 0xff0000)>>16, (lineColor & 0xff00)>>8, lineColor & 0xff, (lineColor>>24) & 255)/255.0; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Rect.fs b/assets/cubyz/shaders/graphics/Rect.fs new file mode 100644 index 00000000..64dcc011 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Rect.fs @@ -0,0 +1,9 @@ +#version 330 + +layout (location=0) out vec4 frag_color; + +flat in vec4 color; + +void main(){ + frag_color = color; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Rect.vs b/assets/cubyz/shaders/graphics/Rect.vs new file mode 100644 index 00000000..415e9e89 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Rect.vs @@ -0,0 +1,26 @@ +#version 330 core + +layout (location=0) in vec2 vertex_pos; + +flat out vec4 color; + + +//in pixel +uniform vec2 start; +uniform vec2 size; +uniform vec2 screen; + +uniform int rectColor; + + +void main() { + + // Convert to opengl coordinates: + vec2 position_percentage = (start + vertex_pos*size)/screen; + + vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); + + color = vec4((rectColor & 0xff0000)>>16, (rectColor & 0xff00)>>8, rectColor & 0xff, (rectColor>>24) & 255)/255.0;; +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Text.fs b/assets/cubyz/shaders/graphics/Text.fs new file mode 100644 index 00000000..0a343ce6 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Text.fs @@ -0,0 +1,37 @@ +#version 330 + +layout (location=0) out vec4 frag_color; + +in vec2 frag_face_pos; +in vec4 color; + +uniform sampler2D texture_sampler; + +//in pxls +uniform vec4 texture_rect; +uniform vec2 fontSize; +uniform int fontEffects; + +vec2 convert2Proportional(vec2 original, vec2 full){ + return vec2(original.x/full.x, original.y/full.y); +} + + +void main(){ + vec4 texture_rect_percentage = vec4(convert2Proportional(texture_rect.xy, fontSize), convert2Proportional(texture_rect.zw, fontSize)); + vec2 texture_position = vec2( + texture_rect_percentage.x+ + frag_face_pos.x*texture_rect_percentage.z + , + texture_rect_percentage.y+ + frag_face_pos.y*texture_rect_percentage.w + ); + if ((fontEffects & 0x01000000) != 0) { // make it bold in y by sampling more pixels. + vec2 pixel_offset = 1/fontSize; + frag_color = color*max(texture(texture_sampler, texture_position), + texture(texture_sampler, texture_position + vec2(0, 0.5f/fontSize.y))); + } else { + frag_color = color*texture(texture_sampler, + texture_position); + } +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/Text.vs b/assets/cubyz/shaders/graphics/Text.vs new file mode 100644 index 00000000..fd0ea3e8 --- /dev/null +++ b/assets/cubyz/shaders/graphics/Text.vs @@ -0,0 +1,42 @@ +#version 330 + +layout (location=0) in vec2 in_vertex_pos; +layout (location=1) in vec2 face_pos; + +out vec2 frag_face_pos; +out vec4 color; + + +//in pixel +uniform vec4 texture_rect; +uniform vec2 scene; +uniform vec2 offset; +uniform vec2 fontSize; +uniform float ratio; +uniform int fontEffects; + +uniform float alpha; + + +vec2 convert2Proportional(vec2 original, vec2 full) { + return vec2(original.x/full.x, original.y/full.y); +} + + +void main() { + vec2 vertex_pos = in_vertex_pos; + vec2 position_percentage = convert2Proportional(offset*ratio, scene); + vec2 size_percentage = convert2Proportional(vec2(texture_rect.z, texture_rect.w)*ratio, scene); + if ((fontEffects & 0x02000000) != 0) { // italic + vertex_pos.x += vertex_pos.y/texture_rect.z; + } + + //convert glyph coords to opengl coords + vec4 rect = vec4(position_percentage, size_percentage); + + vec2 position = vec2(rect.x+vertex_pos.x*rect.z, -rect.y+vertex_pos.y*rect.w)*2+vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); + frag_face_pos = face_pos; + color = vec4(vec3((fontEffects & 0xff0000)>>16, (fontEffects & 0xff00)>>8, fontEffects & 0xff)/255.0, alpha); +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/graph.fs b/assets/cubyz/shaders/graphics/graph.fs new file mode 100644 index 00000000..dbbd81d1 --- /dev/null +++ b/assets/cubyz/shaders/graphics/graph.fs @@ -0,0 +1,9 @@ +#version 430 + +layout (location=0) out vec4 frag_color; + +uniform vec3 lineColor; + +void main() { + frag_color = vec4(lineColor, 1); +} \ No newline at end of file diff --git a/assets/cubyz/shaders/graphics/graph.vs b/assets/cubyz/shaders/graphics/graph.vs new file mode 100644 index 00000000..84722879 --- /dev/null +++ b/assets/cubyz/shaders/graphics/graph.vs @@ -0,0 +1,25 @@ +#version 430 core + +//in pixel +uniform vec2 start; +uniform vec2 dimension; +uniform vec2 screen; +uniform int points; +uniform int offset; + +layout(std430, binding = 4) buffer _data +{ + float data[]; +}; + + +void main() { + float x = gl_VertexID; + float y = -data[(gl_VertexID+offset)%points]; + // Convert to opengl coordinates: + vec2 position_percentage = (start + dimension*vec2(x/points, y))/screen; + + vec2 position = vec2(position_percentage.x, -position_percentage.y)*2 + vec2(-1, 1); + + gl_Position = vec4(position, 0, 1); +} \ No newline at end of file diff --git a/src/graphics.zig b/src/graphics.zig index dc1ef240..c831ab12 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -2,6 +2,10 @@ /// Also contains some basic 2d drawing stuff. const std = @import("std"); +const Vec4i = @import("vec.zig").Vec4i; +const Vec2f = @import("vec.zig").Vec2f; + +const Window = @import("main.zig").Window; const Allocator = std.mem.Allocator; @@ -14,19 +18,317 @@ fn fileToString(allocator: Allocator, path: []const u8) ![]u8 { return file.readToEndAlloc(allocator, std.math.maxInt(usize)); } -pub fn init() void { +pub const Draw = struct { + var color: i32 = 0; + var clip: ?Vec4i = null; + pub fn setColor(newColor: u32) void { + color = @bitCast(i32, newColor); + } + + /// Returns the previous clip. + pub fn setClip(newClip: Vec4i) ?Vec4i { + const oldClip = clip; + clip = newClip; + var clipRef: *Vec4i = &clip.?; + if(oldClip == null) { + c.glEnable(c.GL_SCISSOR_TEST); + } else { + if (clipRef.x < oldClip.x) { + clipRef.z -= oldClip.x - clipRef.x; + clipRef.x += oldClip.x - clipRef.x; + } + if (clipRef.y < oldClip.y) { + clipRef.w -= oldClip.y - clipRef.y; + clipRef.y += oldClip.y - clipRef.y; + } + if (clipRef.x + clipRef.z > oldClip.x + oldClip.z) { + clipRef.z -= (clipRef.x + clipRef.z) - (oldClip.x + oldClip.z); + } + if (clipRef.y + clipRef.w > oldClip.y + oldClip.w) { + clipRef.w -= (clipRef.y + clipRef.w) - (oldClip.y + oldClip.w); + } + } + c.glScissor(clipRef.x, clipRef.y, clipRef.z, clipRef.w); + return oldClip; + } + + /// 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.x, clipRef.y, clipRef.z, clipRef.w); + } else { + c.glDisable(c.GL_SCISSOR_TEST); + } + } + + // ---------------------------------------------------------------------------- + // Stuff for fillRect: + var rectUniforms: struct { + screen: c_int, + start: c_int, + size: c_int, + rectColor: c_int, + } = undefined; + var rectShader: Shader = undefined; + var rectVAO: c_uint = undefined; + var rectVBO: c_uint = undefined; + + fn initRect() void { + rectShader = Shader.create("assets/cubyz/shaders/graphics/Rect.vs", "assets/cubyz/shaders/graphics/Rect.fs") catch Shader{.id = 0}; + rectUniforms = rectShader.bulkGetUniformLocation(@TypeOf(rectUniforms)); + var rawData = [_]f32 { + 0, 0, + 0, 1, + 1, 0, + 1, 1, + }; + + c.glGenVertexArrays(1, &rectVAO); + c.glBindVertexArray(rectVAO); + c.glGenBuffers(1, &rectVBO); + c.glBindBuffer(c.GL_ARRAY_BUFFER, rectVBO); + c.glBufferData(c.GL_ARRAY_BUFFER, rawData.len*@sizeOf(f32), &rawData, c.GL_STATIC_DRAW); + c.glVertexAttribPointer(0, 2, c.GL_FLOAT, c.GL_FALSE, 2*@sizeOf(f32), null); + c.glEnableVertexAttribArray(0); + } + + fn deinitRect() void { + rectShader.delete(); + c.glDeleteVertexArrays(1, &rectVAO); + c.glDeleteBuffers(1, &rectVBO); + } + + pub fn rect(pos: Vec2f, dim: Vec2f) void { + rectShader.bind(); + + c.glUniform2f(rectUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height)); + c.glUniform2f(rectUniforms.start, pos.x, pos.y); + c.glUniform2f(rectUniforms.size, dim.x, dim.y); + c.glUniform1i(rectUniforms.rectColor, color); + + c.glBindVertexArray(rectVAO); + c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); + } + + // ---------------------------------------------------------------------------- + // Stuff for drawLine: + var lineUniforms: struct { + screen: c_int, + start: c_int, + direction: c_int, + lineColor: c_int, + } = undefined; + var lineShader: Shader = undefined; + var lineVAO: c_uint = undefined; + var lineVBO: c_uint = undefined; + + fn initLine() void { + lineShader = Shader.create("assets/cubyz/shaders/graphics/Line.vs", "assets/cubyz/shaders/graphics/Line.fs") catch Shader{.id = 0}; + lineUniforms = lineShader.bulkGetUniformLocation(@TypeOf(lineUniforms)); + var rawData = [_]f32 { + 0, 0, + 1, 1, + }; + + c.glGenVertexArrays(1, &lineVAO); + c.glBindVertexArray(lineVAO); + c.glGenBuffers(1, &lineVBO); + c.glBindBuffer(c.GL_ARRAY_BUFFER, lineVBO); + c.glBufferData(c.GL_ARRAY_BUFFER, rawData.len*@sizeOf(f32), &rawData, c.GL_STATIC_DRAW); + c.glVertexAttribPointer(0, 2, c.GL_FLOAT, c.GL_FALSE, 2*@sizeOf(f32), null); + c.glEnableVertexAttribArray(0); + } + + fn deinitLine() void { + lineShader.delete(); + c.glDeleteVertexArrays(1, &lineVAO); + c.glDeleteBuffers(1, &lineVBO); + } + + pub fn line(pos1: Vec2f, pos2: Vec2f) void { + lineShader.bind(); + + c.glUniform2f(lineUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height)); + c.glUniform2f(lineUniforms.start, pos1.x, pos1.y); + c.glUniform2f(lineUniforms.direction, pos2.x - pos1.x, pos2.y - pos1.y); + c.glUniform1i(lineUniforms.lineColor, color); + + c.glBindVertexArray(lineVAO); + c.glDrawArrays(c.GL_LINE_STRIP, 0, 2); + } + + // ---------------------------------------------------------------------------- + // Stuff for drawRect: + // Draw rect can use the same shader as drawline, because it essentially draws lines. + var drawRectVAO: c_uint = undefined; + var drawRectVBO: c_uint = undefined; + + fn initDrawRect() void { + var rawData = [_]f32 { + 0, 0, + 0, 1, + 1, 1, + 1, 0, + }; + + c.glGenVertexArrays(1, &drawRectVAO); + c.glBindVertexArray(drawRectVAO); + c.glGenBuffers(1, &drawRectVBO); + c.glBindBuffer(c.GL_ARRAY_BUFFER, drawRectVBO); + c.glBufferData(c.GL_ARRAY_BUFFER, rawData.len*@sizeOf(f32), &rawData, c.GL_STATIC_DRAW); + c.glVertexAttribPointer(0, 2, c.GL_FLOAT, c.GL_FALSE, 2*@sizeOf(f32), null); + c.glEnableVertexAttribArray(0); + } + + fn deinitDrawRect() void { + c.glDeleteVertexArrays(1, &drawRectVAO); + c.glDeleteBuffers(1, &drawRectVBO); + } + + pub fn rectOutline(pos: Vec2f, dim: Vec2f) void { + lineShader.bind(); + + c.glUniform2f(lineUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height)); + c.glUniform2f(lineUniforms.start, pos.x, pos.y); // Move the coordinates, so they are in the center of a pixel. + c.glUniform2f(lineUniforms.direction, dim.x - 1, dim.y - 1); // The height is a lot smaller because the inner edge of the rect is drawn. + c.glUniform1i(lineUniforms.lineColor, color); + + c.glBindVertexArray(lineVAO); + c.glDrawArrays(c.GL_LINE_LOOP, 0, 5); + } + + // ---------------------------------------------------------------------------- + // Stuff for fillCircle: + var circleUniforms: struct { + screen: c_int, + center: c_int, + radius: c_int, + circleColor: c_int, + } = undefined; + var circleShader: Shader = undefined; + var circleVAO: c_uint = undefined; + var circleVBO: c_uint = undefined; + + fn initCircle() void { + circleShader = Shader.create("assets/cubyz/shaders/graphics/Circle.vs", "assets/cubyz/shaders/graphics/Circle.fs") catch Shader{.id = 0}; + circleUniforms = circleShader.bulkGetUniformLocation(@TypeOf(circleUniforms)); + var rawData = [_]f32 { + -1, -1, + -1, 1, + 1, -1, + 1, 1, + }; + + c.glGenVertexArrays(1, &circleVAO); + c.glBindVertexArray(circleVAO); + c.glGenBuffers(1, &circleVBO); + c.glBindBuffer(c.GL_ARRAY_BUFFER, circleVBO); + c.glBufferData(c.GL_ARRAY_BUFFER, rawData.len*@sizeOf(f32), &rawData, c.GL_STATIC_DRAW); + c.glVertexAttribPointer(0, 2, c.GL_FLOAT, c.GL_FALSE, 2*@sizeOf(f32), null); + c.glEnableVertexAttribArray(0); + } + + fn deinitCircle() void { + circleShader.delete(); + c.glDeleteVertexArrays(1, &circleVAO); + c.glDeleteBuffers(1, &circleVBO); + } + + pub fn circle(center: Vec2f, radius: f32) void { + circleShader.bind(); + + c.glUniform2f(circleUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height)); + c.glUniform2f(circleUniforms.center, center.x, center.y); // Move the coordinates, so they are in the center of a pixel. + c.glUniform1f(circleUniforms.radius, radius); // The height is a lot smaller because the inner edge of the rect is drawn. + c.glUniform1i(circleUniforms.circleColor, color); + + c.glBindVertexArray(circleVAO); + c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); + } + + // ---------------------------------------------------------------------------- + // Stuff for drawImage: + // Luckily the vao of the regular rect can used. + var imageUniforms: struct { + screen: c_int, + start: c_int, + size: c_int, + image: c_int, + color: c_int, + } = undefined; + var imageShader: Shader = undefined; + + fn initImage() void { + imageShader = Shader.create("assets/cubyz/shaders/graphics/Circle.vs", "assets/cubyz/shaders/graphics/Circle.fs") catch Shader{.id = 0}; + imageUniforms = imageShader.bulkGetUniformLocation(@TypeOf(imageUniforms)); + } + + fn deinitImage() void { + imageShader.delete(); + } + + pub fn boundImage(pos: Vec2f, dim: Vec2f) void { + imageShader.bind(); + + c.glUniform2f(imageUniforms.screen, @intToFloat(f32, Window.width), @intToFloat(f32, Window.height)); + c.glUniform2f(imageUniforms.start, pos.x, pos.y); + c.glUniform2f(imageUniforms.size, dim.x, dim.y); + c.glUniform1i(imageUniforms.color, color); + + c.glBindVertexArray(rectVAO); + c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); + } + +// // ---------------------------------------------------------------------------- +// // TODO: Stuff for drawText: +// +// private static CubyzFont font; +// private static float fontSize; +// public static void setFont(CubyzFont font, float fontSize) { +// Graphics.font = font; +// Graphics.fontSize = fontSize; +// } +// +// /** +// * Draws a given string. +// * Uses TextLine. +// * @param x left +// * @param y top +// * @param text +// */ +// public static void drawText(float x, float y, String text) { +// text = String.format("#%06x", 0xffffff & color) + text; // Add the coloring information. +// TextLine line = new TextLine(font, text, fontSize, false); +// line.render(x, y); +// } +}; + +pub fn init() void { + Draw.initCircle(); + Draw.initDrawRect(); + Draw.initImage(); + Draw.initLine(); + Draw.initRect(); } pub fn deinit() void { - + Draw.deinitCircle(); + Draw.deinitDrawRect(); + Draw.deinitImage(); + Draw.deinitLine(); + Draw.deinitRect(); } pub const Shader = struct { id: c_uint, fn addShader(self: *const Shader, filename: []const u8, shader_stage: c_uint) !void { - const source = try fileToString(std.heap.page_allocator, filename); + const source = fileToString(std.heap.page_allocator, filename) catch |err| { + std.log.warn("Couldn't find file: {s}", .{filename}); + return err; + }; defer std.heap.page_allocator.free(source); const ref_buffer = [_] [*c]u8 {@ptrCast([*c]u8, source.ptr)}; const shader = c.glCreateShader(shader_stage); diff --git a/src/main.zig b/src/main.zig index 00628a92..b6d7dac8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,6 +2,8 @@ const std = @import("std"); const graphics = @import("graphics.zig"); +const Vec2f = @import("vec.zig").Vec2f; + pub const c = @cImport ({ @cInclude("glad/glad.h"); @cInclude("GLFW/glfw3.h"); @@ -56,6 +58,12 @@ pub const Window = struct { width = @intCast(u31, newWidth); height = @intCast(u31, newHeight); } + fn glDebugOutput(_: c_uint, typ: c_uint, _: c_uint, severity: c_uint, length: c_int, message: [*c]const u8, _: ?*const anyopaque) callconv(.C) void { + if(typ == c.GL_DEBUG_TYPE_ERROR or typ == c.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR or typ == c.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR or typ == c.GL_DEBUG_TYPE_PORTABILITY or typ == c.GL_DEBUG_TYPE_PERFORMANCE) { + std.log.err("OpenGL {}:{s}", .{severity, message[0..@intCast(usize, length)]}); + @panic("OpenGL error"); + } + } }; fn init() !void { @@ -65,6 +73,9 @@ pub const Window = struct { return error.GLFWFailed; } + if(@import("builtin").mode == .Debug) { + c.glfwWindowHint(c.GLFW_OPENGL_DEBUG_CONTEXT, 1); + } c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 4); c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 3); @@ -79,6 +90,13 @@ pub const Window = struct { return error.GLADFailed; } c.glfwSwapInterval(1); + + if(@import("builtin").mode == .Debug) { + c.glEnable(c.GL_DEBUG_OUTPUT); + c.glEnable(c.GL_DEBUG_OUTPUT_SYNCHRONOUS); + c.glDebugMessageCallback(GLFWCallbacks.glDebugOutput, null); + c.glDebugMessageControl(c.GL_DONT_CARE, c.GL_DONT_CARE, c.GL_DONT_CARE, 0, null, c.GL_TRUE); + } } fn deinit() void { @@ -120,6 +138,11 @@ pub fn main() !void { graphics.init(); defer graphics.deinit(); + c.glEnable(c.GL_CULL_FACE); + c.glCullFace(c.GL_BACK); + c.glEnable(c.GL_BLEND); + c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA); + while(c.glfwWindowShouldClose(Window.window) == 0) { { // Check opengl errors: const err = c.glGetError(); @@ -130,6 +153,22 @@ pub fn main() !void { c.glfwSwapBuffers(Window.window); c.glfwPollEvents(); c.glViewport(0, 0, Window.width, Window.height); + c.glClearColor(1, 1, 0, 1); + c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); + { // Render the game + c.glEnable(c.GL_DEPTH_TEST); + // TODO + } + + { // Render the GUI + c.glDisable(c.GL_DEPTH_TEST); + + graphics.Draw.setColor(0xff0000ff); + graphics.Draw.rect(Vec2f{.x = 100, .y = 100}, Vec2f{.x = 200, .y = 100}); + graphics.Draw.circle(Vec2f{.x = 200, .y = 200}, 59); + graphics.Draw.setColor(0xffff00ff); + graphics.Draw.line(Vec2f{.x = 0, .y = 0}, Vec2f{.x = 1920, .y = 1080}); + } } std.log.info("Hello zig.", .{});