alt-romes / alt-romes/ghengin

Rendering dynamic list of meshes

オープン
#7 コメント 5 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Haskell
スター
85
フォーク
2
PR マージ指標
30日以内にマージされた PR はありません

説明

I'd like to be able to render a list of entities, and not have to make one manual insertMesh call for each entity in the game world.

I'm far from an expert on this. The way I've always done this is by uploading a (fixed) list of entities to the shader (each containing position, model, whether it should be rendered, etc), then using instanced rendering to select the right each object and render it.

It's my understanding that the engine renders each mesh exactly once, as instanced rendering isn't supported by the engine, but maybe I'm wrong? (Here the instance count is set to 1): https://github.com/alt-romes/ghengin/blob/2de2a822ae39e1a5281efde0420955c0c71f8fc8/ghengin-core/ghengin-vulkan/Ghengin/Vulkan/Renderer/Command.hs#L290

I'm not sure what the interface should look like which allows you to specify instance counts, but I don't especially need it right now.

I came up with this solution:

```haskell
insertMeshN :: forall π p ma me vs. (Compatible vs me ma p π) => MaterialKey π p ma -> Int -> [MeshKey π p ma vs me] -> GRGMESH.Mesh vs me -> RenderQueue () -> (RenderQueue (), Ur [MeshKey π p ma vs me])
insertMeshN mkey max mshkey mesh rq | max > (length mshkey) =
let (rq, (GRG.Ur mshkey')) = insertMesh mkey mesh rq
in insertMeshN mkey max (mshkey' : mshkey) mesh rq
insertMeshN mkey max mshkey mesh rq = (rq, (Ur mshkey))
```

It's messy and unsafe, but just inserts the desired amount of meshes into the render queue. As alluded to here, this solution has the advantage of the compiler being able to make it use instanced rendering in the future perhaps: https://github.com/alt-romes/ghengin/blob/2de2a822ae39e1a5281efde0420955c0c71f8fc8/ghengin-core/ghengin-core/Ghengin/Core/Render/Queue.hs#L142

Although then it would need to mess with the shaders the user has made, adding in references to `gl_InstanceIndex` into the shader to index the current instance, so perhaps that's not possible. And instanced rendering, as I understand it, isn't always the best strategy to use. I have heard that sprites can be rendered faster with singular calls, than through instanced rendering, but that might be wrong. So perhaps the user would have to allow such an optimization with a parameter.

I suppose the question is whether the right path forward is to add a function like `insertMeshN` for now that's cleaned up, by for instance returning a typed sized array and making the amount of meshes you wish to insert a type argument instead of an `Int`.

Or maybe I'm missing something?

EDIT:

So I'm proposing something like this:
```haskell
insertMeshN :: KnownNat n => ... -> Array n (MeshKey ...)
```
Usage:
```haskell
(rq, (Ur meshes)) <- insertMeshN @10 ...

gameLoop meshes ...
```

And I'd be very interested if you know of a better technique of rendering a dynamic list of objects than what I described above. Especially one that doesn't involve sending each object a Bool, allowing the shader to know whether to render the object at all or not, for when it hasn't spawned yet, etc.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。