Open dt-rush opened 1 year ago
good tutorial site: https://learnopengl.com/Advanced-OpenGL/Instancing#:~:text=Instanced%20arrays%20are%20defined%20as,belong%20to%20the%20current%20vertex.
instanced models architecture: https://docs.google.com/drawings/d/1tncH1WAicmSG-lJmdTmf_prayMIInq0DyqZwABPSqfM/edit?usp=sharing
buffer object streaming: https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming
go-gl 4.3: https://github.com/chsc/gogl/blob/master/gl43/gl43.go
excellent youtube playlist: https://www.youtube.com/watch?v=7D8lLbp9_rQ
skeletal animation tutorial: https://www.youtube.com/watch?v=F-kcaonjHf8
frustrum culling: https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling
compute shader frustrum culling: https://vkguide.dev/docs/gpudriven/compute_culling/
This is for vulkan, but possibly the same thing exists for opengl?
this article describes - in very strange language - GPU culling:
the source code for their (several) method(s) including GPU culling is here:
https://wizards-laboratory.com/files/ -> file: FrustrumCulling.rar
3 ways of vertex attribute packing:
GPU collision detection: https://fileadmin.cs.lth.se/graphics/theses/projects/gpucd/report.pdf
some discussion of multidrawindirect being faster than instancing:
gamedev sketchbook example i've cooked up:
https://github.com/dt-rush/gamedev-sketchbook/blob/master/opengl/opengl3.go
features:
performance improvement for opengl:
steps:
MapBufferRange
and write to it like a ring buffer.// At the beginning of time
flags = MAP_WRITE_BIT | MAP_PERSISTENT_BIT | MAP_COHERENT_BIT;
BufferStorage(ARRAY_BUFFER, allParticleSize, NULL, flags);
mParticleDst = MapBufferRange(ARRAY_BUFFER, 0, allParticleSize, flags);
mOffset = 0;
// allParticleSize should be ~3x one frame's worth of particles
// to avoid stalling.
void UpdateParticleData() {
for particle in allParticles {
dataSize = GetParticleSize(particle);
mParticleDst[mOffset] = *particle
mOffset += dataSize;
// ring buffer wrapping not shown
}
}
// Now render with everything.
https://www.youtube.com/watch?list=PLckFgM6dUP2hc4iy-IdKFtqR9TeZWMPjm&v=-bCeNzgiJ8I
"why is it 3x?" explanation: https://youtube.com/watch?v=-bCeNzgiJ8I&feature=shares&t=714
"Now, even though that should be enough to guarantee that there's enough room, you do need to fence, basically, to make sure. So, in OpenGL, i just wanted to briefly cover this, I don't know how many people are familiar with it, they use GL fencing: you place a fence, and then you remember that fencing object that you just placed, then later when you're ready to start writing on this range again, you say ok, i need to do a client waitsync right here, now, a client waitsync will cause all the way up to a CPU GPU sync point if the GPU has to finish work in order for that fence to be retired, so you want to wrap that function with a performance counter; what should happen basically all the time is that the client waitsync should immediately return already-returned, and it should take basically zero time at all; if it doesn't*, you have a sizing problem, and your logs should tell you that.
Another performance improvement:
bindless texture arrays
https://www.khronos.org/opengl/wiki/Bindless_Texture
Basically, passsing integers that represent textures so that switching textures is just switching the integer, and the texture data itself is already loaded up, you just get the texture using the integer. ("handle")
some discussion here: https://gamedev.stackexchange.com/a/142939
not a performance thing but a cool expressive technique:
https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
Switching between uniform buffer bindings is typically faster than switching dozens of uniforms in a program. Therefore, uniform buffers can be used to quickly change between different sets of uniform data for different objects that share the same program.
https://litasa.github.io/blog/2017/09/04/OpenGL-MultiDrawIndirect-with-Individual-Textures
multidrawindirect lets you issue a bunch of different draw calls - including instanced calls - using structs that specify the commands, allowing you to draw even objects with different geometries
(of course, the same program)
typedef struct { unsigned int count; unsigned int instanceCount; unsigned int firstIndex; unsigned int baseInstance; } DrawArraysIndirectCommand;
typedef struct { unsigned int count; unsigned int instanceCount; unsigned int firstIndex; unsigned int baseVertex; unsigned int baseInstance; } DrawElementsIndirectCommand;
https://learnopengl.com/Lighting/Light-casters
lighting
(also see advanced lighting section for bloom, caster types, etc.)
painterly shader
crazy animation gems:
of course the go-sdl2 repo has an example showing go-gl usage.
this repo has some great helper functions wrapping common opengl actions with go-gl (for example, here, compiling a shader): https://github.com/dkvilo/andromeda/blob/develop/framework/shader/compile.go