#GrubStomper29's OpenGL Sandbox

1 messages Β· Page 2 of 1

night shoal
#

then mdi would be the next logical step ne?

gilded shell
#

Yeah it’s in my notes lol

#

the only thing I’m binding anymore is my ubos

night shoal
#

thats fine

gilded shell
#

yeah

#

if i profile and its killing me, i can just make an array

night shoal
#

there are extensions for nvidia from 15 years ago, which allow bindless buffers

gilded shell
#

i checked

#

im not sure amd supports those

night shoal
#

and you can also track the bind state on your side too, and only bind when it needs binding

gilded shell
#

right

night shoal
#

mdi + bindless textures as a base line

#

then frustum and hiz culling on gpu

gilded shell
#

yeah

night shoal
#

and then the next step would be nanite, where you split your shit into meshlets and do the same frustum/hiz culling

gilded shell
#

i went bindless now because id rather build off of it than have to change it later

night shoal
#

in my older engines i had a fallback to texture2darrays, so that i can debug in renderdoc, but might not worth the effort, but simply because i dont like nsight much

gilded shell
#

i dont mean for textures, im talking about geometry

night shoal
#

what do you mean

#

bindless buffers is pretty much out of question for opengl : >

#

unless you want to support nvidia hardware only

gilded shell
#

technically not bindless

#

but huge buffers with everything that are always bound

night shoal
#

ah yeah

#

megavertex/index/material/instance buffers

gilded shell
#

i dont want to write a meshlet generator then immediately refactor it to use megabuffers yeah

night shoal
#

libmeshopt will do the meshlettification : )

#

or libLVSTRI soon(tm)

gilded shell
#

at runtime?

night shoal
#

at model loading time

#

which isnt a hotpath

gilded shell
#

alright

night shoal
#

or as a preprocessing step, or even at build time if you want

gilded shell
#

okay good

#

i dont think writing my own would be out of the question though

night shoal
#

maybe later as an exercise to figure out that meshlettification stuff

gilded shell
#

it won’t be as elegant

night shoal
#

i also believe this is a rabbithole and will grant you a million dollhairs if you actually solve it for every mesh configuration there is

gilded shell
#

lol

night shoal
#

it always sounded like thats an actual maffematical problem or topological or whatever term, when lustri was talking about METIS and whatnot heh

gilded shell
#

my original plan was to tipsify sort the index buffer, then put sequential tris in a meshlet

#

the results looked good enough for high poly yet simple models like that dragon thing

#

but im sure it would fall apart with complex or low poly geometry

night shoal
#

i have not put any thought into meshlets myself yet

kind sparrow
#

Bindless textures doesn't improve performance on its own afaik

#

the point is to do larger batched draws

night shoal
#

yep theoretically they do improve performance, because you dont bind any texture anymore and have to group your meshes by material and whatnot

kind sparrow
#

oh yeah right

#

I forgot that texture switching itself can be a significant cost

#

for some reason I've never had that issue

night shoal
#

on the account of not having any textures going in your game ahem

kind sparrow
#

I do though lol

night shoal
#

hihi

#

those metal plates you can shoot at at the range πŸ˜›

#

just pulling your leg

kind sparrow
#

I make textures that are just solid colors as a pessimization so that later when I have real textures it doesn't cause any perf or memory issues

#

I have like 1024x1024 textures that are 3 blocks of solid color lol

night shoal
#

: ) absolutely nothing wrong with that

#

and probably a smarter idea anyway

kind sparrow
#

But yeah probably because I don't have a large enough number of different models yet

#

actually though I don't even batch by texture binding

#

so just not enough objects

night shoal
#

you just render what needs rendering neh?

#

in whatever order it comes in

#

as in, no batching

kind sparrow
#

I bin by pipeline

night shoal
#

ah

kind sparrow
#

and then just draw the objects naively

#

batching is implemented bespoke for systems that have a lot of objects

#

e.g. foliage

night shoal
#

yeah

#

rendering the 2 quads per grass tile would be insane as individual drawcalls heh

kind sparrow
#

if you think about it, environment stuff is almost always going to outweigh anything the player creates

night shoal
#

yeah

#

asteroid belts, whole planets, cities full of housing and whatnot, or otherwise terrain rocks and whatnotisms

kind sparrow
#

Yeah

night shoal
#

plus all the fluff which goes with it, decals and foliage

#

this madrigal guy keeps teasing me

#

with his little terrain and car fisiks arrangement

#

(i believe he works in the studio which made alan wake)

#

explains a lot of stuff πŸ™‚

kind sparrow
#

An average scene in the game is like,
trees/rocks/misc ground clutter: 100,000,000
items/gear/vehicles/etc: 100
buildings: 50
characters: 50

kind sparrow
night shoal
#

: )

#

i played a bit of dayz earlier again and kept gazing at the trees and grass and sky and the wind playing with all that shit

#

and pictured some vehicle driving around with wobbly suspension and antennae and whatnot

kind sparrow
#

haha

#

I'm taking over some structural dynamics sims at work rn so I am learning stuff that will potentially result in lots of wobbly suspension and antennae if I ever make it to SRS DLC #137

night shoal
#

ah sweet

#

bendy trusses and whatnot πŸ™‚

kind sparrow
#

in this case vibration analysis but yeah

night shoal
#

noice

#

also 3d visualizationisms involved?

kind sparrow
#

not yet beyond some debug 3D plotting I've done as a basic vis

#

but maybe I will later if I can justify spending time on it

#

otherwise the output is just plotting transfer functions and stuff

#

power spectral density

night shoal
#

your colleagues should hold on to their knickers then

#

when you drop the srs plugin for that thing : >

#

where you can walk around in that simulation and inspect values from a virtual camera, or even V R

kind sparrow
#

haha

night shoal
#

like they did when they build CERN

kind sparrow
#

I have actually used SRS code for work stuff lol

#

in small pieces

night shoal
#

i knew it

#

hehe

kind sparrow
#

E.g. when I was working on geodesy stuff I transcribed some of the math code from SRS to do my work calculations

#

same for some aircraft attitude problems

night shoal
#

thats cool when you can apply stuff from your hobby to your work, or other way around

#

then you did something right πŸ™‚

kind sparrow
#

It's surprising how clunky some of the APIs are when it comes to spatial math stuff, like in matlab or python (even with numpy) I find myself whipping up some glm-like functions that let me do math the way I'm used to doing in GP

night shoal
#

weird, you would think those maffs libs come with those things, neh

#

since they are so widely used

kind sparrow
#

They kinda do but they're just clunky

#

like in numpy if you want to take a bunch of vectors and turn them into homogeneous coordinates to multiply them all by a matrix, you have to do a few steps to append the column of 1s and multiply them by the matrix and stuff, so I just made a function that does it in one step

#

small QOL things

#

Similar to the debug graphics API I have in my engine

#

being able to plot a matrix directly as basis vectors in 3D

night shoal
#

in 2005 or so, i rewrote a whole workflow engine from scratch in c# as a demo, see if i can actually do it or not, since iat the time i was working with something java based (had a visual editor in c# which i was able to reuse) but my crude c# bs was magnitudes faster, the core of the engine is basically just xslt transformations, from any input to any output, forks and joins and whatnot

kind sparrow
#

haha cool

night shoal
#

i was just a trainee at that time too hehe

night shoal
kind sparrow
#

it is in some limited ways just not as flexible as I'd like

#

usually it's fine, there are just a few awkward parts that I fixed with bits I have in SRS too basically

night shoal
#

even the VectorGeometry.pas pascal file for all the math stuff had it built in back when i was fiddling with Delphi

#

from homogeneous to affine and other way around, overloads for everything you need

kind sparrow
#

yeah

#

numpy is more general, like matlab

night shoal
#

sucks

kind sparrow
#

the helper functions it provides are hit or miss, but 90% of the time it's good

#

I use it for everything

night shoal
#

if it works most of the time then its probably alright

#

and then you just add whatever is missing fgor your special corner case

kind sparrow
#

yeah

gilded shell
gilded shell
kind sparrow
#

No

#

It's the same as regular instancing

gilded shell
#

oh wow

#

then yeah bindless all the way

kind sparrow
#

Personally I juse use array textures

night shoal
gilded shell
#

dang

#

what about you @kind sparrow

kind sparrow
#

2016

gilded shell
#

oh okay

kind sparrow
#

That's when I started programming

#

But I was fiddling with computers since maybe 2010 and using them since 2004 or something

#

Just playing games and drawing on macpaint and stuff

#

Before that I guess too in limited capacity

#

I don't think macpaint existed anymore in 2004 so maybe that was earlier

gilded shell
#

yeah

#

dinosaurs in my chat

kind sparrow
#

Lmao

#

Most people here are over the age of 25

gilded shell
#

yeah

#

graduates i assume

kind sparrow
#

Yes

#

Since most people aren't really equipped to do GP until then

gilded shell
#

yeah

gilded shell
#

~4.5 ms

#

ignore this im just writing it down

gilded shell
#

I wonder if I should use compute shaders for my mdi

#

so I can properly choose which SSBOs to read from in vert/frag shaders

#

and to calculate transforms

night shoal
#

try naive first

#

then use compute to cull and fill the indirectbuffer with the surviving geometry

gilded shell
night shoal
#

no compute shaders

#

frustum culling on cpu, populating the indirect/parameters buffer for glMultiDrawIndirectCount

kind sparrow
#

Yes this is good enough for most purposes

#

Your application may not have enough stuff going on to get much benefit from computer draw generation idk

gilded shell
#

i know you can specify the offsets of each parameter buffer letting you put extra stuff in there ig

#

but how would you access that extra stuff?

gilded shell
#

it looks like on vulkan you can have a full command buffer for bindless rendering

#

im jealous now

kind sparrow
night shoal
#

you have all your meshes, have all their aabbs, you cull those aabbs against your view frustum, the ones which survive, you add to the indirect buffer, and put the count of all of them in the parameterbuffer

#

then you bind both buffers and glMultiDrawElementsIndirectCount()

#

next frame, you do the same, as you might have moved your camera around, frustum changes, you cull all meshes using their aabbs

#

etc

kind sparrow
#

Maybe worth doing some regular instancing before trying MDI

night shoal
#

yea

#

and funny enough

#

if you slowly progress through glDrawArrays, glDrawElements, glDrawElementsInstanced, glDrawElementsInstancedBaseVertex, glDrawElementsInstancedBaseVertexBaseInstance etc you arrive naturally at glDrawIndirect and glMultiDrawIndirect and then the peak of MDIism glMultiDrawElementsIndirectCount hehe

#

and you can see how all the params of the DrawIndirectElementsCommand came to be

#

next evolution then is, doing the culling all on the gpu

#

with compute

#

then hiz occlusion culling

#

and then the latest thing, you meshlettify all your geometry and hiz occlusion cull all of them

gilded shell
#

makes sense

night shoal
#

if you have a lot of geometry that is

#

which overlaps a lot

#

otherwise a shrimple glDrawElementsInstanced is probably the best

gilded shell
#

I think the structure I will take is

#

have an array with elements for each primitive/meshlet being rendered containing indices to transforms, materials, etc.

#

and then have arrays for said transforms and materials

#

all on GPU side

night shoal
#

use buffers instead of arrays

gilded shell
#

yeah what I mean

#

buffers of arrays

night shoal
#

buffers of elements : )

#

sorry for being picky

gilded shell
#

the whole point is to never bind

#

so i can do mdi

night shoal
#

its not a sin to bind stuff

gilded shell
#

i know but I literally cannot bind

night shoal
#

you might have a depth prepass, a deferred render pass, lights and shadows and whatnot

#

those require binding of sorts

gilded shell
#

as far as i know mdi doesn't let you bind between draws

night shoal
#

ye its in the nature of the thing

#

bind all the things you need for the pass to be able to draw its stuff

gilded shell
night shoal
#

dont overthink it or overengineer it, you also might need to bind some stuff for debugging purposes

#

like a line renderer or so to visualize aabbs or frustums

gilded shell
#

right

#

but then no mdi

night shoal
#

mdi is still very possible

kind sparrow
#

You have a couple thousand state changes per frame before you start getting bottlenecked by the driver

night shoal
#

just in a different renderpass then

#

yeah also texture binds is what used to be the costly part, but since you go for bindless textures already thats gone pretty much

gilded shell
#

okay

gilded shell
night shoal
#

like i just mentioned

kind sparrow
#

MDI is just another type of draw call

night shoal
#

you might have a depth prepass, then some deferred geometry pass, then a pass lights and shadows pass, then a pass to resolve the two

kind sparrow
#

You don't have to put every single thing into one MDI call, that's not really desirable

