tobbebex / GPipe-Core

Core library of new GPipe, encapsulating OpenGl and providing a type safe minimal library
157 stars 29 forks source link

Support for dynamically-sized geometry #58

Closed werner291 closed 6 years ago

werner291 commented 6 years ago

Hello,

really like this library! Being able to use Haskell in the shaders is especially nice.

However, is there support for variable-size geometry? For example, a terrain system with an LOD system where the number of vertices varies between frames.

Right now, newBuffer takes the length of the buffer at the start, and I don't see any obvious ways to resize a buffer or delete one so it can be re-allocated.

werner291 commented 6 years ago

Proposal: take the existing code for newBuffer, and factor out the part that actually sets the size into something like setBufferSize which takes the buffer name and the desired size. This is then called automatically by newBuffer or by user code directly.

tobbebex commented 6 years ago

Hi! GPipe is an abstraction over OpenGl and since that doesnt have dynamically sizable buffers neither does GPipe. What you usually do is to create a buffer large enough, and instead use takeVertices on the primitive array to limit number of vertices used for each drawcall. Hope this helps!

werner291 commented 6 years ago

Hi, thanks for the quick response!

I was mainly referring to the following functionality in glBufferData:

glBufferData creates a new data store for the buffer object currently bound to target​. Any pre-existing data store is deleted. The new data store is created with the specified size​ in bytes and usage​. If data​ is not NULL, the data store is initialized with data from this pointer. In its initial state, the new data store is not mapped, it has a NULL mapped pointer, and its mapped access is GL_READ_WRITE.

(According to https://www.khronos.org/opengl/wiki/GLAPI/glBufferData)

I must admit I don't have that much experience with OpenGL, especially not within Haskell. I'll try if I can somehow break up my mesh into chunks.

werner291 commented 6 years ago

For those who might have a similar issue and found this issue through Google or something, this turned out to be really easy.

My code now looks someting like this:

forM_ (chunksOf terrainBufferSize tg) $ \chunk -> do
          writeBuffer vertexBuffer 0 chunk

          render $ do
            vertexArray <- newVertexArray vertexBuffer
            shader $ toPrimitiveArray LineList $ takeVertices (length chunk) vertexArray

In this context, tg is simply a Haskell list of triangle vertices (each with a normal as well, but that doen't matter if you do it right). terrainBufferSize is the size of my buffer in vertices. Depending on the kind of primitives you're drawing, make sure that this chunk size is correct. For instance, it needs to be divisible by 3 if you're drawing triangles.

tobbebex commented 6 years ago

Thanks for the code snippet! Looks good!

I see your point with redefining buffer data, makes sense. You can achieve almost the same by simply creating a new buffer, though with higher memmory low watermark. Glad it worked out fine for you anyway!