|
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 |
|
|
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
ftrTerrainDrawMagnumfeature simply does the OpenGL/Magnum-specific logic to send this to the GPU:osp-magnum/src/testapp/features/magnum.cpp
Lines 518 to 626 in 9939731
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)