night shoal
#

and in the depth prepass and deferred you ahve the mega vbo/ibo bound for mdi

#

yeah

gilded shell
#

I see

#

change of plans then

night shoal
#

all the post effects if you ever add some will do their own thing

gilded shell
#

i'll stick to singular draw indirect which I assume is about a nanosecond faster lol

#

and upgrade to mdi in the future if needed

night shoal
#

drawindirect and mdi is virtually the same

gilded shell
#

correct

night shoal
#

but starting with non indirect draw is a good start too

#

it does have implications on the "renderer" "architecture" a bit but thats just 1 vs many (2 per mesh)buffers really

gilded shell
#

I think I'm just bikeshedding the wrong stuff

night shoal
#

: )

#

thats what we like to do too hehe

kind sparrow
#

Well it depends on your goals I guess, deccer and I are fairly practical about this so our advice is always going to be "you don't need to bikeshed this until your application demands it"

#

But if you don't want to make an application and you just want to make a meshlet bikeshedding application then that's up to you

#

But you can't really dive into it without some decent experience using the API the normal way imo

gilded shell
#

I plan to implement gi, so I do want to optimize this well but I really doubt I'm cpu bound anyways

#

I do wonder how people are drawing sponza at 0.1ms though

#

probably just culling

#

honestly before I do anything else I want some OIT

#

and maybe alpha to coverage

kind sparrow
#

OIT supplants A2C as far as I know

#

The point of A2C is to avoid blending altogether

gilded shell
#

ohh

#

I thought it was a technique to reduce aliasing

night shoal
#

: )

gilded shell
#

I read a paper on something called "fourier opacity mapped OIT"

#

it sounds like a neat place to start

night shoal
#

for some reason i have old game magazines in front of my third eye right now explaining MSAA with some telefone cable poles in games

kind sparrow
gilded shell
#

perhaps

kind sparrow
#

I guess if you're just taking stuff straight off the paper maybe it's doable

gilded shell
#

if it's too much I can always fall back to whatever method logl has up

kind sparrow
#

I wish there were more test scenes that were better than sponza and bistro

gilded shell
#

weighed blended

night shoal
#

i have this neat antenna thing from mjp's shadow demo thingy

kind sparrow
#

I've never rendered them but afaik they are basically just one giant mesh right? Nothing to really instance

gilded shell
#

uhhhh

night shoal
#

yeah more or less

#

lustri is also complaining about it

gilded shell
#

I think bistro has some identical bush meshes

#

but repeated less than 10 times so most likely not worth any instancing

kind sparrow
#

Yeah that's not that interesting though, what we need is a test scene that's like an actual game and not just a blender scene

night shoal
#

thats why i always wanted to make some "bricks" in various default sizes 1x1x2, 1x1x3, and so forth per axis, and "rebuild" sponza out of those, would be suitable for some fisiks testing too hehe

gilded shell
#

lol

#

actually

#

doesnt sponza have that 1 thousand candles add on

night shoal
#

yes

#

and ivy

#

and curtains

#

too bad the fucking knight model only comes in obscure file formats

gilded shell
#

fr

night shoal
#

<rant> i have no fucking clue whats so hard to properly name the model, its parts and whatever else is in there, and then export them into all the fileformats they need individually </rant>

kind sparrow
#

I'm going to be the first one here whose engine includes a glTF exporter and then others can render SRS scenes in their engines lol

gilded shell
#

absolute W

night shoal
#

i screenshotted that

#

i enjoy being distracted grumpy

#

otherwise i would need to attend my 4k lines of mess.cpp

gilded shell
#

yeah

#

doing controlled sixteenth notes on a single kick is hard

#

but i refuse to buy a double pedal

kind sparrow
#

Rip

#

Double pedals are great

gilded shell
#

well

#

people can do 32nds on their doubles

kind sparrow
#

Although I exclusively play 16ths on the kick lol

gilded shell
#

so naturally, 16ths on singles are possible

kind sparrow
#

I thought you meant sustained

gilded shell
#

wdym sustained

#

as in doing it for a while?

kind sparrow
#

Yeah

gilded shell
#

yeah that's what I mean

kind sparrow
#

I can play 8ths sustained on one pedal up to a certain bpm but not 16ths

#

Idk how you'd do that unless at very low bpm

gilded shell
gilded shell
kind sparrow
#

Where does he play 16ths on the kick

gilded shell
#

he does 32nds

#

while doing those cymbal rolls

kind sparrow
#

Oh I see it

#

He's got a double pedal though

gilded shell
#

still thats an equivelant of 16ths on one foot

#

unless hes doing some sort of double stroke

kind sparrow
#

Timestamp? I'm at work I can't watch the whole thing

gilded shell
#

4:43

#

but the whole video is certainly worth a watch 😁

kind sparrow
#

Those sound like 16ths to me

gilded shell
#

he speeds up to 32nds

#

this isnt metal, the song is like 120

kind sparrow
#

Ah I'm counting it at cut time I guess

gilded shell
#

yeah

#

im learning this song

#

its hard lol

kind sparrow
#

I can sustain 8ths at 200 I think

#

Or could rather

#

Haven't played in years

gilded shell
#

16ths at 100 sound more impressive

#

theres plenty of songs at 100

kind sparrow
#

Well that's 8ths doing a blast beat on a single foot so I can do 16ths on a double pedal at that BPM

gilded shell
#

yeah

kind sparrow
#

That's pushing the range of what I could sustain for more than 30 seconds or so though

#

Ok I found maybe the only recording of myself playing that I can find online, it's two songs I tracked for my friend's meme grindcore project lol

#

I will DM you a link so as to not dox myself

gilded shell
#

lol

gilded shell
#

darn, none of my projects are cool enough to go in that comp

night shoal
#

dont say that πŸ™‚

#

or take it as an inspiration

#

like these tiktokers who ask random 1 man burgerflippers if they can make them a 60s intro video πŸ˜›

gilded shell
#

put the deadline a year ahead and there might finally be some cool stuff in here lol

kind sparrow
#

Is this compilation thing going to be publicly associated with this server, I don't want it to attract more windowlickers

gilded shell
#

i was a windowlicker once

night shoal
#

#1252708855176106086

kind sparrow
#

Advertising it as a place to come hang out with the cool kids or see cool projects without contributing

kind sparrow
night shoal
#

i like aphex twin's window licker

night shoal
#

time to create an alt account, demon πŸ˜›

#

where nobody will totally recognize all the DLCs which went into srs when showing srs reel

gilded shell
#

maybe we just show it to our wives/gfs and no one else

night shoal
#

that also works

kind sparrow
#

I would include SRS if there was no way a viewer could follow it back to this server

night shoal
#

i will also refrain from fan commentary under that video then

gilded shell
#

all ive seen are some models and a terrain and fooliage system

kind sparrow
#

There's not a whole lot to see yet tbh I just test it in small pieces and right now it's all taken apart to rewrite most of the whole game

#

The most cohesive things to see is just at the top of my thread basically

gilded shell
#

lol

#

i need to escape this habit of doing some tiny task then being done for the day

kind sparrow
#

I need to stop anxiously avoiding my projects because of the crushing weight of their difficulty

#

I waste a lot of time

#

Also I feel bad working on that one because there's another I'm supposed to be working on

gilded shell
#

huh

kind sparrow
#

I am beholden to another volunteer project that I can't disclose but it's a huge PITA to work on so I've been avoiding it

gilded shell
#

i see

night shoal
gilded shell
#

i think my ubo alignment is all messed up

#

ah

#

I think my booleans were being optimized to 1 byte or something

#

anyways it took embarrasingly long to get this demo up

gilded shell
#

True order independent transparency

#

(weighed blended)

gilded shell
#

I have dozens of gl objects that i dont delete when the program closes

#

"ill handle it later" lol

gilded shell
#

Forgive me

#

but I might make a Scratch project

kind sparrow
#

Oh no lol

#

Graphics not masochistic enough is it

gilded shell
#

yeah

gilded shell
#

now would be an appropriate time

gilded shell
#

I have finally gotten my model class written

#

theres a couple more things to do to finalize it but other than that were good

#

and I am proud to report that I did not write a Scratch project

gilded shell
#

Andβ€”I might switch to vulkan later down the road for rt support

#

we’ll have to see

gilded shell
#

Tbh

#

I might just

#

step through the hierarchy a second time for transparent primitives

#

I doubt it's much slower than making some sort of queue system

#

and if it's a perf problem I can probably just store two seperate hierarchies in the future

night shoal
#

the material should be able to tell you whether its transparent or not

#

and from that you can divide your primitives in Opaque and Transparent-isms

#

i suppose

gilded shell
#

There is an issue

#

blender didn't actually correctly write the materials upon export

night shoal
#

spooky

#

there is a correct bistro model (as glb) out somewhere, check the searchbox

gilded shell
night shoal
#

idk thats a foreign discord

#

it was mentioned in #ray-tracing somewhere, perhaps ping jaker or BayBoyKiller

#

i believe those 2 were referring to the good one some time agio

gilded shell
#

ill try jaker

gilded shell
#

The gltf file is worse than I imagined

#

it's storing duplicate texture-sampler pairs

#

ig I gotta make a hash table now 😐

gilded shell
#

the fix was simpler than imagined yet took some time to write

if (!set.contains(mTextures[i].bindlessHandle))
{
    glMakeTextureHandleResidentARB(mTextures[i].bindlessHandle);
    set.insert(mTextures[i].bindlessHandle);
}
night shoal
#

use the variant which takes samplers into account already

#

i believe i mentioned that some time ago, that when you go bindless to also look at sampler objects

#

otherwise you have no way of using different samplers per texture

gilded shell
#

thats what I do

night shoal
#

ah right the sampler and texture goes into the GetSampledTextureHandleThingARB not this function

#

i didnotread

gilded shell
#

yeah lol

#

i am smart

gilded shell
#

shader hot reloading

gilded shell
#

@night shoal cool finding

#

those depth issues with the sponza decals don't occur with OIT for some reason

night shoal
#

interesting

gilded shell
#

todo: default sampler

gilded shell
#

5 on the ap csa exam

gilded shell
#

finally correctly rendering sponza

west trail
#

That's bistro mate

gilded shell
#

oops

gilded shell
#

normal mapping

oak moat
#

doesn't look very normal to me bleakekw

gilded shell
#

everything is white, and the light color is red

#

the code is all updated on the github if anyone wants to see

night shoal
#

i dont like the highfov

gilded shell
night shoal
#

looking at the screenshots

gilded shell
#

i changed it to 75

night shoal
#

dont get me wrong, just beacuse i dont like it doesnt mean you have to change it πŸ™‚

gilded shell
#

i mean i didnt really like it either lol

#

would die for some code review though

night shoal
#

i scrolled through a little and i think its perfectly fine

#

i personally dont use glGetXXXLocation to map strings to locations, i just use locations directly because they will never change really

#

there is a slight problem with creating textures, regarding color space/format, diffuse or albedo and emissive textures need to (or should) be in GL_SRGB8_ALPHA8, the rest in whatever... when you add compressed textures later then that matters for normals and single channel stuff too (the BC format, not srgb)

#

you can also save some bandwidth, by encoding normals into an uint using orthogonal encoding and glm::packSnorm2x16 (plus its counterpart in glsl to unpack and decode orthogonal into vec3)

#

looks like you create materialbuffer etc per model you load

#

that most likely will work when you render each model individually (bistro + deccer cubes + sponza + whatever)

#

hehe reading c++ which doesnt use trailing type thingy syntax is weird, now that i kind of like it and use it everywhere

gilded shell
#

i personally don’t like it

#

if you noticed i also dont store vertex tangents at all

#

A lot of models don’t include it anyways so I just calculate them on the fly with no major perf penalty

night shoal
#

gltf will provide tangents

gilded shell
night shoal
#

tick "tangents" when exporting gltf

#

and they will be vec4s

gilded shell
#

It’s just easier to calculate them lol

night shoal
#

sure fallback to have makes sense

gilded shell
kind sparrow
#

I don't like the trailing type thingy either

#

Declaring everything as auto only to separately declare its return type is just pointless imo

#

But to each their own

#

The thing about C++ is that there are so many ways to do things that you just need to learn to be flexible with different code styles with it

night shoal
#

yeah

gilded shell
#

yeah

#

I just dislike it because it makes the actual function name harder to find

night shoal
#

i do use fuzzy finders in whatever tool when present, but i understand what you are saying

gilded shell
#

deferred shading

night shoal
#

im jealous πŸ™‚

gilded shell
night shoal
#

my renderrer is fucked atm : >

gilded shell
#

Language

#

but mine too slightly

#

