Skip to content

Write godot backend for planet rendering #315

@Capital-Asterisk

Description

@Capital-Asterisk

It's possible to port the 'flight' scenario to godot, but the planet won't be visible as there's currently no code to send planet terrain mesh data to godot rendering server.

'planeta' manages a platform-independent vertex and index buffer. The ftrTerrainDrawMagnum feature simply does the OpenGL/Magnum-specific logic to send this to the GPU:

struct ACtxDrawTerrainGL
{
Magnum::GL::Buffer vrtxBufGL{Corrade::NoCreate};
Magnum::GL::Buffer indxBufGL{Corrade::NoCreate};
MeshGlId terrainMeshGl;
bool enabled{false};
};
FeatureDef const ftrTerrainDrawMagnum = feature_def("ShaderPhong", [] (
FeatureBuilder &rFB,
Implement<FITerrainDrawMagnum> terrainMgn,
DependOn<FITerrain> terrain,
DependOn<FIWindowApp> windowApp,
DependOn<FIMagnum> magnum,
DependOn<FIMagnumScene> magnumScn,
DependOn<FISceneRenderer> scnRender)
{
using namespace planeta;
auto &rScnRender = rFB.data_get< ACtxSceneRender > (scnRender.di.scnRender);
auto &rScnRenderGl = rFB.data_get< ACtxSceneRenderGL > (magnumScn.di.scnRenderGl);
auto &rRenderGl = rFB.data_get< RenderGL > (magnum.di.renderGl);
auto &rDrawTerrainGl = rFB.data_emplace< ACtxDrawTerrainGL >(terrainMgn.di.drawTerrainGL);
rDrawTerrainGl.terrainMeshGl = rRenderGl.m_meshIds.create();
rRenderGl.m_meshGl.emplace(rDrawTerrainGl.terrainMeshGl, Magnum::GL::Mesh{Corrade::NoCreate});
rFB.task()
.name ("Sync terrainMeshGl to entities with terrainMesh")
.sync_with ({windowApp.pl.sync(Run), scnRender.pl.meshDirty(UseOrRun), scnRender.pl.mesh(Ready), magnum.pl.meshGL(Modify)})
.args ({ terrainMgn.di.drawTerrainGL, terrain.di.terrain, scnRender.di.scnRender, magnumScn.di.scnRenderGl, magnum.di.renderGl })
.func ([] (ACtxDrawTerrainGL &rDrawTerrainGl, ACtxTerrain &rTerrain, ACtxSceneRender &rScnRender, ACtxSceneRenderGL &rScnRenderGl, RenderGL &rRenderGl) noexcept
{
for (DrawEnt const drawEnt : rScnRender.m_meshDirty)
{
ACompMeshGl &rEntMeshGl = rScnRenderGl.m_meshId[drawEnt];
MeshIdOwner_t const &entMeshScnId = rScnRender.m_mesh[drawEnt];
if (entMeshScnId == rTerrain.terrainMesh)
{
rScnRenderGl.m_meshId[drawEnt] = ACompMeshGl{
.m_scnId = rTerrain.terrainMesh,
.m_glId = rDrawTerrainGl.terrainMeshGl };
}
}
});
rFB.task()
.name ("Resync terrainMeshGl to entities with terrainMesh")
.sync_with ({windowApp.pl.resync(Run), scnRender.pl.mesh(Ready), magnum.pl.meshGL(Modify)})
.args ({ terrainMgn.di.drawTerrainGL, terrain.di.terrain, scnRender.di.scnRender, magnumScn.di.scnRenderGl, magnum.di.renderGl })
.func ([] (ACtxDrawTerrainGL &rDrawTerrainGl, ACtxTerrain &rTerrain, ACtxSceneRender &rScnRender, ACtxSceneRenderGL &rScnRenderGl, RenderGL &rRenderGl) noexcept
{
for (DrawEnt const drawEnt : rScnRender.m_drawIds)
{
MeshIdOwner_t const &entMeshScnId = rScnRender.m_mesh[drawEnt];
if (entMeshScnId == rTerrain.terrainMesh)
{
rScnRenderGl.m_meshId[drawEnt] = ACompMeshGl{
.m_scnId = rTerrain.terrainMesh,
.m_glId = rDrawTerrainGl.terrainMeshGl };
}
}
});
rFB.task()
.name ("Update terrain mesh GPU buffer data")
.sync_with ({windowApp.pl.sync(Run), terrain.pl.chunkMesh(Ready)})
.args ({ scnRender.di.scnRender, magnumScn.di.groupFwd, magnumScn.di.scnRenderGl, magnum.di.renderGl, terrainMgn.di.drawTerrainGL, terrain.di.terrain})
.func ([] (ACtxSceneRender &rScnRender, RenderGroup &rGroupFwd, ACtxSceneRenderGL const &rScnRenderGl, RenderGL &rRenderGl, ACtxDrawTerrainGL &rDrawTerrainGl, ACtxTerrain &rTerrain) noexcept
{
if ( ! rDrawTerrainGl.enabled )
{
rDrawTerrainGl.enabled = true;
rDrawTerrainGl.indxBufGL = Magnum::GL::Buffer{};
rDrawTerrainGl.vrtxBufGL = Magnum::GL::Buffer{};
Magnum::GL::Mesh &rMesh = rRenderGl.m_meshGl.get(rDrawTerrainGl.terrainMeshGl);
rMesh = Mesh{Magnum::GL::MeshPrimitive::Triangles};
auto const &posFormat = rTerrain.chunkGeom.vbufPositions;
auto const &nrmFormat = rTerrain.chunkGeom.vbufNormals;
rMesh.addVertexBuffer(rDrawTerrainGl.vrtxBufGL, GLintptr(posFormat.offset), GLsizei(posFormat.stride - sizeof(Vector3u)), Magnum::Shaders::GenericGL3D::Position{})
.addVertexBuffer(rDrawTerrainGl.vrtxBufGL, GLintptr(nrmFormat.offset), GLsizei(nrmFormat.stride - sizeof(Vector3u)), Magnum::Shaders::GenericGL3D::Normal{})
.setIndexBuffer(rDrawTerrainGl.indxBufGL, 0, Magnum::MeshIndexType::UnsignedInt)
.setCount(Magnum::Int(3*rTerrain.chunkInfo.faceTotal)); // 3 vertices in each triangle
}
auto const indxBuffer = arrayCast<unsigned char const>(rTerrain.chunkGeom.indxBuffer);
auto const vrtxBuffer = arrayView<std::byte const>(rTerrain.chunkGeom.vrtxBuffer);
// There's faster ways to sync the buffer, but keeping it simple for now
// see "Buffer re-specification" in
// https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming
rDrawTerrainGl.indxBufGL.setData({nullptr, indxBuffer.size()});
rDrawTerrainGl.indxBufGL.setData(indxBuffer);
rDrawTerrainGl.vrtxBufGL.setData({nullptr, vrtxBuffer.size()});
rDrawTerrainGl.vrtxBufGL.setData(vrtxBuffer);
});
}); // ftrShaderPhong

Just need to add equivalent logic in https://github.com/TheOpenSpaceProgram/osp-magnum/blob/master/src/gdextension/sessions/godot.cpp
(note: folder name here should be "features" instead of "sessions". godot stuff needs a lot of cleanup in general)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestplannedLikely a requirement for a 'final' product

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions