alt-romes / alt-romes/ghengin

Rendering dynamic list of meshes

未关闭
#7 5 条评论 0 个 reaction 已指派 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 摘要。