those lamps hanging from the rope should be colored

night shoal
#

indeed

gilded shell
#

I also need to debug this

#

obviously it's working but I'm still scared that it's somehow not

#

It might be something about emissiveness

night shoal
#

i think they have emissive properties yeah, but also some diffuse

gilded shell
#

Well im not rendering emissive properties

#

nor do I plan to

#

I went to a gltf viewer and turned emissiveness off, and it looks like the colors do dissapear

#

so it's fine

night shoal
gilded shell
#

time to choose a meshlet generator

#

any suggestions?

#

also i went and saw dmb last night

#

their drummer is insane

gilded shell
gilded shell
#

I've downloaded it

#

the documentation seems very lacking

#

ohhhhh nvm

night shoal
#

: )

gilded shell
#

I am a little confused by what I'm left with after using meshopt to generate meshlets

#

there's meshletVertices which are meant to be indices to the original vertex buffer

#

so I suppose the new meshlet vertices are sorted

#

and then there's meshletTriangles

#

which ig is the actual index buffer, but it's std::vector<unsigned char>

gilded shell
#

yeah that would seem so

gilded shell
#

why not just use uint8_t though

gilded shell
#

Taking a week off as I plan to go on vacation

gilded shell
#

I know its far off

#

but when I’m done with college, I want to make a really good 2D game and distribute it for free

#

using my own engine and music of course

night shoal
#

im looking forward to it

gilded shell
#

The thing is I kinda want to release it anonymously

#

I think that could be cool

#

or at the very least be silent about it during development

night shoal
#

you could release it as StrubGromper69

gilded shell
#

I’d probably use my real name

#

which is a great reason to not dox myself here

#

maybe I will personally DM you and demon about it lol

kind sparrow
#

Yea the separation of identities is pretty tricky

#

It's hard to keep them perfectly isolated

#

I have a more professional handle that I don't mind being associated with myself but obviously I do all my main discording and stuff with this one so if I were to release under another name then everyone who's seen me here will know the connection between the identities

gilded shell
#

Interesting

#

well if a side scroller is released in 2030 with dave matthews styled music youll all know who made it

kind sparrow
#

I'll keep my eyes peeled

gilded shell
#

goodness gracious water is so beautiful

kind sparrow
#

Midwesterner moment hehe

gilded shell
gilded shell
#

but md water sucks so true

kind sparrow
#

Oh I thought you were from Ohio for some reason

kind sparrow
# gilded shell

Seeing the curvature of the earth always reinvigorates my desire to stick with my round earth terrain froge_love

oak moat
#

just assume earth is a 10 dimensional object with a perfectly flat projection in 3D

gilded shell
#

waterposting gets this thread more activity than actually taking about the project nervous

#

well I love water so I’m not too bothered by that

kind sparrow
#

Gotta do more bikeshedding

gilded shell
#

there’s no code to bikeshed

#

i impress myself with how small my programs tend to be

gilded shell
#

In which we explore ray tracing, the reason modern CGI can look so convincing, and ReSTIR, a recent technique that allows images (and particularly animations) to be rendered hundreds of times faster.

RIS Paper: https://diglib.eg.org/bitstream/handle/10.2312/EGWR.EGSR05.139-146/139-146.pdf?sequence=1&isAllowed=y
RIS Thesis: https://scholarsarchi...

β–Ά Play video
#

I found this video to be a good resource

gilded shell
#

i am home now

night shoal
#

wb

gilded shell
#

I hate these bugs:

    throw;

std::size_t maxMeshlets{ meshopt_buildMeshletsBound(tmpIndices.size(), 64, 124) };```
It doesn't throw, but meshopt_build fails because 
`assert(index_count % 3 == 0);`
#

alright we're getting somewhere

#

Okay index bufs are per meshlet

gilded shell
#

a lot closer

#

even closer

#

the meshlets seem to be cut short

gilded shell
#

meshlet gen works, but that frametime πŸ˜“

gilded shell
#

7x slower

#

I need to use smaller indices, and maybe mdi for the meshlets

#

ahhh I see why its slower

#

I updated my little stats thing and before meshlets, there are 1538 drawcalls, and now with meshlets there are 50213

junior sparrow
#

How slow we are talking about? Also what gpu do you hve?

night shoal
#

the trick is now to cull all the non visible meshlets

gilded shell
gilded shell
#

mdi is much needed here

junior sparrow
gilded shell
junior sparrow
#

58k

#

but indirect

gilded shell
#

exactly

#

all 50k calls are over the pcie

junior sparrow
#

the opengl driver has to have insane overhead

#

for just executing drawcalls

gilded shell
#

yeah

#

try direct calls

junior sparrow
#

not really possible cpu almost doesnt know what is loaded

gilded shell
#

uh

#

you can do singular draw indirects

#

thats what im doing

#

bind the indirect buffer then call drawindirect

junior sparrow
#

Its not simple for me to just switch it

gilded shell
#

unless you’re using vulkan, im not sure what the equivalent will be

#

God willing, I’ll start with MDI and see if that resolves it

junior sparrow
#

only thing missing is lods and sw raster

gilded shell
#

i see

junior sparrow
#

wait for hiz its going to be big pain in the ass

#

I still havent nailed it. There are some edge cases that are hard to nail down

gilded shell
#

Time to bikeshed drawcall batching

#

Ideally I want to use one MDI per mesh so that all meshlet draw calls are indirect

#

however I still need to sneak culling into that process

#

afaik you can't have MDI skip an instance

#

I have heard of mesh and meshlet shaders but iirc theyre vender specific so I want to avoid those

#

The vulkan switch may come sooner than we thought KEKW

kind sparrow
#

Is this for culling

gilded shell
kind sparrow
#

Normally you just build up the list of draws from scratch and you skip in that process

gilded shell
#

so

#

via compute i generate the indirect draw arrays each frame?

kind sparrow
#

Or just on the host, whenever you build up the draw data

#

Oh wait this is for meshlets is it

gilded shell
#

yeah

#

i do have meshlet data on host

kind sparrow
#

Ok I guess it's still similar, but you have sort of a fixed "whole scene" buffer that's static and then fill the MDI buffer and transform buffer out of that I suppose

#

I'm not really sure

#

The difference for me is that normally your draw data is changing every frame

gilded shell
#

right

kind sparrow
#

But if you're just selecting meshlets to be drawn out of a fixed array it's a bit different

#

You'd either have to copy the scene data into a compact instance buffer, sort the scene data, or add another layer of indirection so that your instances can randomly access the meshlets they're drawing

gilded shell
#

but the takeaway is im rebuilding indirect arrays each frame, right?

kind sparrow
#

Most likely

#

How do the meshlets work, is each one an indirect draw?

kind sparrow
#

I don't see how they could be instanced

#

Ok

#

Yeah just rebuild the draw list

gilded shell
#

so i could get the scene represented on gpu

#

then use compute to gen the arrays

kind sparrow
#

You can do this on the host too which is easier to start with but yeah you can do it in compute as well

gilded shell
#

okay

#

this would be a lot easier if i could make a drawcall from a compute shader

kind sparrow
#

Wdym isn't that what we're talking about doing

gilded shell
#

i thought we were using compute to make the draw arrays then make the few drawcalls from the cpu?

kind sparrow
#

The CPU just does kicks off the indirect work

gilded shell
#

so why do we need to write the arrays if the compute shaders can just directly make the drawcalls?

kind sparrow
#

Wait is there no transformation data for the meshlets

gilded shell
#

there’s material/transform data per mesh but not meshlet

kind sparrow
#

Ah ok

#

Then I guess you don't need the arrays

#

But either way you're just filling the indirect draw buffer every time

gilded shell
#

excellent

#

this seems a little bit more trivial

night shoal
#

meshlets are nothing else but ordinary mesh primitives

#

you treat them the same way as your cube or sphere or motorcycle or deccer cube

#

they all go in your whole scene geometry/andotherwise indirection buffers

#

then on the gpu you ask the compute shader to cull invisible ones

#

and the survivors are appended into the indirect(and parameter buffer if you use mdic) buffer for the next mdi call

junior sparrow
#

First what I would do move the data needed for rendering to gpu. So materials, transforms, mesh groups and meshes are on gpu in their own buffers and are reachable from shaders.
My simple render loop looked like:

  1. compute dispatch which reads a scene data and writes a indirect compute dispatch with ammount of mesh groups
  2. indirect compute shader goes over all meshgroups and their meshes to write all meshlets into one giant buffer with a counter.
  3. compute shader that read a counter and writes a single indirect draw call command with the instance count which equals to meshlet count in the scene
  4. indirect draw call which reads a previously written buffer with meshlet data and renders them.

This is my vertex shader that renders meshlets

#

I abuse instancing to render meshlets

kind sparrow
#

That's true if the meshlets are all the same size you can just use instancing and pull the vertices huh

junior sparrow
#

I set vertex count to a max of vertices that meshlet can have and if meshlets has less then max I clip out the vertex

night shoal
#

instancing for meshlets?

junior sparrow
#

As I said I abuse instancing

night shoal
#

is their vertex data always the same? hehe

#

ah

kind sparrow
#

Yeah if each meshlet is e.g. 64 vertices then you can instance a 64-vert mesh and use the instanceID to fetch the vertices from an SSBO

junior sparrow
#

if you mean if they have different amount of vertices you can simply handle it same way I do

junior sparrow
#

its not optimal but vertex shaders are fast enough

kind sparrow
#

How do you discard the unused invocations, just emit NaN?

junior sparrow
#

I linked the shader how I do it

night shoal
#

indeed, i was thinking wrong

#

with vertex fetch you can do whatever you like

night shoal
#

i also have yet to descend into the meshlet realm

junior sparrow
#

If you can use mesh shaders its much better

#

otherwise you have to cope with compute and vertex shaders

night shoal
#

yeah so i heard

#

fortunately i have some 40xx grade hardware

#

but a fallback would also be nice, for the learning purposisms

kind sparrow
#

My entire player character is a meshlet

night shoal
#

sounds like an insult if you say it like that

junior sparrow
kind sparrow
#

Well I am in the 11.2% and am not sure I agree with this message

#

I want to be able to play Deccer's game

#

Although I'm going to put a 30xx in my other computer eventually so all will be forgiven if he decides to go the mesh shader route

junior sparrow
#

This is only discrete gpus on steam

kind sparrow
#

Actually weren't there whisperings of cross-platform mesh shaders coming in GL soon

#

Although idk if that would work on old cards still

junior sparrow
#

I assume most players who will want to play my game will have one

kind sparrow
#

Are mesh shaders a hardware thing

junior sparrow
#

sadly they are

#

turing+

kind sparrow
#

rip

junior sparrow
#

so gtx 1660 up in nvidia terms

gilded shell
kind sparrow
#

Vulkan

#

But it still requires a newer card

gilded shell
#

oh brother

#

i am kinda tired of dealing with ogl's crap

kind sparrow
#

Like what

gilded shell
#

only having vendor specific mesh shaders KEKW

kind sparrow
#

Lol

gilded shell
#

lack of hw rt support

#

and overall inconsistencies

junior sparrow
gilded shell
#

I don’t want raw vulkan though; i think an abstraction would be better

junior sparrow
#

I can recommend daxa

gilded shell
junior sparrow
#

made by lpotrick

#

and gabe rundlet with saky

gilded shell
#

hmm

junior sparrow
#

very easy to use

gilded shell
#

a quick glance tells me it might be too high level

junior sparrow
#

it exposes everything you want to use

#

but no raw vulkan

gilded shell
#

i see

#

ill keep this in mind, thanks

junior sparrow
#

also to mention it has rendergraph

gilded shell
#

uh oh

#

what’s that?

junior sparrow
#

it handles synchronization for you and easier to code stuff

gilded shell
#

i see

junior sparrow
#

also it requires to share code between C++ and glsl/slang

night shoal
#

OpenGL also supports mesh shaders

#

on nwidea hardware

junior sparrow
#

only vendor specific extensions

#

mesh shaders are also coming to amd

night shoal
#

yeah, turns out i cannot read, as usual

#

@gilded shell you can find the daxa thread in #1019722539116802068

junior sparrow
#

kinda dead tho

night shoal
gilded shell
#

lol

junior sparrow
#

daxa has its own server but that one has occasional activity

gilded shell
#

i changed my mind

#

raw bulkan sounds funner

junior sparrow
night shoal
#

good thing is you can still pester potti or gabe or any other frog who took the daxa pill

junior sparrow
#

daxa pill is very nice froge_love

kind sparrow
#

If you want to make a specific game then raw Vulkan is fine

#

If you want to make a flexible engine or sandbox tool for graphics prototyping you should use something like vuk or daxa

gilded shell
#

i see

#

vuk vs. daxa?

kind sparrow
#

Otherwise you're going to just spend huge numbers of hours writing infrastructure code

night shoal
#

we need a srs contender

#

aptly named "srsly"

gilded shell
#

i suppose calling this a sandbox is wrong because i do have end goals

night shoal
#

famous last words

gilded shell
#

but i do want this to be sandbox-like

junior sparrow
kind sparrow
#

End goals as in a specific game or end goals as in a certain set of graphics features

gilded shell
#

features

#

which is why for now im going with daxa or vuk πŸ‘

#

maybe vuk because it has a better name

kind sparrow
#

It's also made by a funnier person

night shoal
#

vuk has a dedicated server too, its in #related-servers martty is on travelz atm might not get immediate feedback atm

#

but Hek is there to help as well

gilded shell
#

i see

junior sparrow
#

with daxa you have to either infer from the code or timerdoodle or one of my projects

#

Also you can ask me

gilded shell
#

daxa does have a dedicated tutorial too

junior sparrow
#

I dont think its up to date but its really close

#

there were breaking changes and lpotrick is lazy to write it

gilded shell
#

darn

junior sparrow
#

I would rather consult one of my projects or timberdoodle

oak moat
#

why is none of you suggesting the good ways of doing meshlets without mesh shaders

#

@gilded shell #1262676828322271293 message

gilded shell
#

legend

#

thank you

gilded shell
#

@oak moat if I’m β€œdecoding” a vertex index in the vert shader, doesn’t that mean i cant use conventional vertex buffer layouts where the shader fetches the vertex automatically?

junior sparrow
#

you fetch from buffers

junior sparrow
oak moat
gilded shell
#

i see

gilded shell
#

"dispatch a compute shader to write an index buffer of size meshletCount * maxPrimitives * 3 that encodes primitiveID and meshletID, then in the vertex shader you can decode the vertex index and proceed as usual"

#

Not sure why it needs to write the index buffer

night shoal
#

you bind it as an indexbuffer

#

and make use of indexed drawing as usual

gilded shell
#

right but why? I already have index buffers; rewriting them with compute seems wasteful

#

I can understand the primitive and meshlet id part

junior sparrow
#

its buffer that contains indices for meshlet

oak moat
gilded shell
#

why not do it offline and drop the original indices?

oak moat
gilded shell
#

I do not understand why

junior sparrow
#

because you write same info 3 times instead of just once

#

same packed index for every vertex in triangle or you could do it once per triangle

gilded shell
#

Sorry but I'm incredibly confused lol

oak moat
#

I will simplify

oak moat
#

you have a buffer of size N

#

now suppose you want culling

gilded shell
#

just to clarify offline means on the CPU at loadtime?

oak moat
#

it doesn't matter

#

point is that it's not done in compute

oak moat
#

worst case for culling is that every meshlet and every triangle is visible

#

so the worst case size for the new buffer that contains the culling result is N again

#

therefore the total size is 2N

gilded shell
#

right

#

so how does doing this in compute fix this?

oak moat
#

you don't do it offline

#

and the culling shader is the same as your "make buffer" shader

gilded shell
#

okay

oak moat
#

I think it's better if you actually implement it

#

then it'll become clear

gilded shell
#

perhaps

#

in conclusion,

#

all the geometry is loaded into storage buffers and when its time to render, a compute shader runs through, does the culling, and writes out the survivors to new buffers?

#

or am I back at square one

gilded shell
#

I see

#

Thank you for giving me widsom

#

wisdom

#

after that, I suppose the CPU issues an MDI command that draws all those survivors

oak moat
#

no

gilded shell
#

No?

junior sparrow
#

you write the command in compute shader and cpu does indirect with the buffer

oak moat
#

actually yes I thought you were doing the other strat

#

yes it's a single command with indexCount set as survivingMeshlets * triangleCount * 3

gilded shell
#

of course

#

one more thing

#

is this solution for per-triangle culling as well? That would explain the index buffer rewrite

junior sparrow
#

yes

gilded shell
#

I see

#

I wonder how per-triangle culling can be faster than just letting them through

#

it depends on the method I suppose

junior sparrow
#

you reduce vertex invocations

gilded shell
#

I assume per-triangle culling would use a frustum intersection method, rather than the projection method used in vkguide 2

oak moat
#

no

#

you do small triangle culling

#

then backface culling

#

and then you profile if occlusion/frustum culling is worth it

#

typically it's not

junior sparrow
#

also from lpotrick its not worth if you dont use mesh shader

gilded shell
#

i can't really do backface culling before vertex transform though

junior sparrow
#

you can

oak moat
#

yes you can

gilded shell
#

πŸ€”

#

via dot products?

junior sparrow
#

no by using determinant

oak moat
#
v0 = projView * worldTransform * vertices[indices[i0]];
v1 = projView * worldTransform * vertices[indices[i1]];
v2 = projView * worldTransform * vertices[indices[i2]];
cull = determinant(mat3(v0.xyw, v1.xyw, v2.xyw)) > 0;```
gilded shell
#

