Skip to content

Instantly share code, notes, and snippets.

@btipling
Last active October 30, 2023 21:30
Show Gist options
  • Save btipling/e18e3815f59beefcfc87be418913fa0e to your computer and use it in GitHub Desktop.
Save btipling/e18e3815f59beefcfc87be418913fa0e to your computer and use it in GitHub Desktop.
opengl triangle with zig-gamedev
const std = @import("std");
const zsdl = @import("libs/zig-gamedev/libs/zsdl/build.zig");
const zopengl = @import("libs/zig-gamedev/libs/zopengl/build.zig");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "hellotriangle",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const zsdl_pkg = zsdl.package(b, target, optimize, .{});
const zopengl_pkg = zopengl.package(b, target, optimize, .{});
zsdl_pkg.link(exe);
zopengl_pkg.link(exe);
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
// in /src/main.zig
const std = @import("std");
const sdl = @import("zsdl");
const gl = @import("zopengl");
pub fn main() !void {
_ = sdl.setHint(sdl.hint_windows_dpi_awareness, "system");
try sdl.init(.{ .audio = true, .video = true });
defer sdl.quit();
const gl_major = 3;
const gl_minor = 3;
try sdl.gl.setAttribute(.context_profile_mask, @intFromEnum(sdl.gl.Profile.core));
try sdl.gl.setAttribute(.context_major_version, gl_major);
try sdl.gl.setAttribute(.context_minor_version, gl_minor);
try sdl.gl.setAttribute(.context_flags, @as(i32, @bitCast(sdl.gl.ContextFlags{ .forward_compatible = true })));
const window = try sdl.Window.create(
"zig-gamedev: minimal_sdl_gl",
sdl.Window.pos_undefined,
sdl.Window.pos_undefined,
600,
600,
.{ .opengl = true, .allow_highdpi = true },
);
defer window.destroy();
const gl_context = try sdl.gl.createContext(window);
defer sdl.gl.deleteContext(gl_context);
try sdl.gl.makeCurrent(window, gl_context);
try sdl.gl.setSwapInterval(0);
try gl.loadCoreProfile(sdl.gl.getProcAddress, gl_major, gl_minor);
{
var w: i32 = undefined;
var h: i32 = undefined;
try window.getSize(&w, &h);
std.debug.print("Window size is {d}x{d}\n", .{ w, h });
sdl.gl.getDrawableSize(window, &w, &h);
std.debug.print("Drawable size is {d}x{d}\n", .{ w, h });
}
var vertices: [9]gl.Float = [9]gl.Float{
-0.7, -0.5, 0.0,
0.7, -0.5, 0.0,
0.0, 0.7, 0.0,
};
var VAO: gl.Uint = undefined;
gl.genVertexArrays(1, &VAO);
gl.bindVertexArray(VAO);
var VBO: gl.Uint = undefined;
gl.genBuffers(1, &VBO);
gl.bindBuffer(gl.ARRAY_BUFFER, VBO);
gl.bufferData(gl.ARRAY_BUFFER, vertices.len * @sizeOf(gl.Float), &vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 3 * @sizeOf(gl.Float), null);
gl.enableVertexAttribArray(0);
var e = gl.getError();
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
var vertexShaderSource: [:0]const u8 = @embedFile("triangle.vs");
std.debug.print("vertexShaderSource: {s}\n", .{vertexShaderSource.ptr});
var vertexShader: gl.Uint = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, 1, &[_][*c]const u8{vertexShaderSource.ptr}, null);
gl.compileShader(vertexShader);
var success: gl.Int = 0;
gl.getShaderiv(vertexShader, gl.COMPILE_STATUS, &success);
if (success == 0) {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getShaderInfoLog(vertexShader, 512, &logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{s}\n", .{infoLog[0..i]});
return;
} else {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getShaderInfoLog(vertexShader, 512, &logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("INFO::SHADER::VERTEX::LINKING_SUCCESS\n{s}\n", .{infoLog[0..i]});
}
var fragmentShaderSource: [:0]const u8 = @embedFile("triangle.fs");
std.debug.print("fragmentShaderSource: {s}\n", .{fragmentShaderSource.ptr});
var fragmentShader: gl.Uint = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, 1, &[_][*c]const u8{fragmentShaderSource.ptr}, null);
gl.compileShader(fragmentShader);
gl.getShaderiv(fragmentShader, gl.COMPILE_STATUS, &success);
if (success == 0) {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getShaderInfoLog(fragmentShader, 512, &logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{s}\n", .{infoLog[0..i]});
return;
} else {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getShaderInfoLog(vertexShader, 512, logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("INFO::SHADER::FRAGMENT::LINKING_SUCCESS\n{s}\n", .{infoLog[0..i]});
}
var shaderProgram: gl.Uint = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
e = gl.getError();
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
gl.linkProgram(shaderProgram);
gl.getProgramiv(shaderProgram, gl.LINK_STATUS, &success);
if (success == 0) {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getProgramInfoLog(shaderProgram, 512, &logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("ERROR::SHADER::PROGRAM::LINKING_FAILED\n{s}\n", .{infoLog[0..i]});
return;
} else {
var infoLog: [512]u8 = undefined;
var logSize: gl.Int = 0;
gl.getProgramInfoLog(shaderProgram, 512, &logSize, &infoLog);
var i: usize = @intCast(logSize);
std.debug.print("INFO::SHADER::PROGRAM::LINKING_SUCCESS {d}\n{s}\n", .{ i, infoLog[0..i] });
}
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
e = gl.getError();
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
std.debug.print("program set up \n", .{});
main_loop: while (true) {
var event: sdl.Event = undefined;
while (sdl.pollEvent(&event)) {
if (event.type == .quit) {
break :main_loop;
} else if (event.type == .keydown) {
if (event.key.keysym.sym == .escape) break :main_loop;
}
}
gl.clearBufferfv(gl.COLOR, 0, &[_]f32{ 0.2, 0.4, 0.8, 1.0 });
gl.useProgram(shaderProgram);
e = gl.getError();
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
gl.bindVertexArray(VAO);
e = gl.getError();
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
gl.drawArrays(gl.TRIANGLES, 0, 3);
if (e != gl.NO_ERROR) {
std.debug.print("error: {d}\n", .{e});
return;
}
sdl.gl.swapWindow(window);
}
}
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
@btipling
Copy link
Author

btipling commented Oct 29, 2023

Built with

$ zig version
0.12.0-dev.1319+aecdf6ad5
$ git submodule status
 7341c5d33564ef3c2c4c85b8384219540e106fd7 libs/zig-gamedev (v0.5.0-2868-g7341c5d3)

@btipling
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment