#Foundations - Learning Graphics Programming with the Zig Programming language

1 messages Β· Page 1 of 1 (latest)

delicate delta
#

My attempt to build a voxel engine taught me a lot, but it also taught me that I don't really know enough just yet. I'm starting fresh, with just a triangle. My aim is to hopefully build a game engine just for the purpose of learning and fun, not for anyone to actually use.

My repo: https://github.com/btipling/foundations

Even writing this triangle using Jaker's Modern OpenGL guide (https://github.com/fendevel/Guide-to-Modern-OpenGL-Functions), that I had previously read, I learned things that I was doing wrong and was confused about in my game.

Anyway, I'm reading the following books and recording notes and building things based on what I learn in them or elsewhere:

https://foundationsofgameenginedev.com/
https://www.mathfor3dgameprogramming.com/
https://www.gameenginebook.com/
https://athena.ecs.csus.edu/~gordonvs/textC2E.html
https://athena.ecs.csus.edu/~gordonvs/textC3E.html
https://essentialmath.com/book.htm
https://www.gamemath.com/

I kind of like having a thread on this server, it's a fun way share what I'm doing and keeps me motivated to keep going. It's very basic stuff for most people, I'm sure. I really like doing this stuff and I like this server so going to keep at it.

I'm going to be sticking to latest nightly zig and avoid all zig dependencies and just work with more stable C/C++ deps to avoid managing zig versioning issues and to learn and use the same resources this community uses.

GitHub

Exercises for Foundations of Game Engine Development in zig plus extra things for whatever I want to do to learn graphics programming - btipling/foundations

delicate delta
#

going through the Computer Graphics Programming in OpenGL with C++ book, I kind of like function overloading in C++, it's not something I miss in zig, it just seems nice

#

been going through the examples and implementing them

#

in zig however

delicate delta
#

the first 30-page chapter of https://essentialmath.com/book.htm is entirely about floating point representations and has explained so many issues I had been running into, this is a really good book

#

the not doing direct comparison of floating point numbers, man I bet that was a problem I was running into in my voxel game that I could not understand with my third person camera approaching 0

#

in the x or z direction when y was 0

delicate delta
#

I like how a dot product in zig is just @reduce(.Add, v1 * v2)

#

I also like how I can validate with tests as I refresh my understanding of linear algebra

#

pub fn dotProduct(v1: anytype, v2: anytype) @TypeOf(v1[0]) {
    const T = @TypeOf(v1);
    const K = @TypeOf(v2);
    switch (@typeInfo(T)) {
        .Vector => |VT| switch (@typeInfo(K)) {
            .Vector => |VM| if (VT.len != VM.len) @compileError("mismatched vector dimension") else return @reduce(.Add, v1 * v2),
            else => @compileError("second input must be a vector"),
        },
        else => {},
    }
    @compileError("first input must be a vector");
}

test dotProduct {
    const a_v1: vec2 = .{ 4, 6 };
    const a_v2: vec2 = .{ -3, 7 };
    const ae: f32 = 30;
    try std.testing.expectEqual(ae, dotProduct(a_v1, a_v2));

    const b_v1: vec3 = .{ 3, -2, 7 };
    const b_v2: vec3 = .{ 0, 4, -1 };
    const be: f32 = -15;
    try std.testing.expectEqual(be, dotProduct(b_v1, b_v2));

    // Geometric tests
    // perpendicular dot product produces a 0:
    const c_v1: vec3 = .{ 2, 0, 0 };
    const c_v2: vec3 = .{ 0, 4, 0 };
    const ce: f32 = 0;
    try std.testing.expectEqual(ce, dotProduct(c_v1, c_v2));

    // same direction vectors produce a positive value
    const d_v1: vec3 = .{ 2, 0, 0 };
    const d_v2: vec3 = .{ 4, 0, 0 };
    try std.testing.expect(dotProduct(d_v1, d_v2) > 0);

    // opposite direction vectors produce a negative value
    const e_v1: vec3 = .{ 2, 0, 0 };
    const e_v2: vec3 = .{ -4, 0, 0 };
    try std.testing.expect(dotProduct(e_v1, e_v2) < 0);
}

delicate delta
#
    // dot product projection scales by the same factor as scaling the vector
    const f_v1: vec3 = .{ 3, -2, 7 };
    const f_v2: vec3 = .{ 0, 4, -1 };
    const f_scale: f32 = 5;
    try std.testing.expectEqual(dotProduct(f_v1, mul(f_scale, f_v2)), dotProduct(f_v1, f_v2) * f_scale);
    try std.testing.expectEqual(dotProduct(mul(f_scale, f_v1), f_v2), dotProduct(f_v1, f_v2) * f_scale);
#

:D

#

idk it's fun

#

    // if both vectors are unit vectors the projection of eiter on the other has the same length
    const g_v1: vec3 = .{ 3, -2, 7 };
    const g_v2: vec3 = .{ 0, 4, -1 };
    try std.testing.expectEqual(
        dotProduct(normalize(g_v1), normalize(g_v2)),
        dotProduct(normalize(g_v2), normalize(g_v1)),
    );
#

oh they don't have to be the same length to be commutative

delicate delta
#

Me right now

delicate delta
delicate delta
#

all my work on this so far has mostly been building out the math library, recently added decomposing vector projection and conversion to polar/spherical coordinates, just as I go through the books, and get a better understanding, write out some math code and tests

#

eventually I should get to building more interesting things

#

it's a lot of time reading and taking notes, the notes I'm not adding to my repo due to copyright

delicate delta
#

working some vector math visualizations

#

gonna make it a little bit better

delicate delta
#

I know super basic but still kind of cool, add one vector to the end of another then create a third vector from their sum and negate it and place it at the head of the new origin and goes directly to the origin of the first vector. Just cool to build a thing to do that visually and see it

#

except the window and of course dear imgui, everything I'm doing is all from scratch, my own math, my own everything. I can't do 3D, transforms or camera yet or mouse interaction or any of it yet I haven't build any of that. Zero tutorials, zero copy pasted code, it's all from first principles. This is all just vector math, no matrices atm

delicate delta
#

back to reading, for now

delicate delta
#

It's really cool when I learn a new math thing, add a test to my math library to check it and the new test confirms that thing I learned


    // The result of a decomposition are perpendicular and parallel vectors that add up to the orignal vector.
    const b_v1: vec3 = .{ 2, -5, 8 };
    const b_q: vec3 = .{ 1, 0, 0 };
    const b_res = decomposeProjection(b_v1, b_q);
    try std.testing.expectEqual(b_v1, add(b_res.proj, b_res.perp));
ivory verge
#

there is this scene from the "Hackers" movie

#

where cereal arrives late to the party

delicate delta
#

is this the movie with Angelina Jolie

#

I think I saw it once in the 90s

#

my favorite early hackers movie is Sneakers with Ben Kingsley and River Phoenix

ivory verge
#

yeah that one πŸ™‚

#

Sneakers is also one of my favorite movies

delicate delta
#

it's so good

ivory verge
#

i really need to give zig an actual try

delicate delta
#

I really like it, I really don't want to write any C, C++ or C# or rust and still get pretty good non-gc, lowish level type programming in

#

I had a bunch of false starts with C++ projects that never went anywhere it just wasn't fun, and this is a personal hobby

#

I've learned a lot from the zig developers who work on zig and the community, I've never done much of this type of programming before

#

it's a bit of a fixed cost to learn a new thing and decide if it's for you

#

the negatives are a lot of casting, no operator overloading, a newish eco system, and backwards breaking changes landing pretty frequently unless you stick with stable

#

but the positives are really good imo

ivory verge
#

hehe

#

every language has its pros and cons

#

i want C# without the managed part, or rather i want C++ with C#'s base class library, but also i dont want beeflang, because you are kind of forced to use their shitty custom IDE

delicate delta
#

the other thing that's nice is that anything anyone makes in zig, other people excited about zig are excited to learn about it, so no project is ever ignored

ivory verge
#

yeah

#

i noticed that on the zig discord

#

the only boring thing there so far is kristoff's boring streams lol where he only talks on stream and not writes any code, despite the title saying "working on xxx"

delicate delta
#

it's a cool community

#

lol

#

I haven't watched his streams much, he runs the sycl community (software you can love) which a lot of the zig community overlaps with

ivory verge
#

sycl is an unfortunate acronym

delicate delta
#

lol

ivory verge
#

khronos uses it too

delicate delta
#

yes

ivory verge
#

maybe its because of that heh

#

and ofc i love unvestigate's stuff

delicate delta
#

we've talked about it before #634812978994085888 message

#

it's pretty funny

ivory verge
#

xD

delicate delta
#

I kinda just jumped in with zig and made console hang man game for my first thing, then did a snake game, then went started with LOGL, saw I could draw a cube and thought wow now I can make minecraft and ran into every problem you would have predicted

#

kind of starting over now, but I am excited to do more GP with zig

ivory verge
#

once i have a somewhat useful renderer with my c++ thing, i will try to rewrite it in zig

delicate delta
#

nice, I hope that's fun, I think it would be

ivory verge
#

its 3700 loc in free floating functions of c++ goodness all in a main.cpp atm

delicate delta
#

I think zig increases LOC numbers

#

it's a little lower level than C or C++

ivory verge
#

im not afraid of typing, its 125kb already hehe

delicate delta
ivory verge
#

im just stuck in figuring out how to load a scene somewhat properly and not just be able to load 1 model and basically have a glorified modelviewer

delicate delta
#

yes I've been following the EngineKit thread, it's been interesting, I understand maybe 25% of it

ivory verge
#

haha

ivory verge
delicate delta
#

yes have to manually flush, manually allocate and free memory, one of the goals is to avoid hiding complexity and potential errors behind abstractions

ivory verge
#

similar to disposable pattern in c#

#

when you implement a class which handles low levelisms, like bitmaps, sockets or files or whatever OS handle, then you need to manage those too

delicate delta
#

yes

ivory verge
#

btw, we talked about Hackers the other day. For some very weird reason i find the German voices and dub much better fitting

#

the original one sounds like a tv show but not like a professional one, more like someone follows them around with a camera kind of thing

#

its weird

delicate delta
#

whonst du in Deutschland?

ivory verge
#

: D

#

i live in germany atm, ye

delicate delta
#

I was born in Whilemshaven

ivory verge
#

and i do speak it natively

delicate delta
#

I used to

ivory verge
#

i thought you were afrikaans πŸ˜›

delicate delta
#

oh because swartkrans?

ivory verge
#

swart could also be icelandic

#

but yeah

delicate delta
#

I use that because I studied archaeology in university and it's a famous site in the study of early hominids

ivory verge
#

ah cool

delicate delta
#

idk, I think a lot of people picked their online names at my age at college

ivory verge
#

and it is south african apparently hehe

delicate delta
#

ya

ivory verge
#

baie lekker

delicate delta
#

I thought you were in the UK

ivory verge
#

i lived in .za

delicate delta
#

oh I see

#

I've never been south of the equator

#

I should rewatch Hackers

ivory verge
#

oi

#

and im also mentioning hackers again because i also just put it on again

wild ember
#

@delicate delta is blockens on hiatus? Or is this a rewrite of it?

queen hinge
delicate delta
#

this is not a rewrite, this is like a playground for learning, I hope some kind of engine comes out of it or maybe it can be a precursor

delicate delta
#

I've gotten through some more reading and have added some matrices math https://github.com/btipling/foundations/blob/main/src/foundations/math/matrix.zig

I took advantage of some zig comptime to have loops at comptime and not write out all the things, I'm just interested in working math I understand and not looking for highly optimized, this is all for learning right now. When something doesn't work, like pulling frustum planes out of a perspective I want the math to be understandable.

Anyway here's my matrix multiplication zig code with some inline comptime stuff

pub fn mxm(a: matrix, b: matrix) matrix {
    const amt = transpose(a);
    var rv: matrix = undefined;
    comptime var column: usize = 0;
    inline while (column < 4) : (column += 1) {
        rv.columns[column] =  .{
            vector.dotProduct(amt.columns[0], b.columns[column]),
            vector.dotProduct(amt.columns[1], b.columns[column]),
            vector.dotProduct(amt.columns[2], b.columns[column]),
            vector.dotProduct(amt.columns[3], b.columns[column]),
        };
    }
    return rv;
}
ivory verge
#

horrible name though

delicate delta
#

It's going to be awhile before any of the books I am reading simultaneously get to projections, but I think I'll just do a couple of demos that do budget projections by just dividing the coordinate space

delicate delta
#

there's no overloading in zig

#

so I have mxv, mxm mxs, and I could just make a mul that does comptime reflection but this is just like my personal code

#

what would you call it I guess?

wild ember
#

No operator overloading in zig?

delicate delta
#

nope

wild ember
#

Ouch

delicate delta
#

no hidden abstractions in zig is a primary goal

#

of the language

wild ember
#

Hmm ok

delicate delta
#

this is an example of zig being a little bit lower level of a language I guess

wild ember
#

I'll avoid airing my opinions here froge_love

delicate delta
#

:P

#

I agree A * B * C in C++ is way more readable than mul(mul(A, B), C)

#

but then you have all the other stuff you get with C++

#

like destructors that flush and hide syscall errors when that fails

#

I'm going to go outside of the beaten paths and have column major matrices, left handed coordinate system, Xup it's going to be just totally custom

#

my final transform will just always be fixing all that to NDC in the shader

delicate delta
#

my books all go off on tangents after matrices before getting to projections, ray tracing in one, bezier curves in another, it's kind of annoying wanting to read these front to back

ivory verge
#

no operator overloading is not the worst thing

#

but mxv mxs etc is weird πŸ™‚

#

id just do MatrixMultiply or VectorTransform or VectorScale or otherway around TransformVector, ScaleVector and MultiplyMatrix etc

#

or in snek_case

delicate delta
#

I like transformVector scaleMatrix and transformMatrix actually

#

thank you

ivory verge
#

np πŸ™‚

#

you could also transformNormal

#

for homogeneous/affine vectors

delicate delta
#

surface normals?

ivory verge
#

yeah, or any "direction"

delicate delta
#

I haven't gotten to normals yet

#

right

#

I see you mean vectors

ivory verge
#

transformvector for points/"positions"

delicate delta
#

right

ivory verge
#

yeah

delicate delta
#

I think the very mathy books I am reading consider a surface normal as a specific kind of vector that is perpendicular to a plane

#

I'm going to take a break from reading and do some code thing, I need to do that prevent burnout fuck

#

just small projects related to what I'm reading

ivory verge
#

: )

main escarp
#

drive by comment: your hello triangle in preview blends in srgb

#

i.e. it's cringe and wrong

#

ur welcome

delicate delta
#

srgb?

main escarp
#

yes

#

the middle of triangle is too dark

#

it's not 0.5, 0.5, 0.5

delicate delta
#

I just hard coded some random colors

main escarp
#

but 0.5^2, 0.5^2, 0.5^2

#

yes

delicate delta
#

oh ok

main escarp
#

is this gl

delicate delta
#

thank you, no that's good feedback

main escarp
#

bro forgor glEnable(srgb) πŸ’€

delicate delta
#

I've never heard of srgb before lol

#

I will look it up

#

please keep driving by I learned stuff thank you np πŸ™

delicate delta
#

way better

#

jfc

#

GL_FRAMEBUFFER_SRGB is the thing to enable

#

yeah

#

no contest, thanks @main escarp

main escarp
#

ofc turn it off if you're rendering something like a normal map or whatever

#

tbh idk how framebuffer srgb works thonk

delicate delta
#

I can enable it and disable it whenever

main escarp
#

can you have some attachments srgb and others unorm

delicate delta
#

I have no idea

#

I think I just set some properties in my code and enable on draws?

main escarp
#

idk

#

I don't like how gl does this

delicate delta
#

fuck I just have to read about linear colorspace now too

#

great

main escarp
#

you should ask in opengl about this probably

#

the thing that concerns me

delicate delta
#

ah it's covered in one of my books

main escarp
#

at least in certain other apis I'm pretty sure it's possible to be rendering to one attachment in srgb, and to other in unorm

delicate delta
#

I just haven't gotten to it yet

main escarp
#

but I don't immediately see how you'd do that in gl

#

(I don't know gl)

#

so you should ask in #opengl about this stuff more

delicate delta
#

it seems to me that it just a global that dictates what colorspace a fragment shader is writing to and you can turn it on or off

#

I bet I can draw two triangles one in one color space and one in the other

#

that would prove the concept right

main escarp
#

the thing I'm considering

#

how are you supposed to do deferred rendering or whatever

#

where you have color attachment that's supposed to be srgb, and normal and other stuff which absolutely should not be srgb

delicate delta
#

oh I see some documentation on srgb attachments

#

GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING

#

I've never done anything with attachments so I don't really even know what they are I'm completely new to it

queen hinge
#

You could also just enable srgb on the window context for glfw

#

I believe

queen hinge
delicate delta
wild ember
delicate delta
#

nice

wild ember
#

You are just rendering to the backbuffer rn?

#

As in no FBO

delicate delta
#

I didn't know anything about this two seconds ago

#

so I was just reading and drew some triangles and directly enabling it per draw right now

wild ember
#

Best to just leave framebuffer_srgb enabled unless you have some very specific reason not to

delicate delta
#

that's what my book said too

#

it's like a full chapter on color math I think

#

haven't gotten to it yet

wild ember
#

If you set the fbo format correctly it will just do the right thing

#

But you probably aren't at fbos yet?

delicate delta
#

no not yet, still doing basic linear algebra math πŸ˜…

#

I'm reading a bunch of different books all at once

wild ember
#

Good learn that stuff real goodπŸ‘

delicate delta
#

yup

wild ember
#

Feel free to ask questions from us, but it seems you already are froge_love

delicate delta
#

I got the books I'm working listed at the top of the thread

#

reading a chapter at a time from each

wild ember
#

Are you using a math lib?

delicate delta
#

@ivory verge would it be possible to please pin the top thread πŸ™ thank you so much

delicate delta
wild ember
#

Is there some kind of zGLM?

delicate delta
#

there's zmath, but I can just also use GLM in zig

#

the zig compiler can compile C

#

and C++

#

I need a C extern wrapper around any C++ is all

wild ember
delicate delta
#

nice, yes my problem in blockens was trying to extract the frustum planes and not able to really understand what I was doing

wild ember
#

I can show you mine if you're interested

#

For frustum planes

delicate delta
#

oh, sure! I am not just there yet, but I realized this was something I can understand at a fundamental level if I just read up on it so that's what I'm doing

#

I also realized just lurking on this server that there was a lot I didn't understand

#

this server is great

wild ember
#

This is the best discord server I've ever been on

queen hinge
delicate delta
#

it's a power that only a few may wield

wild ember
#

as promised my code for extracting frustom planes from the MVPM ```cpp
const float* const MVPM = mvpMatrix.getFloatArray();

vec4 a = vec4(MVPM[3], MVPM[7], MVPM[11], MVPM[15]);
vec4 b = vec4(MVPM[0], MVPM[4], MVPM[8], MVPM[12]);

frustum_planes[(size_t)clip::X_RIGHT] = a - b;
frustum_planes[(size_t)clip::X_RIGHT] /= frustum_planes[(size_t)clip::X_RIGHT].xyz().magnitude();

frustum_planes[(size_t)clip::X_LEFT] = a + b;
frustum_planes[(size_t)clip::X_LEFT] /= frustum_planes[(size_t)clip::X_LEFT].xyz().magnitude();

b = vec4(MVPM[1], MVPM[5], MVPM[9], MVPM[13]);

frustum_planes[(size_t)clip::Y_TOP] = a + b;
frustum_planes[(size_t)clip::Y_TOP] /= frustum_planes[(size_t)clip::Y_TOP].xyz().magnitude();

frustum_planes[(size_t)clip::Y_BOTTOM] = a - b;
frustum_planes[(size_t)clip::Y_BOTTOM] /= frustum_planes[(size_t)clip::Y_BOTTOM].xyz().magnitude();

b = vec4(MVPM[2], MVPM[6], MVPM[10], MVPM[14]);

frustum_planes[(size_t)clip::Z_FAR] = a - b;
frustum_planes[(size_t)clip::Z_FAR] /= frustum_planes[(size_t)clip::Z_FAR].xyz().magnitude();

frustum_planes[(size_t)clip::Z_NEAR] = a + b;
frustum_planes[(size_t)clip::Z_NEAR] /= frustum_planes[(size_t)clip::Z_NEAR].xyz().magnitude();```
delicate delta
#

thank you!

wild ember
#

this line frustum_planes[(size_t)clip::X_RIGHT] /= frustum_planes[(size_t)clip::X_RIGHT].xyz().magnitude(); is basically just normalizing based on the xyz part of the vec4 btw

delicate delta
#

this is the Gribb-Hartmann method way yes

wild ember
#

Oh I didn't know it had a name

delicate delta
#

that's what I tried, but I messed it up somehow in a way I didn't understand

#

I have a better understanding of planes now though

wild ember
#

Yeah so its like the plane equations where you have Ax + By + Cz = D

delicate delta
#

(size_t) is casting an enum to something you can index an array with?

wild ember
#

Yeah its a C++ism just ignore it lol

delicate delta
#

really cool thank you

#

I swiped it for my collection

#

unless you don't want me to

wild ember
#

the "clip" enum has uint8_t storage for reasons that I don't need to get into right now

wild ember
delicate delta
#

you are indexing columns or rows?

wild ember
#

Here I'm just using the actual float index, its stored exactly how GL matrices are stored

delicate delta
#

oh right you don't have 15 columns sorry

wild ember
#

No worries

#

One more thing, My engine is left handed (+Z forward, +Y up) but in this case I think its irrelevant

delicate delta
#

I'm going to do left handed too

#

I was actually thinking -X up just to be crazy, but subtracting to go up, hrmmm it's kinda weird

#

I think I might do it though

#

it costs fuel to go up

#

there you go, that's the narrative

wild ember
#

But why X?

#

X is usually left-right

#

I would kinda understand -Y up, since thats like raster coordinates

delicate delta
#

I just want it to be totally different, I got so hung up on coordinate system hacks in blockens with importing from gltf, following logl code, I barely understood what I was doing and I had real trouble, like swapping keys out to go left and right, I inverted my character model and and it walked backwards when I pressed forwards I just kept having to do weird stuff, so I just want to have a completely different coordinate system that's just mine and I always have to take anything I get from where else and convert it to what I have. I know it sounds weird, it's just going to force me to think about it

#

I mean I'm in a much better place now

#

I got really far with blockens with how little I knew tbh

wild ember
#

Ok one tip, make sure you are really sure about what coordinate system you are in at all times, that messed me up alot when I was starting out

delicate delta
#

yup

wild ember
#

when you start adding random negations to get things to work you know you done fucked up

delicate delta
#

that's what I did so I could walk my blender gltf export character forwards

#

and also I had to reverse the rotation animations

#

anyway, I understand it now though

#

everything I use will have to be converted to my weird coordinate system

wild ember
#

So you understand handedness, which is the most important part IMO

delicate delta
#

yes

wild ember
delicate delta
#

that's a cool chart

wild ember
#

I'm in the top left with Unity

queen hinge
#

Left handed z up

#

Wild how it’s literally just one

wild ember
#

The one is Unreal tho

#

lots of ppl use unreal

#

Most of the right handed ones look like they started as GL projects

#

Except Source, but it has lineage going back to the Quake engine, so I dunno maybe Quake was right handed?

#

D3D has always been left handed AFAIK

#

Unreal started in Glide, so I wonder if glide was left handed

#

Ok it seems like glide may have been Left handed Z up by default, mystery solved

delicate delta
delicate delta
#

I wanted to stop keep having to add to this switch so I resorted to zig comptime

#

before:

pub fn drawDemo(self: Demos, frame_time: f64) void {
    switch (self.ui_state.demo_current) {
        .point => self.point.draw(),
        .point_rotating => self.point_rotating.draw(frame_time),
        .triangle => self.triangle.draw(),
        .triangle_animated => self.triangle_animated.draw(frame_time),
        .math_vector_arithmetic => self.math_vector_arithmetic.draw(frame_time),
        .linear_colorspace => self.linear_colorspace.draw(frame_time),
        .cubes_animated => self.cubes_animated.draw(frame_time),
        else => {},
    }
}
#

after:

#
pub fn drawDemo(self: Demos, frame_time: f64) void {
    const idx = @intFromEnum(self.ui_state.demo_current);
    comptime var i: usize = 0;
    inline while (i < num_demos - 1) : (i += 1) {
        if (i == idx) {
            switch (self.demo_instances[@intFromEnum(self.ui_state.demo_current)]) {
                @as(demo_type, @enumFromInt(i)) => |d| d.draw(frame_time),
                else => {},
            }
        }
    }
}
#

now I can keep adding to my demo without having to update all the switches everywhere

#

it's basically at compile time making an if statement for each possible enum value and then the switch extracts the actual instance of the thing I can draw and it uses duck typing to infer that the value for that enum in the tagged union has a draw method

#

if there's a bug here where I forget to update num_demos or something it is a compile error, not a run time error

#

lol

#

I got it down to

#
pub fn drawDemo(self: Demos, frame_time: f64) void {
    switch (self.demo_instances[@intFromEnum(self.ui_state.demo_current)]) {
        inline else => |d| d.draw(frame_time),
    }
}
delicate delta
#
   // With `inline else` the function is explicitly generated
    // as the desired switch and the compiler can check that
    // every possible case is handled.
    inline else => |slice| slice.len,
delicate delta
#

I call these the sinister finger gun coordinates

#
pub inline fn leftHandedXUpToNDC() matrix {
    return .{
        .columns = .{
            // zig fmt: off
            .{  0,  1,  0,  0 },
            .{  0,  0,  1,  0 },
            .{  1,  0,  0,  0 },
            .{  0,  0,  0,  1 },
            // zig fmt: on
        },
    };
}
ivory verge
#

xD

delicate delta
#

I kind of like thinking about like vertices from like blender glft exports or whatever as just like alien invaders from outer space

#

they're vectors from a different vector space

#

they don't belong in my vector space, the numbers look like numbers in my coordinate system, but that's a lie

#

their coefficient basis vectors aren't the same as mine, they require a transformation, all linear transforms are a change of vectors from one vector space to another, a coordinate space change from one to another

#

it's like a magic spell you have to cast to make the vectors no longer be from the upside down, they. must be cleansed, or it's like there's gremlins in my engine

queen hinge
#

I-
wha KEKW

#

That first sentence has a lot of likes

delicate delta
#

fuck

#

I'll use a better gpt prompt next time

queen hinge
delicate delta
#

I'm nearly done with the pure math stuff, about to get visual in here man VISUAL

#

I just implemented a row echelon reduction to produce an inverse and next is a diagonalization to find the eigenvalues and then it's like actually using math to draw things, finally lol, three weeks later Oo

wild ember
#

Were you planning on doing quaternions?

delicate delta
#

yes

#

most of these books have that in a representing rotations chapter

#

some of them have combined it in an affine transformation section

#

when I mean pure math, like just pure linear algebra, at least rotations can be drawn, and aren't just tests I'm writing

wild ember
#

true

wild ember
#

you probably do want tests for your quaternions though

delicate delta
#

yes I write lots of tests as you can see ^^

wild ember
#

Yeah you seem much more disciplined at that than me

delicate delta
#

I'm still being lazy, I'm doing the implement this math thing in zig instead of doing the practice problems I think that's working out for me

wild ember
#

ehh whatever

delicate delta
#

I want to make cool stuff, but I have already learned so many useful things in the last few weeks

#

I think it's been very worth it

#

it's going to be applied soon

#

also, if I didn't write tests I don't think I would haven't gotten it right, because I had lots of bugs my tests found

#

I would go to wolfram alpha to get things that should work and see my tests would fail and I had to fix, but that also reinforced in my brain how it works

#

me today

wild ember
#

FLT_EPSILON

delicate delta
#

yeah I wrote my own then found out zig already had it and nearly identical

wild ember
#

or std::numeric_limits<float>::epsilon()

delicate delta
#

I wrote return @abs(v - k) <= epsilon * @max(@abs(v), @abs(k), 1);

#

and zig has return @abs(x - y) <= @max(@abs(x), @abs(y)) * tolerance;

#

I mean I based mine off my math book

#

I didn't reinvent it, but it was just cool to see it was the same zigwise

delicate delta
#

I'm just going to barrel down all the chapters until I'm done with perspective before I go crazy with rendering, I just need to get it out of the way, I've read at least one book's content about quaternions and will write some math there, I think I get that now, but it's just going to be heads down for a week or two or three of just reading. I am pretty much spending every spare minute I have reading. Once I'm done with the perspective it's all actually doing things though. Like lighting, shadowing, culling etc, then I'll have some stuff to actually do that is visible

#

once I get through it I'm done, I've learned so much already, like a lot. I understand how rotation matrices work now, like at a fundamental level, and how quaternion multiplication works, and why surface normals require the inverse transpose for non orthogonal matrices (because you need the dot product of the tangent and surface normal vectors to equal 0 and the inverse transpose is derived from the original vertices matrix and some algebraic simplification, etc

#

like

#

I even understand eigenvectors and diagonalization and and row echelon form and solving systems of linear equations, like this is all great stuff, and I get these chapters out of the way, I'm going to have a really solid foundation of understanding to solve problems later

#

I think this approach is better than just following LOGL tutorials O_o

delicate delta
#

going to start doing some interpolation soon

#

first I'll add the quaternion math tomorrow to my math library

delicate delta
ivory verge
#

icosahedron/geodesic next?

delicate delta
#

I don't know what those are :O

#

I'm just messing around trying to create things I can rotate with the quarternion math I will write

#

oh those are cool though

delicate delta
#

neat

ivory verge
#

thats the former, a 12?sider

#

and thats a geodesic

#

with the latter you dont get ugly pole regions like you usually have with "spheres"

delicate delta
#

neat

#

I like my sphere froge_sad

ivory verge
#

the latter can be nicely subdivided too for planetoids πŸ˜›

delicate delta
#

I'll need to figure out how to render those

#

I'm sure I can look it up

#

was just trying to figure it out myself :O

ivory verge
#

i have no idea on top of my head either, perhaps also via some polar to cartesian isms

delicate delta
#

I just got it wrong for about a few hours and then used renderdoc mesh viewer to find where all my bugs were

#

I don't know what I would do without renderdoc

ivory verge
#

its a super useful and underused tool πŸ™‚

delicate delta
#

geodesic is kind of mindblowing

ivory verge
#

they use it for constructing halfdomes

delicate delta
#

fun

ivory verge
#

noice

#

with slightly faster than pi speed : >

delicate delta
#

this is my quaternion code, I need to write tests still


pub fn multiplyQuaternions(q2: Quat, q1: Quat) Quat {
    const v1: vector.vec3 = .{ q1[1], q1[2], q1[3] };
    const v2: vector.vec3 = .{ q2[1], q2[2], q2[3] };
    const w = q1[0] * q2[0] - vector.dotProduct(v1, v2);
    var v = vector.mul(q1[0], v2);
    v = vector.add(v, vector.mul(q2[0], v1));
    v = vector.add(v, vector.crossProduct(v2, v1));
    return .{ w, v[0], v[1], v[2] };
}

pub fn identityQuat() Quat {
    return .{ 1, 0, 0, 0 };
}

pub fn inverseNormalizedQuat(q: Quat) Quat {
    return .{ q[0], -q[1], -q[2], -q[3] };
}

pub fn inverseQuat(q: Quat) Quat {
    const qn = vector.normalize(q);
    return inverseNormalizedQuat(qn);
}

pub fn rotateVectorWithNormalizedQuat(v: vector.vec3, q: Quat) vector.vec3 {
    const qw = q[0];
    const qx = q[1];
    const qy = q[2];
    const qz = q[3];

    const vx = v[0];
    const vy = v[1];
    const vz = v[2];

    const v_mul: f32 = 2.0 * (qx * vx + qy * vy + qz * vz);
    const cross_mul: f32 = 2.0 * qw;
    const p_mul = cross_mul * qw - 1.0;

    return .{
        p_mul * vx + v_mul * qx + cross_mul * (qy * vz - qz * vy),
        p_mul * vy + v_mul * qy + cross_mul * (qz * vx - qx * vz),
        p_mul * vz + v_mul * qz + cross_mul * (qx * vy - qy * vx),
    };
}

pub inline fn normalizedQuaternionToMatrix(q: Quat) matrix {
    const qw = q[0];
    const qx = q[1];
    const qy = q[2];
    const qz = q[3];

    const s: f32 = 2.0 / (qx * qx + qy * qy + qz * qz + qw * qw);

    const xs: f32 = s * qx;
    const ys: f32 = s * qy;
    const zs: f32 = s * qz;

    const wx = qw * xs;
    const wy = qw * ys;
    const wz = qw * zs;

    const xx = qx * xs;
    const xy = qx * ys;
    const xz = qx * zs;

    const yy = qy * ys;
    const yz = qy * zs;

    const zz = qz * zs;

    return .{
        .columns = .{
            .{
                1.0 - (yy + zz),
                xy + wz,
                xz - wy,
                0,
            },
            .{
                xy - wz,
                1.0 - (xx + zz),
                yz + wx,
                0,
            },
            .{
                xz + wy,
                yz - wx,
                1.0 - (xx + yy),
                0,
            },
            .{ 0, 0, 0, 1 },
        },
    };
}
delicate delta
#

I guess I need some conversion code, because how else am I going to use this

delicate delta
#

after writing some tests I did have to make a few changes

#

inverting a non-unit quat doesn't involve a normalization, to invert a non-unit quaternion you divide each component by its squared length so you don't change the quaternions magnitude

delicate delta
#

I think the tests are good enough, I'm really limited to what sorts of visualizations I can create until I've read through the perspective chapters

#

that's why all my actual visual things are so bare bones 2D looking, I do not have any perspective math yet

#

I will create some bezier curve visualization and interpolation or something after getting through this next chapter on interpolation

#

I think then it's barreling down until I finally get to something about perspective math, it's like 5 more chapters across 3 books before I'm done with all the needed math before I even get to anything about perspective

#

one chapter takes me about 2 or 3 days

queen hinge
#

How about rotors?

delicate delta
#

rotors?

queen hinge
#

I need to play with these myself for my engine tbh

#

Donno how much better they are than quats but I have been told they are better

delicate delta
#

ah

#

one of the books I'm reading actually hinted at the wedge product

#

I haven't gotten to it yet

#

that's Grassmann Algebra

queen hinge
#

I work a lot more with in practice than with reading up on stuff tbh

delicate delta
#

well I'm not going to remember any of this unless I use it

#

so I plan on putting it into practice

#

but I do want to understand it

#

I don't want to copy some equation and try to use an equation I don't understand

#

I didn't understand quaterions at all until this week

#

I was able to use a slerp GLSL function with quaternions without understanding any of it, but now I understand it

#

it's kind of nuts

queen hinge
#

As far as I care quats are math magic KEKW
They’re one of few things with vector math I know absolutely nothing about afaik

delicate delta
#

it is though

#

it's like rotating in 4D

queen hinge
#

Yea

delicate delta
#

adding a quaternion rotation to a vector involves two rotations that occur at the same time and you have to cancel one out

queen hinge
delicate delta
#

it's impossible to visualize

#

but the math works

#

it's literally though a q * v * q⁻¹ where you need an inverse to cancel out the second rotation

queen hinge
#

For stuff like quats
I tend to go for more of a conceptual understanding than an actual one

delicate delta
#

there's a bunch of 4D stuff that's come up, I think there was some other hyperplane math where you end up with a parallopipe which is basically a projection from a 4D shape

#

a 3D shape being a slice from a 4D shape of some kind

#

I forget what it was now

queen hinge
#

Matrices I actually understand perfectly on a how they work
I don’t remember the math between matrices
But the math between matrices and vectors makes perfect sense to me

delicate delta
#

it was like an aside in the book explaining some approach for converting from a matrix to some other representation I forget, it was just fun tor ead about and not useful

queen hinge
#

Affine decomposition, I think it is?

wild ember
#

One way I find that helps to think about quaternions is to think about them as encoding the same information as an axis + an angle

delicate delta
#

that might be it

#

yes

#

they're like a better version of an axis angle representation

#

that's actually how I create a quaternion in my code, from an axis angle

queen hinge
#

Yeah

#

I have that in my like
4 function quaternion helper for glsl

wild ember
#

Yeah its just instead of an angle its the cosine of half that angle and the axis is multiplied by the sin

delicate delta
#

oh right, and the reason given for it being half the angle is the 4D stuff

queen hinge
delicate delta
#

fancy

#

I didn't know you could do xxxx, I'm guessing that gives you a vec4 with just the x for each component?

#

cool

queen hinge
#

Arbitrarily did that one day and found that it worked
It does require at least some glsl version or an extension though, and I’m not sure which version/extension it is

#

I think gpu_shader5 for opengl?

#

donno

#

maybe I’m mixing it up with fma

delicate delta
#

I don't use any extensions, haven't needed to so far

#

but I haven't done anything interesting yet

queen hinge
#

What glsl version do you specify?

delicate delta
#

460

queen hinge
#

You most likely will not use an extension

#

By 460, pretty much all interesting extensions for opengl are already part of the spec

delicate delta
#

what systems do people target, besides macs, that don't have 460

queen hinge
#

Old devices that only support up to 330 that probably also support the glsl extensions

delicate delta
#

rotors seem cool, maybe I'll pull them in, I didn't know about them

delicate delta
#

I see

queen hinge
#

Modern MC uses GL32, which is why I choose 320 in specific

#

What MC uses is actually a pretty decent indicator of what can be considered legacy hardware tbh

delicate delta
#

I don't really expect many people to want to play anything I make, so I don't see the pain of worrying about it useful personally

wild ember
queen hinge
#

I do mean java edition, yes
And by modern mc, I mean modern versions of mcje

#

Like 1.20+

queen hinge
wild ember
#

Strong disagree there, MDI and DSA are a big win

queen hinge
#

I have no idea what those are KEKW

delicate delta
#

multidraw indirect

wild ember
#

also compute shaders?

queen hinge
#

Oh right compute shaders are 4x

#

Wait are they?

delicate delta
#

dsa avoids you having to bind

queen hinge
#

What does dsa stand for?

delicate delta
#

direct state access I think

wild ember
#

Direct State Access yeah

queen hinge
#

No idea what that is KEKW

wild ember
#

it makes your code much simpler, and often faster

queen hinge
#

So far I have yet to comprehend multidraw indirect

delicate delta
#

like using glVertexArrayElementBuffer

#

I really like it

#

I just create buffers now

#

multdirawindirect you like control what you draw all from the GPU

queen hinge
#

What the heck
Compute shaders are 4.3?

delicate delta
#

so you can like do occlusion culling based on previous frame

#

if it didn't render last frame you don't attempt to draw it on the next

#

you update a buffer on the GPU and MDI uses it

queen hinge
#

ah

delicate delta
#

I haven't used it personally

#

but I think that's how it works

#

I did use multidraw

queen hinge
#

But I’m trying to stick to GL33

#

I had to bump up the gl version the game requests in order to this as it stands

#

I don’t really wanna bump it all the way to 4X KEKW

delicate delta
#

hey if it works

queen hinge
#

I do plan to write the lines of code to support GL32
Shouldn’t be too much work

#

KEKW less work than making this support iris

wild ember
#

I have trouble finding cards that don't suport 4.6 tbh

queen hinge
#

But also less performant

#

I have talked to a person who has a GPU old enough that it doesn’t support GL3X, so they were stuck in older mc versions KEKW

delicate delta
#

this interpolation stuff is all new to me

#

it's going to take me a bit

#

it's got hermite curves and calculus

#

I gotta like write code as I read it I'm never going to understand it otherwise

#

basis functions and integrals

#

cool cool

#

I'm going to add some capabilities to do drag and drop so I can drop points and drag them to resize tangent vectors

#

and add some triangle strips to draw lines

#

I played around a bit in python with matplot but I want it in my zig

delicate delta
ivory verge
#

unreal engine clone incoming πŸ™‚

delicate delta
#

:P

#

I think that's Bevy at this point

ivory verge
#

i try to ignore webgpu/rust based things, im in a pool of enough distractions already hehe

delicate delta
#

I keep forgetting bevy is written in rust

#

oh I guess if I get this working I could write a node editor sorta

ivory verge
#

node editor for something specific?

delicate delta
#

no I thought maybe that's what you were joking about

#

since unreal is basically a node editor and I'm working on curved lines

ivory verge
#

ah when i mean UE clone i mean everything the whole thing, all the renderpasses and techniques in it

#

not just how you use the editor to make games hehe

queen hinge
#

oh if bevy's written in rust I guess I'm not using it

ivory verge
#

there is/was also some drama around its creation

#

with something called AngelEngine or something like that

queen hinge
#

rust is eh
something I'd rather avoid using

ivory verge
#

same

queen hinge
#

it's just
too aggressive in its memory model for me

#

I like my nullability and public static variables and manual memory management when I want it and not needing to worry about lifetimes

delicate delta
#

yup

queen hinge
#

manual memory management is sometimes nice
not usually
but sometimes

#

but rust is so far opposite to that that it becomes annoying again

delicate delta
#

Rust constrains me from writing code and solving problems the way my brain wants to solve them for the sake of it's safeguards, I hate it

#

it's good and great, I just don't want it personally

queen hinge
#

yeah

wild ember
#

Rust turns you into an insufferable evangelist if you use it long enough

#

πŸš€

ivory verge
#

hehe

#

im just too old already to learn yet another language

wild ember
#

C++ is my first and only love

delicate delta
queen hinge
#

java personally

ivory verge
#

my trainees try to hand me rust pills almost daily too

queen hinge
#

would be C# if not for ide choices

delicate delta
#

I have pamphlets

#

jk

ivory verge
#

c# ❀️

wild ember
#

OK you might be the first person I met who unironically likes java

delicate delta
#

I think zig is good for people who like C

#

I don't think it will make people who like C++ or C# or Java happy

#

although there are a subset of C++ people who seem to like zig

ivory verge
#

i want to take a look at zig more closely too

queen hinge
wild ember
#

It takes a very specific type of person to like C++

queen hinge
#

C++ is ok
but I run into undefined behavior a bit more often than I want to deal with

wild ember
#

UB froge_love

queen hinge
#

why do my std::strings corrupt always bleakekw

wild ember
#

What are you doing with them?

queen hinge
#

trying to use it
to store a string
in a struct

wild ember
#

And...

queen hinge
#

I don't know what more there is for me to say there KEKW

delicate delta
#

I just use []const u8 and avoid strings

queen hinge
#

I just use char* in C++ tbh

wild ember
#

OK im gonna stop talking about langs now to avoid further derailment

queen hinge
#

agreed

queen hinge
delicate delta
#

this thread is basically a language thread, it's intentionally like gamedev in zig so it's fine imo

#

like sharing what it's like to do graphics programming with zig and contrasting and comparing with other languages 100% on topic

queen hinge
#

lwjgl makes gamedev in java translate pretty nicely from C++
which is something I have noticed is NOT the case with C# libraries and that also pains me bleakekw

#

how's that in zig?

wild ember
#

Yeah but I don't think it's worth dunking on Lyzantra for their questionable string choices

queen hinge
#

there's a reason I don't write C++ often
which is because I use it in questionable ways frOK

wild ember
#

I will withhold the lecture

delicate delta
# queen hinge how's that in zig?

I don't think any object oriented type of thing translates nicely to zig, although there are some vtable implementations people have written. I personally do not like inheritance or OO. I like dependency injection and composition which you get with zig, it has duck typing with anytype and comptime generics

#

you can't hide struct properties in zig

queen hinge
#

inhertance is a pain if is used incorrectly

queen hinge
#

can't have the java enterprise convention nonsense if you don't have that

shy cosmos
#

don't let gob see this thread

#

(do you have this thing open source, I've never looked at zig source)

delicate delta
#

there are also no closures, so you can't hide data in zig easily, you can with an anyopaque I suppose, but yikes

delicate delta
queen hinge
#

random things are locked down that are useful to have not locked down
things are extensible in weird and unnecessary ways creating a maze of code
etc

ivory verge
#

java is a shit language though

#

when you come from c# at least

queen hinge
#

it is
but it's the language I like

ivory verge
#

java is 20 years behind, like c++

queen hinge
#

yep

ivory verge
#

and when you do enterprisey java, with spring its puke pure

#

but yeah, you use what you are comfy with

queen hinge
ivory verge
#

hehe, true

queen hinge
ivory verge
#

yeah

queen hinge
#

especially if you want to interact with a library written in an enterprisey way

ivory verge
#

if you mean all the FizzBuzz bs

queen hinge
ivory verge
#

yeah πŸ˜›

queen hinge
#

because that is a way people unironically end up writing code, unfortunately

ivory verge
#

it is what it is

#

i write my c# in a different way than my c++ shit

#

and i would write it in a java way if i used jaba

queen hinge
#

java is pretty similar to C#
the code styles of the two can largely transfer between the two
there are difference, yes
but for the most part skills from one apply to the other

delicate delta
#

last I checked you can just call functions in Java, they've made that more accessible, there's like nice syntax sugar for static functions

#

so I think if I wrote java it would look not very OOP

#

used to have to create a class wrapper scaffolding for single function non-OOP type code, and then Kotlin introduced a nice way to just have functions that weren't OOP methods in class wrappers and Java borrowed that or was inspired by it

shy cosmos
#

hmm I'm thinking about the language bikeshed and I almost never see people state what their criteria for "good" vs "bad" languages are

queen hinge
#

my main concern is the syntax and verbosity
which java fills pretty much perfectly to my liking
C# is close enough but the IDE choice and libraries makes me favor java

#

there's a lot about java that I don't like
but those things aren't my main concerns

shy cosmos
queen hinge
#

I like sorta a middle ground

#
        int loaded = 0;
```like
being forced to explicitly define a type for my variables
I cannot stand *not* doing that, and a lot of languages don't do that
shy cosmos
#

so type inference is a no-no?

queen hinge
#

yeah

shy cosmos
#

java has var tho innit

queen hinge
#

I have to type approximately the same amount with or without it because of the IDE's suggestions
but without it I can just see ah yes this is an integer at a moment's glance

queen hinge
#

I've seen maybe a total of 3 codebases that use it

shy cosmos
#

does that include mine for the prog3 exam's project kekkedsadge

delicate delta
#

zig has function parameter type inference via anytype which is basically ducktyped at compile time. it will check at compile time if you whatever you passed into a function that accepts an anytype can be used in a way the called function uses it

queen hinge
delicate delta
#

C++'s templates in zig is probably a combination comptime type and anytype although I'm not competent at C++ generics

shy cosmos
#

you can think of C++ templates as fancy macros

#

it really just instantiates the same thing with the type replaced

delicate delta
#
fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

vs

fn addFortyTwo(x: anytype) @TypeOf(x) {
    return x + 42;
}
queen hinge
#

also
modern java's standard libraries are getting less verbose
so like InputStream
you used to have to do some funky stuff with byte[]s to get good performance with those
now you just do byte[] data = is.readAllBytes(); and oh hey that works!
but you can still do the more verbose stuff with the byte[]s if you need to, which is another thing I like

delicate delta
#

anytype is ducktyping

#

comptime: T type is more like C++ templates

queen hinge
delicate delta
#

yes comptime is basically zig's version of macros, but it's not like a dumb preprocessor, it actually runs zig at compile time

shy cosmos
#

type inference comes in many shapes and forms

#

typing in general is a very complicated and convoluted field

delicate delta
#

var x = 5; that would be a comptime_int in zig

queen hinge
#

what's the opposite of type inference called KEKW
been trying to figure out a term for it for a while

#

does it even have a name

delicate delta
shy cosmos
#

I just call it explicit typing

#

(it's all math, always has been)

queen hinge
delicate delta
#

in C++ you have to use auto for type inference?

queen hinge
#

based on a bing search, it is explicit typing

shy cosmos
#

C++ has two kinds of type inference

#

"template argument deduction" which is what happens with auto and regular template instantiation
"placeholder expression type deduction" which is just decltype(expr) or decltype(auto)

#

the first one is both bad and good and the second one, would you believe it, is also both bad and good KEKW

delicate delta
#

I see, so either good or bad

shy cosmos
#

yeah, based on context and usage

delicate delta
#

is there possibility for UB in the case of bad

shy cosmos
#

of course

delicate delta
#

nice

ivory verge
#

trolly problem

delicate delta
#

zig will just fail to compile if you get the type inference wrong

queen hinge
#

so
something I tend to do
is sorta read my code based off keyword pattern rather than off the text

shy cosmos
#

most problems with type inference in C++ come because of declspec-qualifiers

#

which is the 18 different combinations of types you can have

delicate delta
#

18 different combinations is basically infinite

queen hinge
#

so I sorta look for a keyword pattern that might do what I want
and then I actually go and look through the code to evaluate if it is what I want or not

shy cosmos
#
&
&&
const&
const&&
const& noexcept
const&& noexcept
volatile& noexcept
volatile&& noexcept
const volatile& noexcept
const volatile&& noexcept
...
#

me when C++

delicate delta
#

oh boy

queen hinge
#

bleakekw what

shy cosmos
#

there's more

#

with function pointers, arrays of function pointers, member function pointers, nonstatic member pointers (and the cv-qualifications of those) bla bla

delicate delta
#

basic stuff

#

I don't have any concept of anything other than a draw function per frame for any demo at the moment, there's no ECS or any type of per frame set of operations

#

so it's all really primitive at the moment

delicate delta
delicate delta
#
fn initDemo(self: *Demos, dt: ui.ui_state.demo_type) void {
    self.demo_instance = switch (dt) {
        inline else => |dtag| @unionInit(ui.ui_state.demos, @tagName(dtag), std.meta.Child(
            std.meta.TagPayload(
                ui.ui_state.demos,
                dtag,
            ),
        ).init(self.allocator)),
    };
}
#

I just update these

pub const demo_type = enum(usize) {
    point,
    point_rotating,
    triangle,
    triangle_animated,
    cubes_animated,
    math_vector_arithmetic,
    linear_colorspace,
    circle,
    sphere,
    line,
};

pub const demos = union(demo_type) {
    point: *point,
    point_rotating: *point_rotating,
    triangle: *triangle,
    triangle_animated: *triangle_animated,
    cubes_animated: *cubes_animated,
    math_vector_arithmetic: *math_vector_arithmetic,
    linear_colorspace: *linear_colorspace,
    circle: *circle,
    sphere: *sphere,
    line: *line,
};
#

I am still manually adding navigation menu items for these

#

I should automate that also

#

based on the props of the type of demo

#

it now also fully wipes all the opengl state on the GPU when you switch between any of the demos

#

in order to draw lines and points as instance draws I have bee planning how to use buffers and having all the demos have their own buffers live at the same time didn't make sense

#

now everything is fully independent and can use all the resources

#

like I don't have to worry about running out of SSBOs because each thing has their own

#

I wonder if I should rename these to levels, it feels a little bit like it could be a levels thing in a game

#

maybe a scene actually

#

yeah I'm going to rename these to scenes

#

drawing lines with curves is kind of more work than I thought it would be, I can probably bikeshed the meshing to the degree I might bikeshed a voxel chunk mesh

#

I'm going to start with just brute force instanced triangles

#

and then make it better

#

one program for all the points, one program for all the lines, both in just one buffer, fully instanced draws

#

with drag and drop and updating partial buffers

delicate delta
#

ok I get nav menu items for my scenes for free now

#

I added a method like so to each of my scenes

#

pub fn navType() ui.ui_state.scene_nav_info {
    return .{
        .nav_type = .shape,
        .name = "Point",
    };
}
#

and then this code generates all the dear imgui menu items:


inline fn navMenuItems(self: *Nav, nav_type: ui.ui_state.scene_nav_type) void {
    inline for (std.meta.fields(ui.ui_state.scene_type)) |field| {
        const dt = @field(ui.ui_state.scene_type, field.name);
        switch (dt) {
            inline else => |dtag| {
                const ntfn: *const fn () ui.ui_state.scene_nav_info = @field(std.meta.Child(std.meta.TagPayload(
                    ui.ui_state.scenes,
                    dtag,
                )), "navType");
                const nav_info: ui.ui_state.scene_nav_info = @call(.auto, ntfn, .{});
                if (nav_info.nav_type == nav_type) {
                    if (c.igMenuItem_Bool(@ptrCast(nav_info.name), null, false, true)) {
                        self.app_scenes.setScene(dt);
                    }
                }
            },
        }
    }
}
#

for every scene

#

creates that top menu

delicate delta
#

also nice in zig is @offsetOf

#

    pub const attributeData = struct {
        position: [3]f32,
        color: [4]f32,
        normals: [3]f32 = .{ 0, 0, 0 },
    };
      
    c.glVertexArrayAttribFormat(vao, 0, 3, c.GL_FLOAT, c.GL_FALSE, @offsetOf(attributeData, "position"));
    c.glVertexArrayAttribFormat(vao, 1, 4, c.GL_FLOAT, c.GL_FALSE, @offsetOf(attributeData, "color"));
    c.glVertexArrayAttribFormat(vao, 2, 3, c.GL_FLOAT, c.GL_FALSE, @offsetOf(attributeData, "normals"));
granite bolt
#

Looks like rust a bit

#

Also are u swedish? BjΓΆrn, the viking

delicate delta
#

Nah, just American :/

delicate delta
#

heyyy I got building and debugging my zig engine in VS Code working

#

this is my launch.json

#
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(Windows) Launch",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/zig-out/bin/foundations.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "console": "externalTerminal"
        }
    ]
}
#

this is my tasks.json

#
{
    "version": "2.0.0",
    "tasks": [
      {
        "type": "shell",
        "label": "zig build project",
        "command": "zig",
        "args": [
            "build"
        ],
        "problemMatcher": [],
        "group": {
          "kind": "build",
          "isDefault": true
        },
        "detail": "Task generated manually."
      },
      
      {
        "type": "shell",
        "label": "zig run project",
        "command": "zig",
        "args": [
            "build",
            "run"
        ],
        "problemMatcher": [],
        "group": {
          "kind": "build",
          "isDefault": true
        },
        "detail": "Task generated manually."
      }
    ]
  }
#

nice being able to do all this with vs code now, don't need to use cli to build

delicate delta
ivory verge
#

sweet

delicate delta
#

it's not very exciting yet, it will be once I start drawing lines :P

#

all this work though isn't one off, it adds capabilities to the engine, now I can do instanced draws from any scenes, and I made a path toward fully generic vertex array objects that get defined based on the fields of the struct

#

the ability to pass in an anonymous struct and use std.meta.fields on it to define VAOs is pretty cool

delicate delta
#

getting used to x up is taking some time tbh

#
std.debug.print("moving point at index {d} to ({d}, {d})\n", .{ pi, x, z });
#

it's just so strange

#

it's good for me though, it builds character

#

I got a cool bug

#

accidental paint clone

#

I have no idea why some some are blue

#

I think that must be UB

#

I love being able to specify const on a pointer return type in zig froge_love

#
pub fn getReadOnly() ?*const Input {
    return input;
}

can't modify the returned input, generates a compile error

delicate delta
ivory verge
#

you could call it "zig-zag" πŸ˜›

delicate delta
#

That would be a fun project

#

I want to make a game but if I could live forever I would definitely make one of those

delicate delta
#

ok I'm done with this drag stuff, it's good enough, I changed it to only update the single's instance data for hover and drag with a subBufferUpdate instead of recreating the full program and sending the full buffer and switched to DYNAMIC_DRAW and I can barely tell the difference

#

time to draw lines I guess

delicate delta
#

I should probably debounce the drag

delicate delta
ivory verge
#

i can see BridgeBuilderPhysicsSimulator 2024 alreader

delicate delta
#

all that work on making good generic code around instancing last week really paid off

ivory verge
#

still using opengl?

delicate delta
#

it's trivial to add new programs that are instanced

#

yes

#

that's all I know lol

ivory verge
#

with glPointSize(10);? πŸ™‚

delicate delta
#

no those are triangles

ivory verge
#

ah

#

would have been my next question

delicate delta
#

it doesn't look like a line yet

#

I hard coded the segments per line regardless of length

#

and it should be quads, not triangles

#

so two triangles I guess per segment

#

and it should keep the old lines when I add additional points

#

I'm trying to avoid heap allocation for these things so there's going to be a max bound on number of line segments I think and a separate length variable I'll track

ivory verge
#

use a pool

delicate delta
#

what's that

ivory verge
#

a big blob of memory of fixed size

delicate delta
#

oh I see

ivory verge
#

or if you know you will never draw than 100k line segments, then allocate enough for 100k segments upfront

delicate delta
#

makes sense

ivory verge
#

and then you can decide how you want to handle edge cases, what happens if you add more or want more

#

you either allocate again, more space, or you dont, but start at 0 again, and overwrite existing line segments

#

like particles

delicate delta
#

that's great, I like that, thank you, I will do that

#

I really love when I learn a math thing, then build something using that math and it just works, it's amazing

ivory verge
#

geen ding nie

#

it gives me hope that at our age we can still learn shit

#

because i feel like im stagnating xD

delicate delta
#

right, slow down the brain cell decay

delicate delta
#

still just triangles

#

this would be a lot less interesting if it was just a single rectangle from point to point, I'm about to add curves

#

it's just this:

pub fn linear(t: f32, positions: []vector.vec4, times: []f32) vector.vec4 {
    std.debug.assert(times.len == positions.len);
    if (t < times[0]) return positions[0];
    if (t > times[times.len - 1]) return positions[positions.len - 1];
    var i: usize = 0;
    while (true) {
        if (t < times[i + 1]) break;
        if (i + 1 == times.len - 1) break;
        i += 1;
    }
    const t0: f32 = times[i];
    const t1: f32 = times[i + 1];
    const u: f32 = (t - t0) / (t1 - t0);
    const p1 = positions[i];
    const p2 = positions[i + 1];
    return vector.add(vector.mul(1.0 - u, p1), vector.mul(u, p2));
}
#
    const sp = math.interpolation.linear(t / 1_000.0, positions[0..self.num_points], times[0..self.num_points]);

and then I translate every instance

#

time to add tangents

queen hinge
#

certain things that are a few lines of code become pretty annoying to deal with in more low level apis like vulkan

#

and a decent amount of those are common things to do

delicate delta
#

yes I'm going to stick with OpenGL for a bit, I do want to at least do some vulkan tutorials to try and understand it

queen hinge
#

I'm making my game engine in vulkan
and for sake of working on UI code, I'm making an art program
so therefor I'm making an art program in vulkan KEKW

delicate delta
#

that's really cool, is your art program a pixel editor, or for vector art or like a blender?

queen hinge
#

I want it to be able to be used for low res and high res pixel art

#

ideally it's flexible so that I can do both pixel and vector

delicate delta
#

nice

queen hinge
#

but I'mma focus on pixel

delicate delta
#

it's frustrating in pixel apps to have shapes but then they just get rasterized right away, I just want to be able to manipulate them a bit

queen hinge
#

an idea I had that I wanna do is basically
all tools are LUA scripts and glsl files
fill bucket? glsl+lua
regular brush? glsl+lua
blah blah blah

delicate delta
#

very cool

queen hinge
#

mostly haven't been using beziers because of it froge_sad

delicate delta
#

I'm about to add some beziers to this thing

#

after hermite stuff

#

idk maybe hermite is enough though, I don't want to spend too much time on this I just wasn't understanding the text

delicate delta
#

I think it would be really fun to make an art program

queen hinge
#

there's, a surprising amount of work that goes into those things

delicate delta
#

yes

queen hinge
#

I'm considering using a tile system to reduce ram+vram usage

#

because in krita, you can theoretically make a 5tb layer using just two dots KEKW

delicate delta
#

a 5 what?

queen hinge
#

did I stutter?

delicate delta
#

what does the tb mean here? terabytes?

queen hinge
#

terabytes, yep

delicate delta
#

what kind of computer do you have?

queen hinge
#

notice: I say theoretically KEKW

delicate delta
queen hinge
#

I don't have enough disk space for that

#

I literally put down just two dots

#

neither of them are visible on the canvas

delicate delta
#

this is a program you made?

queen hinge
#

and it's 7GiB KEKW

queen hinge
delicate delta
#

oh

#

I was going to ask you how you made that UI

#

:P

queen hinge
#

GTK

delicate delta
#

ah

queen hinge
#

is what krita uses

delicate delta
#

Gobjects froghorror

queen hinge
#

or at least, I'm pretty sure it is

#

mine currently looks more like this

delicate delta
#

nice I like that red

#

how are you rendering your text?

queen hinge
#

I do not have text yet

delicate delta
#

oh you are writing this in java

queen hinge
#

yea

delicate delta
#

which version of jdk?

queen hinge
#

uh

delicate delta
#

er java version

#

my java is rusty

queen hinge
#

21

queen hinge
delicate delta
queen hinge
#

ah boy, awt

delicate delta
#

I don't know what any of that is anymore :P

#

10 years jfc

queen hinge
#

ok so
awt is the builtin UI/graphics stuff for java

#

it uh
old

#

KEKW there is no other nice way for me to put that

delicate delta
#

I'm actually not old at all

queen hinge
#

was calling awt old, not you KEKW
human age is far different from software age

#

basically; javax.swing is the newer of java.awt
but it's built directly ontop of awt in a weird plug and play way and this causes swing to have the same exact problems as awt itself
which is that, it's an old UI library that hasn't been modernized, so it feels extremely clunky to use it

#

also it is pretty much exclusively designed for 2d
if you wanna do 3d stuff, you pretty much have to go make a software raster
and awt/swing is already rasterized in software by default (with optional hardware raster support, which automatically enables itself if the window gets large enough)

queen hinge
#

as for actually rendering
I generate glyph atlases dynamically, and use instanced rendering to actually draw the glyphs

delicate delta
#

I remember that awt stuff to be really slow if I wanted to do anything interesting with it

#

I think that's when I learned about graphics apis but I didn't get into it much at the time

queen hinge
#

yeah awt is slow too
part of that is the software raster, part of that is awt itself

delicate delta
queen hinge
#

the hardware raster looks better than the software raster too froge_sad

delicate delta
#

that was also awt

queen hinge
#

mine was NOT efficient though KEKW

delicate delta
#

I don't know, I just did a computer sciency thing whenever I wanted to do interviewing for a new job

queen hinge
#

yours is defo better than mine

delicate delta
#

idk, I just looked it up on wikipedia I think

queen hinge
#

so apparently I've my program in the background scrolling through like 10 million elements I think while talking
it's like over halfway there KEKW

#

wait no

#

the code I just wrote is bugged

#

and made the scrollbar small KEKW

delicate delta
#

is this an instanced thing in vulkan

queen hinge
#

this is not instanced

#

I could technically set it up to do instancing
but that wouldn't really work out with how I'm currently doing it (I'm using the viewport to size the UI elements, so literally every single element has its own viewport setup)

delicate delta
#

you wrote own scrolling UI?

queen hinge
#

the most annoying thing with vulkan imo
is that in order to update a buffer, I have to end my renderpass, update the buffer, and start the renderpass again
it's not just that it's slower to not do that
not doing that causes undefined behavior

#

so I wanted to avoid dealing with buffers entirely for my UI

queen hinge
#

this surprises you or something?

delicate delta
#

no, was just wondering

#

I think a fully generic scrolling UI is a challenging project

queen hinge
#

way I did it
my scroll panel can hold anything
but it assumes that the thing it holds will automatically "pack" its size from infinite to whatever it needs

#

so in a scroll panel, only fixed sized elements can be used

#

eh that's not the right wording

#

elements that end up with a non-inifinite size even if they're recommended to use an infinite size

delicate delta
#

having worked with different UI libraries, I think my favorite was an early version of ios tables where you got an event whenever a row became visible

#

you basically write a function to be called to render a row

queen hinge
#

my UI elements have no idea where they are on screen KEKW

#

they know where they are relative to their parent
but they don't know what their parent is

delicate delta
#

yeah it's a hard problem

#

this was a table view though

#

not a generic scroll container

queen hinge
#
    @Override
    public void draw(UIGraphics uiGraphics) {
        super.draw(uiGraphics);
        for (Widget child : children) {
            if (!uiGraphics.checkBottom(child)) return;
            if (!uiGraphics.checkTop(child)) continue;
            uiGraphics.draw(child);
        }
    }```I may have a tendency to take forms of inspiration from minecraft
#

this is not at all how mc does its rendering
but the way mc does its UI rendering made me think a bit and decide hm, what if I make it so that all of the positioning is handled outside of the widget classes?

#

because it has like a GUIGraphics class which has a bunch of util methods, and is not at all used how my UIGraphics is used

delicate delta
#

looks like a clean approach

queen hinge
#

it's defo the cleanest approach I've had so far

#

what if I draw a million elements instead of trimming them out

delicate delta
#

you should make a community project thread

queen hinge
#

ah right my ui library trims it out automatically for me anyway

#

yeet the safeguard

#

ah right it still trims it out because the scissor would be 0 or negative sized KEKW

#

0 fps if I yeet that safeguard too πŸ‘

delicate delta
queen hinge
queen hinge
#

makes sense but for some reason I expected imgui to do some hijacking

delicate delta
#

you don't get it for free no

#

but I just have a single input handler used for the whole engine so I just a single place I need to check

delicate delta
#

added tangent vectors

#

now I just need to apply them to get the hermite curves

#

this has been so much work lol

ivory verge
#

@queen hinge the little gradient looks neat

#

is that an ImGui::Image? didnotread

queen hinge
queen hinge
ivory verge
#

no clue who mabox is

queen hinge
#

It’s a linux distribution

ivory verge
#

oooh

#

getting flashbacks from blackbox

queen hinge
#

backbox?

#

blackbox doesn’t seem to exist

#

After a decent bit of scrolling I have come to a facebook page of blackbox-os

ivory verge
#

blackbox window manager you silly goose

#

: )

queen hinge
#

Based on some googling
I get the feeling blackbox might be a fork of openbox

ivory verge
#

other way around

#

but same stuff yeah

queen hinge
#

oh, really?

ivory verge
#

Openbox is a free, stacking window manager for the X Window System, licensed under the GNU General Public License.[5] Originally derived from Blackbox[5] 0.65.0 (a C++ project), Openbox has been completely re-written in the C programming language and since version 3.0 is no longer based upon any code from Blackbox.

#

i remember flying bb4win back then around the 2000s and whenever my best friends and i met for LAN parties, the first day was sharing config files or customizing shit again πŸ˜„

queen hinge
#

I tend to use linux in VMs, so openbox being so minimal quickly became my preferred window manager
And then I stumbled across mabox and noticed that it happened to be configured such that the workflow I use for windows still applied, plus the additional stuff I had in my openbox workflow still exisfed

ivory verge
#

mabox looks interesting

#

i use arch btw

queen hinge
#

Is based on manjaro, which is based on arch

ivory verge
#

the manjaro part is concerning

queen hinge
#

I, personally haven’t had problems with that fact, but you’re not the first to tell me that

#

The only time I’ll use debian based stuff is for C++ development, because… debian makes installing libraries extremely easy

ivory verge
#

debian uses a lot of outdated stuff, but its a solid distro either way

wild ember
#

I used to use debian when I had to use linux, but lately I've been doing manjaro

#

I find debian's conservative update cycle actually infuriating sometimes

delicate delta
#

when I finish all of these books I'm going to get myself a framework 16 with some kind of linux on it

#

was thinking nixos

wild ember
delicate delta
#

if I can do wayland on it ok, idk maybe

wild ember
#

I still only use lunix when I have to though πŸ˜‰

queen hinge
#

lunix

ivory verge
#

correct spelling

delicate delta
#

yes I just want it to test games on amd gpu and linux

wild ember
delicate delta
#

also I'm so over this 4k screen on this underpowered laptop

queen hinge
#

speaking of which
I should test my UI library on AMD

ivory verge
#

you can send the 4k screen to me, if you are over it, bjorn

wild ember
#

I use this mini pc for AMD testing and it has all sorts of issues on windows but on manjaro its much better

queen hinge
#

UI framework works fine so far πŸ‘

delicate delta
ivory verge
#

ah hehe

wild ember
#

The mini-PC is sorta my steem decc proxy

ivory verge
#

i have a dell xps 15 9550 from 2016, also comes with a 4k screen heh, but i just 1080p it, because its just too smol

delicate delta
#

I'm not getting a 4k laptop again until it's like standard

wild ember
#

4k is pretty common now

delicate delta
#

on laptops?

#

a single triangle gets like 350fps

wild ember
#

I don't often use laptops but my latest thinkpad at work can with a 4k screen

delicate delta
#

in full screen

wild ember
#

I think every gamedev should use a 4k monitor, it forces you to optimize the game more

queen hinge
delicate delta
#

how to optimize one triangle

wild ember
#

don't upgrade ur gpu though

wild ember
queen hinge
#

I have a weird monitor

wild ember
#

wait till you have a real scene, like intel sponza or something

ivory verge
delicate delta
#

yes

queen hinge
delicate delta
#

I have to force the nvidia gpu on my project otherwise it uses the intel gpu

ivory verge
#

yeah

#

idk if you can do that in zig, but in c/c++ you can do this

wild ember
queen hinge
#

if you know with 100% certainty that it will be a performance critical region of code
go ahead and do some medium intensity optimizations off the bat
even then, don't go full send though

delicate delta
#

yeah I can do that

ivory verge
#

jake ninjaed it πŸ˜›

delicate delta
#

I can set c headers in zig with @cDefine

queen hinge
delicate delta
#

nah adjusting the display resolution makes everything worse, it has to just be default

queen hinge
#

mine's actually a 2k but I've turned it down to 1680x because everything is tiny elsewise

queen hinge
delicate delta
#

:P

ivory verge
#

i dont think cDefine is the same

queen hinge
#

oh
that
I don't think that's good for my eyes

#

too crispy

ivory verge
#

its true, once you go 4k you dont want to go back, 4k on a properly big screen that is

queen hinge
#

2k on a smaller-than-average-1080p monitor is horrid