i see

#

you both are very smort

oak moat
#

nah zeux is KEKW

junior sparrow
#

yeah kekkedsadge

gilded shell
#

well

#

my plans get closer to nanite daily

junior sparrow
#

Also I need to figure out why my hiz is not 100% correct

#

it just sometimes breaks

gilded shell
#

now all i need is a lod tree and sw raster lol

oak moat
#

all I need is lod tree

#

u-huh

#

let me know when you're done

gilded shell
#

just a couple business days

junior sparrow
#

I tried sw raster but it was hilariously broken like whole sponza was splitted weirdly in half and both parts were going in different direction

gilded shell
#

lol

#

you have to make a scratch project first

junior sparrow
#

god no

#

I am already suffering with my jobs

#

angular + php will make you hate programming

gilded shell
#

right

#

i actually did write a clusterizer and dynamic lod engine on Scratch and it was hell

junior sparrow
#

I saw that

#

I would question your sanity

gilded shell
#

yeah

junior sparrow
#

Also I do wish upon worst enemy to write javaish php code or deal with css/js spec

gilded shell
oak moat
#

sure

#

more rigorously: projected area of triangle is less than threshold (with subpixel scaling taken into account)

gilded shell
#

right

#

but i dont own any models with that level of fidelity lol

#

maybe it makes more sense for far away triangles, not sure if bistro is expansive enough for that to apply

oak moat
#

if you go far enough away every triangle is subpixel

#

but it is pretty marginal

#

it may even give you a little overhead

gilded shell
#

i see

#

ill probably go with the backface cull

#

ahhh i need to make my materials bindless too

kind sparrow
#

The thread has been pulled

gilded shell
kind sparrow
#

You're pulling the thread and now the whole thing is unravelling lol

#

If you're going to go down this route you may as well switch to Vulkan

oak moat
#

fake you can implement nanite without vulkan

#

you need vulkan only if you want to torture your GPU with CAS loops and devicecoherent memory KEKW

#

for that beautiful cross queue async visbuffer writing and bvh trasversal froge_love

gilded shell
#

this meshlet frustum junk + two pass occlusion culling is all i have planned

#

the vulkan switch might be inevitable depending on how performance critical ray trace operations will be

oak moat
#

what kind of tracing

gilded shell
#

not sure what you mean

#

raytracing against a bvh for lumen styled radiance caching

oak moat
#

unless by bvh you mean distance field then you're gonna get "interactive framerates" at best

#

and even then it'll be painful

gilded shell
#

so

#

i need hw rt?

#

meaning i need bulkan?

#

im going to kill myself

gilded shell
#

its at about 1800 messages and yesterday i think it was 1500 lol

#

meaning ~17% of this threads messages occurred today just because i wanted meshlets to draw a bit faster

kind sparrow
#

No I meant the sweater is unravelling

gilded shell
#

well i can either switch to vulkan now or later

oak moat
gilded shell
oak moat
#

slow

gilded shell
#

darn

#

but i dont like ibl

oak moat
#

raymarching and conetracing still exist you know KEKW

#

also IBL is useful for sky lighting

gilded shell
oak moat
#

it depends

#

generally if you want HWRT there is only one way of doing things

#

with everything specified by the API

#

instead of bringing your own representations which may or may not work well with your scene

#

anyway it depends, just do whatever you want

gilded shell
oak moat
#

what about them

#

it's the same thing except without RT pipelines

gilded shell
#

unless you’re talking about the scene and bvh setup?

oak moat
#

legitimately it's really just traceRayEXT but in compute

#

you're still using your HW's BVH format and HW's tracing algorithm and all that

#

it's fast*

*assuming you provide a scene that is a good fit

gilded shell
#

i see

#

i will take this into consideration

#

thank you for taking the time to help

oak moat
#

you should read more

#

what I said is just the tip of the berg

#

generally one can only say "it depends"

gilded shell
gilded shell
#

Actually

#

I think I'll start with screenspace

#

since I want to use screenspace for specular reflections anyways

gilded shell
#

closer

#

the code in question

#

oh my shader version wasn't high enough

#

alright

#

all the scene's materials are now in one big ssbo

gilded shell
#

geometry now mostly bindless

#

this is all so that I can do aforementioned culling and batching methods

#

the only thing left being bound are material indices and and model transforms, which all can probably be built into another large ssbo with per-meshlet elements

#

after that I can use compute to build the index and mdi buffers

night shoal
#

what do you mean by geometry bindless?

gilded shell
night shoal
#

ye thats still not bindless πŸ™‚

#

you mean indirect drawing perhaps

gilded shell
night shoal
#

bindless means you dont bind anything

#

hence the name

#

like bindless textures, you just grab a handle from the resource, and pass the handle to the shader

#

that exists for buffers too on nvidia, not just textures

gilded shell
#

oh

#

well then bind-once i suppose

night shoal
#

most people refer to that as mdi or mdic

gilded shell
#

just huge buffers

night shoal
#

ah

#

and glDrawElementsInstancedBaseVertexBaseInstance?

gilded shell
#

just singular draw indirect

#

since it lets me offset indices

junior sparrow
#

Correct name would be bind less

night shoal
#

no bindless means you dont bind

#

its not "bind less textures" πŸ™‚

night shoal
junior sparrow
#

in vulkan bindless is descriptor indexing and bda. you dont need to bind bda because its pointer but for descriptor indexing you need to bing big descriptor set to index into in shaders

#

you still have to bind but only once per pipeline

night shoal
#

ye but we are in opengl space here πŸ™‚

#

no vulkan debauchery yet

junior sparrow
#

I am aware that in opengl you dont need to bind textures since nvidia has some extension but theres nothing for buffers

night shoal
#

that nvidia extension i was mentioning earlier is also BDA for bindless buffers

junior sparrow
#

hmm

night shoal
#

but for indirect draw you still need to bind the indirect (and parameter buffer)

junior sparrow
#

still stinky

#

vulkan is much better

night shoal
#

yeah

#

i agree

#

gl4.6 is not so bad

junior sparrow
#

Its little better but still have global state and you get surprises like nvidia doing mip mapping of 3d textures on cpu

gilded shell
#

Whenever I say bindless I mean the technique rather than the APIisms

west trail
kind sparrow
#

Because skinning adds a ton of attributes that you'd have a second vao for

#

You wouldn't want to have those attributes on every mesh if they're unused

west trail
#

Still struggling to understand how to do it right. Creating 2 types of vertices, one with skinning attributes,one without and then loading them based on user choice seems wrong

night shoal
#

why user choice

#

you render static objects with vao 1, and all your animated ones with vao 2, or you dont use vaos at all (besides the default one for gl core)

west trail
#
  • creating 2 types of vertices seems wrong to me
night shoal
#

you usually have more than 1 vertex type anyway

west trail
west trail
# night shoal then what?

Saving a bit of memory on stuff like animated gates/doors/etc. You may not want to import animations and just use them for background

night shoal
#

your artist will provide the animations used in the game

#

not loading animations to save memory doesnt matter

gilded shell
#

@junior sparrow @west trail Do you have project threads I can follow?

west trail
#

mind updating your github repo btw? I want to stole check out your codefrekw

junior sparrow
gilded shell
#

Probably not today

#

its at a pretty incomplete state lol

#

what code are you looking for?

west trail
night shoal
gilded shell
#

then maybe today

#

but its gonna be super messy

kind sparrow
#

We're talking about skeletal animation

west trail
#

okay, no user choice then

west trail
gilded shell
#

We do not speak obscenities in this chat

gilded shell
#

@west trail its up

west trail
#

Its night time in my timezone man, let me sleepπŸ˜”

gilded shell
#

i think when i finish this project id like to dabble with 2D

#

or not