From 3083df450f22794e7cacb3ed3461aae5a8ec6bd7 Mon Sep 17 00:00:00 2001 From: vlj Date: Mon, 25 Aug 2014 18:20:37 +0200 Subject: [PATCH] Gather object in instanced calls --- data/shaders/glow_object.frag | 8 + data/shaders/glow_object.vert | 24 + data/shaders/instanced_rsm.frag | 27 + data/shaders/instanced_rsm.vert | 39 ++ src/graphics/glwrap.cpp | 79 ++- src/graphics/glwrap.hpp | 44 +- src/graphics/gpuparticles.cpp | 6 + src/graphics/gpuparticles.hpp | 1 + src/graphics/irr_driver.cpp | 15 +- src/graphics/irr_driver.hpp | 4 + src/graphics/render.cpp | 76 ++- src/graphics/render_geometry.cpp | 655 ++++++++++--------------- src/graphics/shaders.cpp | 26 + src/graphics/shaders.hpp | 12 + src/graphics/stkanimatedmesh.cpp | 4 +- src/graphics/stkanimatedmesh.hpp | 3 +- src/graphics/stkinstancedscenenode.cpp | 6 +- src/graphics/stkinstancedscenenode.hpp | 12 - src/graphics/stkmesh.cpp | 3 +- src/graphics/stkmesh.hpp | 85 +++- src/graphics/stkmeshscenenode.cpp | 156 +++--- src/graphics/stkmeshscenenode.hpp | 5 + src/graphics/stkscenemanager.cpp | 634 ++++++++++++++++++++++++ src/graphics/stkscenemanager.hpp | 32 +- 24 files changed, 1392 insertions(+), 564 deletions(-) create mode 100644 data/shaders/glow_object.frag create mode 100644 data/shaders/glow_object.vert create mode 100644 data/shaders/instanced_rsm.frag create mode 100644 data/shaders/instanced_rsm.vert create mode 100644 src/graphics/stkscenemanager.cpp diff --git a/data/shaders/glow_object.frag b/data/shaders/glow_object.frag new file mode 100644 index 000000000..ca2f881dc --- /dev/null +++ b/data/shaders/glow_object.frag @@ -0,0 +1,8 @@ +in vec4 glowColor; + +flat out vec4 FragColor; + +void main() +{ + FragColor = vec4(glowColor.rgb, 1.0); +} diff --git a/data/shaders/glow_object.vert b/data/shaders/glow_object.vert new file mode 100644 index 000000000..703529317 --- /dev/null +++ b/data/shaders/glow_object.vert @@ -0,0 +1,24 @@ +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec2 Texcoord; +layout(location = 5) in vec3 Tangent; +layout(location = 6) in vec3 Bitangent; + +layout(location = 7) in vec3 Origin; +layout(location = 8) in vec3 Orientation; +layout(location = 9) in vec3 Scale; +layout(location = 12) in vec4 GlowColor; + +flat out vec4 glowColor; + +mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); +mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); + +void main(void) +{ + mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); + mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix); + gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.); + glowColor = GlowColor; +} diff --git a/data/shaders/instanced_rsm.frag b/data/shaders/instanced_rsm.frag new file mode 100644 index 000000000..a5f82d259 --- /dev/null +++ b/data/shaders/instanced_rsm.frag @@ -0,0 +1,27 @@ +#ifndef GL_ARB_bindless_texture +uniform sampler2D tex; +#endif + +in vec2 uv; +in vec3 nor; +in vec4 color; +#ifdef GL_ARB_bindless_texture +flat in uvec2 handle; +#endif +layout (location = 0) out vec3 RSMColor; +layout (location = 1) out vec3 RSMNormals; + +void main() +{ +#ifdef GL_ARB_bindless_texture + vec4 col = texture(sampler2D(handle), uv); +#ifdef SRGBBindlessFix + col.xyz = pow(col.xyz, vec3(2.2)); +#endif +#else + vec4 col = texture(tex, uv); +#endif + if (col.a < .5) discard; + RSMColor = col.xyz * color.rgb; + RSMNormals = .5 * normalize(nor) + .5; +} diff --git a/data/shaders/instanced_rsm.vert b/data/shaders/instanced_rsm.vert new file mode 100644 index 000000000..fc84a79ed --- /dev/null +++ b/data/shaders/instanced_rsm.vert @@ -0,0 +1,39 @@ +uniform mat4 RSMMatrix; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec2 Texcoord; +layout(location = 4) in vec2 SecondTexcoord; +layout(location = 7) in vec3 Origin; +layout(location = 8) in vec3 Orientation; +layout(location = 9) in vec3 Scale; +#ifdef GL_ARB_bindless_texture +layout(location = 10) in uvec2 Handle; +#endif + +out vec3 nor; +out vec2 uv; +out vec2 uv_bis; +out vec4 color; +#ifdef GL_ARB_bindless_texture +flat out uvec2 handle; +#endif + + +mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); +mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); + +void main(void) +{ + mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); + mat4 ModelViewProjectionMatrix = RSMMatrix * ModelMatrix; + mat4 TransposeInverseModel = transpose(inverse(ModelMatrix)); + gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); + nor = (TransposeInverseModel * vec4(Normal, 0.)).xyz; + uv = Texcoord; + color = Color.zyxw; +#ifdef GL_ARB_bindless_texture + handle = Handle; +#endif +} diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index f83f02948..fcdcf2372 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -601,9 +601,22 @@ VAOManager::VAOManager() idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL; instance_count[0] = 0; - glGenBuffers(1, &instance_vbo[0]); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[0]); - glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(float)* 9, 0, GL_STATIC_DRAW); + for (unsigned i = 0; i < InstanceTypeCount; i++) + { + glGenBuffers(1, &instance_vbo[i]); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]); +#ifdef Buffer_Storage + if (irr_driver->hasBufferStorageExtension()) + { + glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + } + else +#endif + { + glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_STREAM_DRAW); + } + } } static void cleanVAOMap(std::map, GLuint> Map) @@ -618,9 +631,7 @@ static void cleanVAOMap(std::map, void VAOManager::cleanInstanceVAOs() { cleanVAOMap(InstanceVAO); - cleanVAOMap(ShadowInstanceVAO); InstanceVAO.clear(); - ShadowInstanceVAO.clear(); } VAOManager::~VAOManager() @@ -639,7 +650,11 @@ VAOManager::~VAOManager() if (vao[i]) glDeleteVertexArrays(1, &vao[i]); } - glDeleteBuffers(1, &instance_vbo[0]); + for (unsigned i = 0; i < InstanceTypeCount; i++) + { + glDeleteBuffers(1, &instance_vbo[i]); + } + } void VAOManager::regenerateBuffer(enum VTXTYPE tp) @@ -743,13 +758,11 @@ void VAOManager::regenerateInstancedVAO() enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS }; for (unsigned i = 0; i < VTXTYPE_COUNT; i++) { - for (unsigned j = 0; j < InstanceTypeCount; j++) - { video::E_VERTEX_TYPE tp = IrrVT[i]; if (!vbo[tp] || !ibo[tp]) continue; GLuint vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[j]); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeDefault]); glEnableVertexAttribArray(7); glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); @@ -766,10 +779,10 @@ void VAOManager::regenerateInstancedVAO() glEnableVertexAttribArray(11); glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); glVertexAttribDivisor(11, 1); - InstanceVAO[std::pair(tp, (InstanceType) j)] = vao; + InstanceVAO[std::pair(tp, InstanceTypeDefault)] = vao; - GLuint shadow_vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[j]); + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]); glEnableVertexAttribArray(7); glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); @@ -784,11 +797,47 @@ void VAOManager::regenerateInstancedVAO() glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); - glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float)+2 * sizeof(unsigned))); + glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); glVertexAttribDivisor(11, 1); - ShadowInstanceVAO[std::pair(tp, (InstanceType)j)] = shadow_vao; + InstanceVAO[std::pair(tp, InstanceTypeShadow)] = vao; + + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); + glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); + glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); + glVertexAttribDivisor(11, 1); + InstanceVAO[std::pair(tp, InstanceTypeRSM)] = vao; + + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(12); + glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(12, 1); + InstanceVAO[std::pair(tp, InstanceTypeGlow)] = vao; glBindVertexArray(0); - } } diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index d973321d3..273cbdcb0 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -142,6 +142,9 @@ void saveCompressedTexture(const std::string& compressed_tex); enum InstanceType { InstanceTypeDefault, + InstanceTypeShadow, + InstanceTypeRSM, + InstanceTypeGlow, InstanceTypeCount, }; @@ -172,23 +175,53 @@ struct InstanceData uint64_t SecondTexture; #ifdef WIN32 }; -#pragma pack(pop) #else } __attribute__((packed)); #endif +struct GlowInstanceData +{ + struct + { + float X; + float Y; + float Z; + } Origin; + struct + { + float X; + float Y; + float Z; + } Orientation; + struct + { + float X; + float Y; + float Z; + } Scale; + unsigned Color; +#ifdef WIN32 +}; +#else +} __attribute__((packed)); +#endif +#ifdef WIN32 +#pragma pack(pop) +#endif + class VAOManager : public Singleton { enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT }; GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT]; - GLuint instance_vbo[1]; - size_t instance_count[1]; + GLuint instance_vbo[InstanceTypeCount]; + size_t instance_count[InstanceTypeCount]; + void *Ptr[InstanceTypeCount]; void *VBOPtr[VTXTYPE_COUNT]; std::vector storedCPUBuffer[VTXTYPE_COUNT]; void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT]; size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT]; std::map mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT]; - std::map, GLuint> InstanceVAO, ShadowInstanceVAO; + std::map, GLuint> InstanceVAO; void cleanInstanceVAOs(); void regenerateBuffer(enum VTXTYPE); @@ -201,11 +234,12 @@ public: VAOManager(); std::pair getBase(scene::IMeshBuffer *); size_t appendInstance(enum InstanceType, const std::vector &instance_data); + GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; } + void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; } unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; } void *getVBOPtr(video::E_VERTEX_TYPE type) { return VBOPtr[getVTXTYPE(type)]; } unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; } unsigned getInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return InstanceVAO[std::pair(vt, it)]; } - unsigned getShadowInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return ShadowInstanceVAO[std::pair(vt, it)]; } ~VAOManager(); }; diff --git a/src/graphics/gpuparticles.cpp b/src/graphics/gpuparticles.cpp index 563852110..6108aa0a7 100644 --- a/src/graphics/gpuparticles.cpp +++ b/src/graphics/gpuparticles.cpp @@ -449,6 +449,12 @@ void ParticleSystemProxy::render() { draw(); } +bool ParticleSystemProxy::update() +{ + doParticleSystem(os::Timer::getTime()); + return (IsVisible && (Particles.size() != 0)); +} + void ParticleSystemProxy::OnRegisterSceneNode() { doParticleSystem(os::Timer::getTime()); diff --git a/src/graphics/gpuparticles.hpp b/src/graphics/gpuparticles.hpp index 84fd72fab..94ca75f81 100644 --- a/src/graphics/gpuparticles.hpp +++ b/src/graphics/gpuparticles.hpp @@ -81,6 +81,7 @@ public: const float* getColorTo() const { return m_color_to; } void setHeightmap(const std::vector >&, float, float, float, float); void setFlip(); + bool update(); }; #endif // GPUPARTICLES_H diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 8f2b9698a..16ff20163 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -166,6 +166,11 @@ void IrrDriver::IncreaseObjectCount() object_count[m_phase]++; } +void IrrDriver::IncreasePolyCount(unsigned Polys) +{ + poly_count[m_phase] += Polys; +} + core::array &IrrDriver::getMainSetup() { return m_mrt; @@ -1631,6 +1636,7 @@ video::ITexture* IrrDriver::applyMask(video::ITexture* texture, // ---------------------------------------------------------------------------- void IrrDriver::setRTT(RTT* rtt) { + memset(m_shadow_camnodes, 0, 4 * sizeof(void*)); m_rtts = rtt; } // ---------------------------------------------------------------------------- @@ -1733,13 +1739,14 @@ void IrrDriver::displayFPS() if (UserConfigParams::m_artist_debug_mode) { sprintf( - buffer, "FPS: %i/%i/%i - Objects (P1:%d P2:%d T:%d) - LightDst : ~%d", + buffer, "FPS: %i/%i/%i - PolyCount (Solid:%d Shadows:%d) - LightDst : ~%d", min, fps, max, - object_count[SOLID_NORMAL_AND_DEPTH_PASS], - object_count[SOLID_NORMAL_AND_DEPTH_PASS], - object_count[TRANSPARENT_PASS], + poly_count[SOLID_NORMAL_AND_DEPTH_PASS], + poly_count[SHADOW_PASS], m_last_light_bucket_distance ); + poly_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0; + poly_count[SHADOW_PASS] = 0; object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0; object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0; object_count[TRANSPARENT_PASS] = 0; diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 1d2710cc0..3e5a671e9 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -359,12 +359,14 @@ private: /** Performance stats */ unsigned m_last_light_bucket_distance; unsigned object_count[PASS_COUNT]; + unsigned poly_count[PASS_COUNT]; u32 m_renderpass; u32 m_lensflare_query; bool m_query_issued; class STKMeshSceneNode *m_sun_interposer; scene::CLensFlareSceneNode *m_lensflare; scene::ICameraSceneNode *m_suncam; + scene::ICameraSceneNode *m_shadow_camnodes[4]; float m_shadows_cam[4][24]; std::vector m_glowing; @@ -406,6 +408,7 @@ private: void renderLights(unsigned pointlightCount); void renderShadowsDebug(); void doScreenShot(); + void PrepareDrawCalls(); public: IrrDriver(); ~IrrDriver(); @@ -421,6 +424,7 @@ public: return sun_ortho_matrix; } void IncreaseObjectCount(); + void IncreasePolyCount(unsigned); core::array &getMainSetup(); void updateConfigIfRelevant(); void setAllMaterialFlags(scene::IMesh *mesh) const; diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index f3f830fd6..18c97b305 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -47,6 +47,7 @@ #include "utils/helpers.hpp" #include "utils/log.hpp" #include "utils/profiler.hpp" +#include "stkscenemanager.hpp" #include #include @@ -269,10 +270,35 @@ void IrrDriver::renderGLSL(float dt) getPostProcessing()->update(dt); } +static GLsync m_sync; + void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector& glows, float dt, bool hasShadow, bool forceRTT) { glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO); + m_scene_manager->setActiveCamera(camnode); + // Add a 1 s timeout + if (!m_sync) + m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000000); + /* switch (reason) + { + case GL_ALREADY_SIGNALED: + printf("Already Signaled\n"); + break; + case GL_TIMEOUT_EXPIRED: + printf("Timeout Expired\n"); + break; + case GL_CONDITION_SATISFIED: + printf("Condition Satisfied\n"); + break; + case GL_WAIT_FAILED: + printf("Wait Failed\n"); + break; + }*/ + PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF); + PrepareDrawCalls(); + PROFILER_POP_CPU_MARKER(); // Shadows { PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90); @@ -323,6 +349,8 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po renderSolidSecondPass(); PROFILER_POP_CPU_MARKER(); + m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + if (getNormals()) { m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind(); @@ -514,7 +542,9 @@ void IrrDriver::renderParticles() glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT); + for (unsigned i = 0; i < ParticlesList::getInstance()->size(); ++i) + ParticlesList::getInstance()->at(i)->render(); +// m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT); } /** Given a matrix transform and a set of points returns an orthogonal projection matrix that maps coordinates of @@ -593,6 +623,11 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float)); const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix(); + for (unsigned i = 0; i < 4; i++) + { + if (!m_shadow_camnodes[i]) + m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone(); + } sun_ortho_matrix.clear(); if (World::getWorld() && World::getWorld()->getTrack()) @@ -670,8 +705,8 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz const float units_per_w = w / 1024; const float units_per_h = h / 1024;*/ - m_suncam->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true); - m_suncam->render(); + m_shadow_camnodes[i]->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true); + m_shadow_camnodes[i]->render(); sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW)); } @@ -773,16 +808,35 @@ void IrrDriver::renderGlow(std::vector& glows) for (u32 i = 0; i < glowcount; i++) { const GlowData &dat = glows[i]; - scene::ISceneNode * const cur = dat.node; + scene::ISceneNode * cur = dat.node; - //TODO : implement culling on gpu - // Quick box-based culling -// const core::aabbox3df nodebox = cur->getTransformedBoundingBox(); -// if (!nodebox.intersectsWithBox(cambox)) -// continue; + STKMeshSceneNode *node = static_cast(cur); + node->setGlowColors(SColor(0, dat.b * 255.f, dat.g * 255.f, dat.r * 255.f)); + if (!irr_driver->hasARB_draw_indirect()) + node->render(); + } - cb->setColor(dat.r, dat.g, dat.b); - cur->render(); + if (irr_driver->hasARB_draw_indirect()) + { + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd); + glUseProgram(MeshShader::InstancedColorizeShader::getInstance()->Program); + + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeGlow)); + if (UserConfigParams::m_azdo) + { + if (GlowPassCmd::getInstance()->Size) + { + glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, + (const void*)(GlowPassCmd::getInstance()->Offset * sizeof(DrawElementsIndirectCommand)), + GlowPassCmd::getInstance()->Size, + sizeof(DrawElementsIndirectCommand)); + } + } + else + { + for (unsigned i = 0; i < ListInstancedGlow::getInstance()->size(); i++) + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((GlowPassCmd::getInstance()->Offset + i) * sizeof(DrawElementsIndirectCommand))); + } } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index 77122a46a..a5192585d 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -117,16 +117,16 @@ struct custom_unroll_args template -void renderMeshes1stPass(const std::vector &TexUnits, std::vector > *meshes) +void renderMeshes1stPass(const std::vector &TexUnits, std::vector > &meshes) { glUseProgram(Shader::getInstance()->Program); if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType)); - for (unsigned i = 0; i < meshes->size(); i++) + for (unsigned i = 0; i < meshes.size(); i++) { std::vector Textures; std::vector Handles; - GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i))); + GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i))); if (!irr_driver->hasARB_base_instance()) glBindVertexArray(mesh.vao); for (unsigned j = 0; j < TexUnits.size(); j++) @@ -148,68 +148,33 @@ void renderMeshes1stPass(const std::vector &TexUnits, std::vectorSetTextureHandles(Handles); else Shader::getInstance()->SetTextureUnits(Textures); - custom_unroll_args::template exec(Shader::getInstance(), meshes->at(i)); + custom_unroll_args::template exec(Shader::getInstance(), meshes.at(i)); } } -template -struct instanced_custom_unroll_args; - -template<> -struct instanced_custom_unroll_args<> -{ - template - static void exec(const T *Shader, const STK::Tuple &t, Args... args) - { - const GLMesh *mesh = STK::tuple_get<0>(t); - size_t instance_count = STK::tuple_get<1>(t); - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh->PrimitiveType; - GLenum itype = mesh->IndexType; - size_t count = mesh->IndexCount; - - Shader->setUniforms(args...); -#ifdef Base_Instance_Support - if (irr_driver->hasARB_base_instance()) - glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*)mesh->vaoOffset, instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance); - else -#endif - glDrawElementsInstanced(ptype, count, itype, 0, instance_count); - } -}; - -template -struct instanced_custom_unroll_args -{ - template - static void exec(const T *Shader, const STK::Tuple &t, Args... args) - { - instanced_custom_unroll_args::template exec(Shader, t, STK::tuple_get(t), args...); - } -}; - -template -void renderInstancedMeshes1stPass(const std::vector &TexUnits, std::vector > *meshes) +#ifdef Draw_Indirect +template +void renderInstancedMeshes1stPass(const std::vector &TexUnits, std::vector &meshes, Args...args) { glUseProgram(Shader::getInstance()->Program); - for (unsigned i = 0; i < meshes->size(); i++) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault)); + for (unsigned i = 0; i < meshes.size(); i++) { std::vector Textures; - GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i))); + GLMesh *mesh = meshes[i]; #ifdef DEBUG - if (mesh.VAOType != VertexType) + if (mesh->VAOType != VT) Log::error("RenderGeometry", "Wrong instanced vertex format"); #endif - if (!irr_driver->hasARB_base_instance()) - glBindVertexArray(mesh.vao); for (unsigned j = 0; j < TexUnits.size(); j++) - Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id])); + Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j].m_id])); Shader::getInstance()->SetTextureUnits(Textures); - instanced_custom_unroll_args::template exec(Shader::getInstance(), meshes->at(i)); + + Shader::getInstance()->setUniforms(args...); + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand))); } } - -static GLsync m_sync; +#endif #ifdef Multi_Draw_Indirect template @@ -228,9 +193,11 @@ void multidraw1stPass(Args...args) } #endif +static core::vector3df windDir; void IrrDriver::renderSolidFirstPass() { + windDir = getWindDir(); m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind(); glClearColor(0., 0., 0., 0.); glDepthMask(GL_TRUE); @@ -241,166 +208,88 @@ void IrrDriver::renderSolidFirstPass() glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); - irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); - ListMatDefault::getInstance()->clear(); - ListMatAlphaRef::getInstance()->clear(); - ListMatSphereMap::getInstance()->clear(); - ListMatDetails::getInstance()->clear(); - ListMatUnlit::getInstance()->clear(); - ListMatNormalMap::getInstance()->clear(); - ListMatGrass::getInstance()->clear(); - ListMatSplatting::getInstance()->clear(); - ListInstancedMatDefault::getInstance()->clear(); - ListInstancedMatAlphaRef::getInstance()->clear(); - ListInstancedMatGrass::getInstance()->clear(); - ListInstancedMatNormalMap::getInstance()->clear(); - // Add a 30 ms timeout - if (!m_sync) - m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 30000000); -/* switch (reason) - { - case GL_ALREADY_SIGNALED: - printf("Already Signaled\n"); - break; - case GL_TIMEOUT_EXPIRED: - printf("Timeout Expired\n"); - break; - case GL_CONDITION_SATISFIED: - printf("Condition Satisfied\n"); - break; - case GL_WAIT_FAILED: - printf("Wait Failed\n"); - break; - }*/ - m_scene_manager->drawAll(scene::ESNRP_SOLID); if (!UserConfigParams::m_dynamic_lights) return; { ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1)); + irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); + + for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++) + ImmediateDrawList::getInstance()->at(i)->render(); std::vector object_pass1_texunits = TexUnits(TexUnit(0, true) ); - renderMeshes1stPass(object_pass1_texunits, ListMatDefault::getInstance()); - renderMeshes1stPass(object_pass1_texunits, ListMatSphereMap::getInstance()); - renderMeshes1stPass(object_pass1_texunits, ListMatDetails::getInstance()); - renderMeshes1stPass(object_pass1_texunits, ListMatSplatting::getInstance()); - renderMeshes1stPass(object_pass1_texunits, ListMatUnlit::getInstance()); - renderMeshes1stPass(TexUnits(TexUnit(0, true)), ListMatAlphaRef::getInstance()); - renderMeshes1stPass(TexUnits(TexUnit(0, true)), ListMatGrass::getInstance()); + renderMeshes1stPass(object_pass1_texunits, ListMatDefault::getInstance()->SolidPass); + renderMeshes1stPass(object_pass1_texunits, ListMatSplatting::getInstance()->SolidPass); + renderMeshes1stPass(object_pass1_texunits, ListMatUnlit::getInstance()->SolidPass); + renderMeshes1stPass(TexUnits(TexUnit(0, true)), ListMatAlphaRef::getInstance()->SolidPass); + renderMeshes1stPass(TexUnits(TexUnit(0, true)), ListMatGrass::getInstance()->SolidPass); renderMeshes1stPass(TexUnits( TexUnit(1, false), TexUnit(0, true) - ), ListMatNormalMap::getInstance()); + ), ListMatNormalMap::getInstance()->SolidPass); + renderMeshes1stPass(object_pass1_texunits, ListMatSphereMap::getInstance()->SolidPass); + renderMeshes1stPass(object_pass1_texunits, ListMatDetails::getInstance()->SolidPass); + + if (irr_driver->hasARB_draw_indirect()) + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd); if (UserConfigParams::m_azdo) { - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd); - DrawElementsIndirectCommand *CommandBufferPtr = SolidPassCmd::getInstance()->Ptr; - - size_t offset = 0; - SolidPassCmd::getInstance()->Offset[MAT_DEFAULT] = offset; - for (unsigned i = 0; i < ListInstancedMatDefault::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatDefault::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatDefault::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = CommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - SolidPassCmd::getInstance()->Size[MAT_DEFAULT] = ListInstancedMatDefault::getInstance()->size(); - - SolidPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = offset; - for (unsigned i = 0; i < ListInstancedMatNormalMap::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatNormalMap::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatNormalMap::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = CommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - SolidPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = ListInstancedMatNormalMap::getInstance()->size(); - - SolidPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = offset; - for (unsigned i = 0; i < ListInstancedMatAlphaRef::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatAlphaRef::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatAlphaRef::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = CommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - SolidPassCmd::getInstance()->Size[MAT_ALPHA_REF] = ListInstancedMatAlphaRef::getInstance()->size(); - - SolidPassCmd::getInstance()->Offset[MAT_GRASS] = offset; - for (unsigned i = 0; i < ListInstancedMatGrass::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatGrass::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatGrass::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = CommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - SolidPassCmd::getInstance()->Size[MAT_GRASS] = ListInstancedMatGrass::getInstance()->size(); #ifdef Multi_Draw_Indirect multidraw1stPass(); multidraw1stPass(); multidraw1stPass(); - core::vector3df dir = ListInstancedMatGrass::getInstance()->empty() ? core::vector3df(0., 0., 0.) : STK::tuple_get<2>(ListInstancedMatGrass::getInstance()->at(0)); - multidraw1stPass(dir); + multidraw1stPass(); + multidraw1stPass(); + multidraw1stPass(); + multidraw1stPass(windDir); #endif } - else +#ifdef Draw_Indirect + else if (irr_driver->hasARB_draw_indirect()) { - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedMeshes1stPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatDefault::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedMeshes1stPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatAlphaRef::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedMeshes1stPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatGrass::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); - renderInstancedMeshes1stPass( - TexUnits(TexUnit(1, false), TexUnit(0, true)), - ListInstancedMatNormalMap::getInstance()); + // Default + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatDefault::getInstance()->SolidPass); + // Alpha ref + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatAlphaRef::getInstance()->SolidPass); + // Unlit + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatUnlit::getInstance()->SolidPass); + // Spheremap + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatSphereMap::getInstance()->SolidPass); + // Grass + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatGrass::getInstance()->SolidPass, windDir); + + // Detail + renderInstancedMeshes1stPass( + TexUnits(TexUnit(0, true)), ListInstancedMatDetails::getInstance()->SolidPass); + + // Normal Map + renderInstancedMeshes1stPass( + TexUnits(TexUnit(1, false), TexUnit(0, true)), ListInstancedMatNormalMap::getInstance()->SolidPass); } +#endif } } template -void renderMeshes2ndPass(const std::vector &TexUnits, std::vector > *meshes, const std::vector &Prefilled_Handle, +void renderMeshes2ndPass(const std::vector &TexUnits, std::vector > &meshes, const std::vector &Prefilled_Handle, const std::vector &Prefilled_Tex) { glUseProgram(Shader::getInstance()->Program); if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType)); - for (unsigned i = 0; i < meshes->size(); i++) + for (unsigned i = 0; i < meshes.size(); i++) { std::vector Handles(Prefilled_Handle); std::vector Textures(Prefilled_Tex); - GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i))); + GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i))); if (!irr_driver->hasARB_base_instance()) glBindVertexArray(mesh.vao); for (unsigned j = 0; j < TexUnits.size(); j++) @@ -423,27 +312,28 @@ void renderMeshes2ndPass(const std::vector &TexUnits, std::vectorSetTextureHandles(Handles); else Shader::getInstance()->SetTextureUnits(Textures); - custom_unroll_args::template exec(Shader::getInstance(), meshes->at(i)); + custom_unroll_args::template exec(Shader::getInstance(), meshes.at(i)); } } -template -void renderInstancedMeshes2ndPass(const std::vector &TexUnits, std::vector > *meshes, const std::vector &Prefilled_tex) +#ifdef Draw_Indirect +template +void renderInstancedMeshes2ndPass(const std::vector &TexUnits, const std::vector &Prefilled_tex, std::vector &meshes, Args...args) { glUseProgram(Shader::getInstance()->Program); - for (unsigned i = 0; i < meshes->size(); i++) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault)); + for (unsigned i = 0; i < meshes.size(); i++) { - GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i))); - if (!irr_driver->hasARB_base_instance()) - glBindVertexArray(mesh.vao); - + GLMesh *mesh = meshes[i]; std::vector Textures(Prefilled_tex); for (unsigned j = 0; j < TexUnits.size(); j++) - Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id])); + Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j].m_id])); Shader::getInstance()->SetTextureUnits(Textures); - instanced_custom_unroll_args::template exec(Shader::getInstance(), meshes->at(i)); + Shader::getInstance()->setUniforms(args...); + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand))); } } +#endif #ifdef Multi_Draw_Indirect template @@ -463,7 +353,6 @@ void multidraw2ndPass(const std::vector &Handles, Args... args) } #endif - void IrrDriver::renderSolidSecondPass() { SColor clearColor(0, 150, 150, 150); @@ -513,41 +402,43 @@ void IrrDriver::renderSolidSecondPass() { ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2)); - m_scene_manager->drawAll(scene::ESNRP_SOLID); + irr_driver->setPhase(SOLID_LIT_PASS); + + for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++) + ImmediateDrawList::getInstance()->at(i)->render(); std::vector DiffSpecSSAOTex = createVector(m_rtts->getRenderTarget(RTT_DIFFUSE), m_rtts->getRenderTarget(RTT_SPECULAR), m_rtts->getRenderTarget(RTT_HALF1_R)); renderMeshes2ndPass(TexUnits( TexUnit(0, true) - ), ListMatDefault::getInstance(), + ), ListMatDefault::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); renderMeshes2ndPass(TexUnits( TexUnit(0, true) - ), ListMatAlphaRef::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); - renderMeshes2ndPass(TexUnits( - TexUnit(0, true) - ), ListMatSphereMap::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); - renderMeshes2ndPass(TexUnits( - TexUnit(0, true), - TexUnit(1, true) - ), ListMatDetails::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); - renderMeshes2ndPass(TexUnits( - TexUnit(0, true) - ), ListMatGrass::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + ), ListMatAlphaRef::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); renderMeshes2ndPass(TexUnits( TexUnit(0, true) - ), ListMatUnlit::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); - + ), ListMatUnlit::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); renderMeshes2ndPass(TexUnits( TexUnit(1, false), TexUnit(2, true), TexUnit(3, true), TexUnit(4, true), TexUnit(5, true) - ), ListMatSplatting::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + ), ListMatSplatting::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + renderMeshes2ndPass(TexUnits( + TexUnit(0, true) + ), ListMatSphereMap::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + renderMeshes2ndPass(TexUnits( + TexUnit(0, true), + TexUnit(1, true) + ), ListMatDetails::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + renderMeshes2ndPass(TexUnits( + TexUnit(0, true) + ), ListMatGrass::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); renderMeshes2ndPass(TexUnits( TexUnit(0, true) - ), ListMatNormalMap::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + ), ListMatNormalMap::getInstance()->SolidPass, createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); if (UserConfigParams::m_azdo) { @@ -555,38 +446,44 @@ void IrrDriver::renderSolidSecondPass() multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0)); multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0)); multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0)); - core::vector3df dir = ListInstancedMatGrass::getInstance()->empty() ? core::vector3df(0., 0., 0.) : STK::tuple_get<2>(ListInstancedMatGrass::getInstance()->at(0)); + multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0)); + multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0)); + multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, 0)); SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT); - multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0), dir, cb->getPosition()); + multidraw2ndPass(createVector(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0), windDir, cb->getPosition()); #endif } - else +#ifdef Draw_Indirect + else if (irr_driver->hasARB_draw_indirect()) { - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedMeshes2ndPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatDefault::getInstance(), DiffSpecSSAOTex); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); - renderInstancedMeshes2ndPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatNormalMap::getInstance(), DiffSpecSSAOTex); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedMeshes2ndPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatAlphaRef::getInstance(), DiffSpecSSAOTex); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture()); - renderInstancedMeshes2ndPass( - TexUnits(TexUnit(0, true)), - ListInstancedMatGrass::getInstance(), DiffSpecSSAOTex); - } + // Default + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatDefault::getInstance()->SolidPass); + // Alpha ref + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatAlphaRef::getInstance()->SolidPass); + // Unlit + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatUnlit::getInstance()->SolidPass); + // Spheremap + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatSphereMap::getInstance()->SolidPass); + // Details + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true), TexUnit(1, false)), DiffSpecSSAOTex, ListInstancedMatDetails::getInstance()->SolidPass); + // Normal map + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatNormalMap::getInstance()->SolidPass); + + // Grass + SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT); + DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture()); + renderInstancedMeshes2ndPass( + TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatGrass::getInstance()->SolidPass, windDir, cb->getPosition()); + } +#endif } - m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } template @@ -611,15 +508,14 @@ static void renderMeshNormals(std::vector > *meshes) void IrrDriver::renderNormalsVisualisation() { - renderMeshNormals(ListMatDefault::getInstance()); - renderMeshNormals(ListMatAlphaRef::getInstance()); - renderMeshNormals(ListMatSphereMap::getInstance()); +// renderMeshNormals(ListMatDefault::getInstance()); +// renderMeshNormals(ListMatAlphaRef::getInstance()); +// renderMeshNormals(ListMatSphereMap::getInstance()); // renderMeshNormals(ListMatGrass::getInstance()); - renderMeshNormals(ListMatDetails::getInstance()); - renderMeshNormals(ListMatUnlit::getInstance()); - renderMeshNormals(ListMatSplatting::getInstance()); - renderMeshNormals(ListMatNormalMap::getInstance()); - +// renderMeshNormals(ListMatDetails::getInstance()); +// renderMeshNormals(ListMatUnlit::getInstance()); +// renderMeshNormals(ListMatSplatting::getInstance()); +// renderMeshNormals(ListMatNormalMap::getInstance()); } template @@ -674,19 +570,17 @@ static video::ITexture *displaceTex = 0; void IrrDriver::renderTransparent() { - irr_driver->setPhase(TRANSPARENT_PASS); glEnable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glDisable(GL_CULL_FACE); - ListBlendTransparent::getInstance()->clear(); - ListAdditiveTransparent::getInstance()->clear(); - ListBlendTransparentFog::getInstance()->clear(); - ListAdditiveTransparentFog::getInstance()->clear(); - ListDisplacement::getInstance()->clear(); - m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT); + + irr_driver->setPhase(TRANSPARENT_PASS); + + for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++) + ImmediateDrawList::getInstance()->at(i)->render(); if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_STANDARD)); @@ -831,16 +725,16 @@ struct shadow_custom_unroll_args }; template -void renderShadow(const std::vector TextureUnits, unsigned cascade, const std::vector > *t) +void renderShadow(const std::vector TextureUnits, unsigned cascade, const std::vector > &t) { glUseProgram(T::getInstance()->Program); if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType)); - for (unsigned i = 0; i < t->size(); i++) + for (unsigned i = 0; i < t.size(); i++) { std::vector Handles; std::vector Textures; - GLMesh *mesh = STK::tuple_get<0>(t->at(i)); + GLMesh *mesh = STK::tuple_get<0>(t.at(i)); if (!irr_driver->hasARB_base_instance()) glBindVertexArray(mesh->vao); for (unsigned j = 0; j < TextureUnits.size(); j++) @@ -855,73 +749,39 @@ void renderShadow(const std::vector TextureUnits, unsigned cascade, cons T::getInstance()->SetTextureHandles(Handles); else T::getInstance()->SetTextureUnits(Textures); - shadow_custom_unroll_args::template exec(T::getInstance(), cascade, t->at(i)); + shadow_custom_unroll_args::template exec(T::getInstance(), cascade, t.at(i)); } } -template -struct instanced_shadow_custom_unroll_args; - -template<> -struct instanced_shadow_custom_unroll_args<> +#ifdef Draw_Indirect +template +void renderInstancedShadow(const std::vector TextureUnits, unsigned cascade, const std::vector &t, Args ...args) { - template - static void exec(const T *Shader, unsigned cascade, const STK::Tuple &t, Args... args) - { - const GLMesh *mesh = STK::tuple_get<0>(t); - size_t instance_count = STK::tuple_get<1>(t); - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh->PrimitiveType; - GLenum itype = mesh->IndexType; - size_t count = mesh->IndexCount; - - Shader->setUniforms(cascade, args...); -#ifdef Base_Instance_Support - if (irr_driver->hasARB_base_instance()) - glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*) mesh->vaoOffset, instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance); - else -#endif - glDrawElementsInstanced(ptype, count, itype, 0, instance_count); - } -}; - -template -struct instanced_shadow_custom_unroll_args -{ - template - static void exec(const T *Shader, unsigned cascade, const STK::Tuple &t, Args... args) - { - instanced_shadow_custom_unroll_args::template exec(Shader, cascade, t, STK::tuple_get(t), args...); - } -}; - -template -void renderInstancedShadow(const std::vector TextureUnits, unsigned cascade, const std::vector > *t) -{ - glUseProgram(T::getInstance()->Program); - for (unsigned i = 0; i < t->size(); i++) + glUseProgram(Shader::getInstance()->Program); + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow)); + for (unsigned i = 0; i < t.size(); i++) { std::vector Handles; std::vector Textures; - GLMesh *mesh = STK::tuple_get<0>(t->at(i)); - if (!irr_driver->hasARB_base_instance()) - glBindVertexArray(mesh->vao); + GLMesh *mesh = t[i]; for (unsigned j = 0; j < TextureUnits.size(); j++) Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]])); - T::getInstance()->SetTextureUnits(Textures); - instanced_shadow_custom_unroll_args::template exec(T::getInstance(), cascade, t->at(i)); + Shader::getInstance()->SetTextureUnits(Textures); + Shader::getInstance()->setUniforms(cascade, args...); + size_t tmp = ShadowPassCmd::getInstance()->Offset[cascade][Mat] + i; + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((tmp) * sizeof(DrawElementsIndirectCommand))); } } - +#endif #ifdef Multi_Draw_Indirect template static void multidrawShadow(unsigned i, Args ...args) { glUseProgram(Shader::getInstance()->Program); - glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(VT, InstanceTypeDefault)); + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow)); if (ShadowPassCmd::getInstance()->Size[i][Mat]) { Shader::getInstance()->setUniforms(i, args...); @@ -943,117 +803,46 @@ void IrrDriver::renderShadows() glClear(GL_DEPTH_BUFFER_BIT); glDrawBuffer(GL_NONE); - irr_driver->setPhase(SHADOW_PASS); - ListMatDefault::getInstance()->clear(); - ListMatAlphaRef::getInstance()->clear(); - ListMatSphereMap::getInstance()->clear(); - ListMatDetails::getInstance()->clear(); - ListMatUnlit::getInstance()->clear(); - ListMatNormalMap::getInstance()->clear(); - ListMatGrass::getInstance()->clear(); - ListMatSplatting::getInstance()->clear(); - ListInstancedMatDefault::getInstance()->clear(); - ListInstancedMatAlphaRef::getInstance()->clear(); - ListInstancedMatGrass::getInstance()->clear(); - ListInstancedMatNormalMap::getInstance()->clear(); - m_scene_manager->drawAll(scene::ESNRP_SOLID); - size_t offset = 0; for (unsigned cascade = 0; cascade < 4; cascade++) { + std::vector noTexUnits; - renderShadow(noTexUnits, cascade, ListMatDefault::getInstance()); - renderShadow(noTexUnits, cascade, ListMatSphereMap::getInstance()); - renderShadow(noTexUnits, cascade, ListMatDetails::getInstance()); - renderShadow(noTexUnits, cascade, ListMatSplatting::getInstance()); - renderShadow(noTexUnits, cascade, ListMatNormalMap::getInstance()); - renderShadow(std::vector{ 0 }, cascade, ListMatAlphaRef::getInstance()); - renderShadow(std::vector{ 0 }, cascade, ListMatUnlit::getInstance()); - renderShadow(std::vector{ 0 }, cascade, ListMatGrass::getInstance()); + + renderShadow(noTexUnits, cascade, ListMatDefault::getInstance()->Shadows[cascade]); + renderShadow(noTexUnits, cascade, ListMatSphereMap::getInstance()->Shadows[cascade]); + renderShadow(noTexUnits, cascade, ListMatDetails::getInstance()->Shadows[cascade]); + renderShadow(noTexUnits, cascade, ListMatSplatting::getInstance()->Shadows[cascade]); + renderShadow(noTexUnits, cascade, ListMatNormalMap::getInstance()->Shadows[cascade]); + renderShadow(std::vector{ 0 }, cascade, ListMatAlphaRef::getInstance()->Shadows[cascade]); + renderShadow(std::vector{ 0 }, cascade, ListMatUnlit::getInstance()->Shadows[cascade]); + renderShadow(std::vector{ 0 }, cascade, ListMatGrass::getInstance()->Shadows[cascade]); + + if (irr_driver->hasARB_draw_indirect()) + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ShadowPassCmd::getInstance()->drawindirectcmd); if (UserConfigParams::m_azdo) { - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ShadowPassCmd::getInstance()->drawindirectcmd); - DrawElementsIndirectCommand *ShadowCommandBufferPtr = ShadowPassCmd::getInstance()->Ptr; - - ShadowPassCmd::getInstance()->Offset[cascade][MAT_DEFAULT] = offset; - for (unsigned i = 0; i < ListInstancedMatDefault::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatDefault::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatDefault::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = ShadowCommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - ShadowPassCmd::getInstance()->Size[cascade][MAT_DEFAULT] = offset - ShadowPassCmd::getInstance()->Offset[cascade][MAT_DEFAULT]; - - ShadowPassCmd::getInstance()->Offset[cascade][MAT_NORMAL_MAP] = offset; - for (unsigned i = 0; i < ListInstancedMatNormalMap::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatNormalMap::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatNormalMap::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = ShadowCommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - ShadowPassCmd::getInstance()->Size[cascade][MAT_NORMAL_MAP] = offset - ShadowPassCmd::getInstance()->Offset[cascade][MAT_NORMAL_MAP]; - - ShadowPassCmd::getInstance()->Offset[cascade][MAT_ALPHA_REF] = offset; - for (unsigned i = 0; i < ListInstancedMatAlphaRef::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatAlphaRef::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatAlphaRef::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = ShadowCommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - ShadowPassCmd::getInstance()->Size[cascade][MAT_ALPHA_REF] = offset - ShadowPassCmd::getInstance()->Offset[cascade][MAT_ALPHA_REF]; - - ShadowPassCmd::getInstance()->Offset[cascade][MAT_GRASS] = offset; - for (unsigned i = 0; i < ListInstancedMatGrass::getInstance()->size(); i++) - { - const GLMesh &mesh = *(STK::tuple_get<0>(ListInstancedMatGrass::getInstance()->at(i))); - size_t &instanceCount = STK::tuple_get<1>(ListInstancedMatGrass::getInstance()->at(i)); - DrawElementsIndirectCommand &CurrentCommand = ShadowCommandBufferPtr[offset++]; - CurrentCommand.instanceCount = instanceCount; - CurrentCommand.baseVertex = mesh.vaoBaseVertex; - CurrentCommand.count = mesh.IndexCount; - CurrentCommand.firstIndex = mesh.vaoOffset / 2; - CurrentCommand.baseInstance = mesh.vaoBaseInstance; - } - ShadowPassCmd::getInstance()->Size[cascade][MAT_GRASS] = offset - ShadowPassCmd::getInstance()->Offset[cascade][MAT_GRASS]; #ifdef Multi_Draw_Indirect multidrawShadow(cascade); + multidrawShadow(cascade); multidrawShadow(cascade); multidrawShadow(cascade); - core::vector3df dir = ListInstancedMatGrass::getInstance()->empty() ? core::vector3df(0., 0., 0.) : STK::tuple_get<2>(ListInstancedMatGrass::getInstance()->at(0)); - multidrawShadow(cascade, dir); + multidrawShadow(cascade); + multidrawShadow(cascade, windDir); #endif } - else +#ifdef Draw_Indirect + else if (irr_driver->hasARB_draw_indirect()) { - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedShadow(noTexUnits, cascade, ListInstancedMatDefault::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedShadow(std::vector{ 0 }, cascade, ListInstancedMatAlphaRef::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); - renderInstancedShadow(std::vector{ 0 }, cascade, ListInstancedMatGrass::getInstance()); - if (irr_driver->hasARB_base_instance()) - glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); - renderInstancedShadow(noTexUnits, cascade, ListInstancedMatNormalMap::getInstance()); + renderInstancedShadow(noTexUnits, cascade, ListInstancedMatDefault::getInstance()->Shadows[cascade]); + renderInstancedShadow(noTexUnits, cascade, ListInstancedMatDetails::getInstance()->Shadows[cascade]); + renderInstancedShadow(std::vector < GLuint > { 0 }, cascade, ListInstancedMatAlphaRef::getInstance()->Shadows[cascade]); + renderInstancedShadow(std::vector < GLuint > { 0 }, cascade, ListInstancedMatUnlit::getInstance()->Shadows[cascade]); + renderInstancedShadow(std::vector < GLuint > { 0 }, cascade, ListInstancedMatGrass::getInstance()->Shadows[cascade], windDir); + renderInstancedShadow(noTexUnits, cascade, ListInstancedMatNormalMap::getInstance()->Shadows[cascade]); } +#endif } glDisable(GL_POLYGON_OFFSET_FILL); @@ -1085,33 +874,93 @@ struct rsm_custom_unroll_args }; template -void drawRSM(const core::matrix4 & rsm_matrix, const std::vector &TextureUnits, std::vector > *t) +void drawRSM(const core::matrix4 & rsm_matrix, const std::vector &TextureUnits, const std::vector > &t) { glUseProgram(T::getInstance()->Program); if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType)); - for (unsigned i = 0; i < t->size(); i++) + for (unsigned i = 0; i < t.size(); i++) { std::vector Textures; - GLMesh *mesh = STK::tuple_get<0>(t->at(i)); + GLMesh *mesh = STK::tuple_get<0>(t.at(i)); if (!irr_driver->hasARB_base_instance()) glBindVertexArray(mesh->vao); for (unsigned j = 0; j < TextureUnits.size(); j++) Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]])); T::getInstance()->SetTextureUnits(Textures); - rsm_custom_unroll_args::template exec(rsm_matrix, t->at(i)); + rsm_custom_unroll_args::template exec(rsm_matrix, t.at(i)); } } +#ifdef Draw_Indirect +template +void renderRSMShadow(const std::vector TextureUnits, const std::vector &t, Args ...args) +{ + glUseProgram(Shader::getInstance()->Program); + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeRSM)); + for (unsigned i = 0; i < t.size(); i++) + { + std::vector Handles; + std::vector Textures; + GLMesh *mesh = t[i]; + + for (unsigned j = 0; j < TextureUnits.size(); j++) + Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]])); + + Shader::getInstance()->SetTextureUnits(Textures); + Shader::getInstance()->setUniforms(args...); + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((RSMPassCmd::getInstance()->Offset[Mat] + i)* sizeof(DrawElementsIndirectCommand))); + } +} +#endif + +#ifdef Multi_Draw_Indirect +template +void multidrawRSM(Args...args) +{ + glUseProgram(Shader::getInstance()->Program); + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VertexType, InstanceTypeRSM)); + if (RSMPassCmd::getInstance()->Size[Mat]) + { + Shader::getInstance()->setUniforms(args...); + glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(RSMPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)), RSMPassCmd::getInstance()->Size[Mat], sizeof(DrawElementsIndirectCommand)); + } +} +#endif + void IrrDriver::renderRSM() { m_rtts->getRSM().Bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - drawRSM(rsm_matrix, std::vector{ 0 }, ListMatDefault::getInstance()); - drawRSM(rsm_matrix, std::vector{ 0 }, ListMatAlphaRef::getInstance()); - drawRSM(rsm_matrix, std::vector{ 0 }, ListMatNormalMap::getInstance()); - drawRSM(rsm_matrix, std::vector{ 0 }, ListMatUnlit::getInstance()); - drawRSM(rsm_matrix, std::vector{ 0 }, ListMatDetails::getInstance()); - drawRSM(rsm_matrix, createVector(1, 2, 3, 4, 5), ListMatSplatting::getInstance()); + drawRSM(rsm_matrix, std::vector{ 0 }, ListMatDefault::getInstance()->RSM); + drawRSM(rsm_matrix, std::vector{ 0 }, ListMatAlphaRef::getInstance()->RSM); + drawRSM(rsm_matrix, std::vector{ 0 }, ListMatNormalMap::getInstance()->RSM); + drawRSM(rsm_matrix, std::vector{ 0 }, ListMatUnlit::getInstance()->RSM); + drawRSM(rsm_matrix, std::vector{ 0 }, ListMatDetails::getInstance()->RSM); + drawRSM(rsm_matrix, createVector(1, 2, 3, 4, 5), ListMatSplatting::getInstance()->RSM); + + if (irr_driver->hasARB_draw_indirect()) + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, RSMPassCmd::getInstance()->drawindirectcmd); + + if (UserConfigParams::m_azdo) + { +#ifdef Multi_Draw_Indirect + multidrawRSM(rsm_matrix); + multidrawRSM(rsm_matrix); + multidrawRSM(rsm_matrix); + multidrawRSM(rsm_matrix); + multidrawRSM(rsm_matrix); +#endif + } +#ifdef Draw_Indirect + else if (irr_driver->hasARB_draw_indirect()) + { + renderRSMShadow(std::vector < GLuint > { 0 }, ListInstancedMatDefault::getInstance()->RSM, rsm_matrix); + renderRSMShadow(std::vector < GLuint > { 0 }, ListInstancedMatAlphaRef::getInstance()->RSM, rsm_matrix); + renderRSMShadow(std::vector < GLuint > { 0 }, ListInstancedMatUnlit::getInstance()->RSM, rsm_matrix); + renderRSMShadow(std::vector(), ListInstancedMatNormalMap::getInstance()->RSM, rsm_matrix); + renderRSMShadow(std::vector < GLuint > { 0 }, ListInstancedMatDetails::getInstance()->RSM, rsm_matrix); + } +#endif } diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 8a901c38c..c6d3d6958 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -1137,6 +1137,18 @@ namespace MeshShader glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + InstancedColorizeShader::InstancedColorizeShader() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/glow_object.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/glow_object.frag").c_str()); + AssignUniforms(); + + GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); + glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + } + ShadowShader::ShadowShader() { // Geometry shader needed @@ -1173,6 +1185,20 @@ namespace MeshShader glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + InstancedRSMShader::InstancedRSMShader() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_rsm.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_rsm.frag").c_str()); + + AssignUniforms("RSMMatrix"); + AssignSamplerNames(Program, 0, "tex"); + + GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); + glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + } + SplattingRSMShader::SplattingRSMShader() { Program = LoadProgram( diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 48bef7ad1..9baae2679 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -615,6 +615,12 @@ public: ColorizeShader(); }; +class InstancedColorizeShader : public ShaderHelperSingleton +{ +public: + InstancedColorizeShader(); +}; + class ShadowShader : public ShaderHelperSingleton, public TextureRead<> { public: @@ -627,6 +633,12 @@ public: RSMShader(); }; +class InstancedRSMShader : public ShaderHelperSingleton, public TextureRead +{ +public: + InstancedRSMShader(); +}; + class SplattingRSMShader : public ShaderHelperSingleton, public TextureRead { diff --git a/src/graphics/stkanimatedmesh.cpp b/src/graphics/stkanimatedmesh.cpp index 04d3128bd..95b0f0561 100644 --- a/src/graphics/stkanimatedmesh.cpp +++ b/src/graphics/stkanimatedmesh.cpp @@ -165,7 +165,7 @@ void STKAnimatedMesh::render() update(); - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) +/* if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); core::matrix4 invmodel; @@ -185,7 +185,7 @@ void STKAnimatedMesh::render() pushVector(ListMatUnlit::getInstance(), mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY, mesh->TextureMatrix); return; - } + }*/ if (irr_driver->getPhase() == TRANSPARENT_PASS) { diff --git a/src/graphics/stkanimatedmesh.hpp b/src/graphics/stkanimatedmesh.hpp index 0ca233ac3..bfcd3f571 100644 --- a/src/graphics/stkanimatedmesh.hpp +++ b/src/graphics/stkanimatedmesh.hpp @@ -11,8 +11,6 @@ class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMes { protected: bool firstTime; - PtrVector MeshSolidMaterial[MAT_COUNT]; - PtrVector TransparentMesh[TM_COUNT]; std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix; void cleanGLMeshes(); @@ -26,6 +24,7 @@ public: virtual void render(); virtual void setMesh(irr::scene::IAnimatedMesh* mesh); + virtual bool glow() const { return false; } }; #endif // STKANIMATEDMESH_HPP diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index cde162d82..ce6b5a907 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -108,8 +108,6 @@ void STKInstancedSceneNode::setFirstTimeMaterial() GLMesh &mesh = GLmeshes[i]; MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); initinstancedvaostate(mesh, instanceData[i]); - if (irr_driver->hasARB_base_instance()) - mesh.vaoBaseInstance = VAOManager::getInstance()->appendInstance(InstanceTypeDefault, instanceData[i]); MeshSolidMaterial[MatType].push_back(&mesh); InitTextures(mesh, MatType); } @@ -191,7 +189,7 @@ void STKInstancedSceneNode::render() setFirstTimeMaterial(); - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) +/* if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) { for (unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++) { @@ -218,5 +216,5 @@ void STKInstancedSceneNode::render() GLMesh *mesh = MeshSolidMaterial[MAT_NORMAL_MAP][i]; ListInstancedMatNormalMap::getInstance()->push_back(STK::make_tuple(mesh, instanceData[0].size())); } - } + }*/ } diff --git a/src/graphics/stkinstancedscenenode.hpp b/src/graphics/stkinstancedscenenode.hpp index 466d0f96c..0766b1c02 100644 --- a/src/graphics/stkinstancedscenenode.hpp +++ b/src/graphics/stkinstancedscenenode.hpp @@ -4,18 +4,6 @@ #include "stkmesh.hpp" #include "utils/leak_check.hpp" -class ListInstancedMatDefault : public MeshList -{}; - -class ListInstancedMatAlphaRef : public MeshList -{}; - -class ListInstancedMatGrass : public MeshList -{}; - -class ListInstancedMatNormalMap : public MeshList -{}; - class STKInstancedSceneNode : public irr::scene::CMeshSceneNode { protected: diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index a8a9f6ffe..2746a5428 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -126,6 +126,7 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb) GLMesh result = {}; if (!mb) return result; + result.mb = mb; result.IndexCount = mb->getIndexCount(); switch (mb->getIndexType()) @@ -230,7 +231,7 @@ core::matrix4 computeMVP(const core::matrix4 &ModelMatrix) return ModelViewProjectionMatrix; } -core::vector3df getWind() +core::vector3df getWindDir() { const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f; GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS); diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index d5d57c596..f4c246419 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -46,9 +46,9 @@ struct GLMesh { core::matrix4 TextureMatrix; size_t vaoBaseVertex; size_t vaoOffset; - size_t vaoBaseInstance; video::E_VERTEX_TYPE VAOType; uint64_t TextureHandles[6]; + scene::IMeshBuffer *mb; }; GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb); @@ -58,61 +58,122 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type); core::matrix4 computeMVP(const core::matrix4 &ModelViewProjectionMatrix); bool isObject(video::E_MATERIAL_TYPE type); -core::vector3df getWind(); +core::vector3df getWindDir(); class STKMeshCommon { -protected: +public: PtrVector MeshSolidMaterial[MAT_COUNT]; PtrVector TransparentMesh[TM_COUNT]; -public: virtual void update() = 0; + virtual bool glow() const = 0; virtual bool isImmediateDraw() const { return false; } }; - template -class MeshList : public Singleton, public std::vector > -{}; +class MeshList : public Singleton +{ +public: + std::vector > SolidPass, Shadows[4], RSM; + void clear() + { + SolidPass.clear(); + RSM.clear(); + for (unsigned i = 0; i < 4; i++) + Shadows[i].clear(); + } +}; +template +class InstancedMeshList : public Singleton +{ +public: + std::vector SolidPass, Shadows[4], RSM; + void clear() + { + SolidPass.clear(); + RSM.clear(); + for (unsigned i = 0; i < 4; i++) + Shadows[i].clear(); + } +}; + +// -----------------------------------------Mat Default---------------------------------------------------- // class ListMatDefault : public MeshList {}; +class ListInstancedMatDefault : public InstancedMeshList +{}; + + +// -----------------------------------------Mat Alpha Ref---------------------------------------------------- // class ListMatAlphaRef : public MeshList {}; +class ListInstancedMatAlphaRef : public InstancedMeshList +{}; + +// -----------------------------------------Mat Normap Map---------------------------------------------------- // class ListMatNormalMap : public MeshList {}; +class ListInstancedMatNormalMap : public InstancedMeshList +{}; + +// -----------------------------------------Mat Grass---------------------------------------------------- // class ListMatGrass : public MeshList {}; +class ListInstancedMatGrass : public InstancedMeshList +{}; + +// -----------------------------------------Mat Sphere Map---------------------------------------------------- // class ListMatSphereMap : public MeshList {}; +class ListInstancedMatSphereMap : public InstancedMeshList +{}; + +// -----------------------------------------Mat Splatting---------------------------------------------------- // class ListMatSplatting : public MeshList {}; +// -----------------------------------------Mat Unlit---------------------------------------------------- // class ListMatUnlit : public MeshList {}; +class ListInstancedMatUnlit : public InstancedMeshList +{}; + +// -----------------------------------------Mat Details---------------------------------------------------- // class ListMatDetails : public MeshList {}; -class ListBlendTransparent : public MeshList +class ListInstancedMatDetails : public InstancedMeshList {}; -class ListAdditiveTransparent : public MeshList +// Transparent +template +class MiscList : public Singleton, public std::vector > {}; -class ListBlendTransparentFog : public MeshList +class ListBlendTransparent : public MiscList {}; -class ListAdditiveTransparentFog : public MeshList +class ListAdditiveTransparent : public MiscList {}; -class ListDisplacement : public MeshList +class ListBlendTransparentFog : public MiscList +{}; + +class ListAdditiveTransparentFog : public MiscList +{}; + +class ListDisplacement : public MiscList +{}; + +class ListInstancedGlow : public Singleton, public std::vector {}; // Forward pass (for transparents meshes) diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index 21024252d..291b5617f 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -21,6 +21,7 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, isDisplacement = false; immediate_draw = false; update_each_frame = false; + isGlow = false; if (createGLMeshes) this->createGLMeshes(); @@ -142,14 +143,12 @@ STKMeshSceneNode::~STKMeshSceneNode() void STKMeshSceneNode::drawGlow(const GLMesh &mesh) { - ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE); assert(mesh.VAOType == video::EVT_STANDARD); GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - - MeshShader::ColorizeShader::getInstance()->setUniforms(AbsoluteTransformation, video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue())); + MeshShader::ColorizeShader::getInstance()->setUniforms(AbsoluteTransformation, video::SColorf(glowcolor.getRed() / 255.f, glowcolor.getGreen() / 255.f, glowcolor.getBlue() / 255.f)); glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } @@ -170,8 +169,6 @@ void STKMeshSceneNode::updatevbo() } } -static video::ITexture *spareWhiteTex = 0; - void STKMeshSceneNode::update() { Box = Mesh->getBoundingBox(); @@ -196,6 +193,8 @@ void STKMeshSceneNode::OnRegisterSceneNode() CMeshSceneNode::OnRegisterSceneNode(); } +static video::ITexture *spareWhiteTex = 0; + void STKMeshSceneNode::render() { irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); @@ -207,7 +206,22 @@ void STKMeshSceneNode::render() update(); - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS && immediate_draw) + bool isTransparent; + + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + + video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; + video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); + + isTransparent = rnd->isTransparent(); + break; + } + + if ((irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) && immediate_draw && !isTransparent) { core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); @@ -225,6 +239,21 @@ void STKMeshSceneNode::render() GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; + if (!mesh.textures[0]) + mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + compressTexture(mesh.textures[0], true); + if (UserConfigParams::m_azdo) + { +#ifdef Bindless_Texture_Support + if (!mesh.TextureHandles[0]) + mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]); + if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) + glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); + MeshShader::ObjectPass1Shader::getInstance()->SetTextureHandles(createVector(mesh.TextureHandles[0])); +#endif + } + else + MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(std::vector < GLuint > { getTextureGLuint(mesh.textures[0]) }); MeshShader::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel); assert(mesh.vao); glBindVertexArray(mesh.vao); @@ -235,54 +264,25 @@ void STKMeshSceneNode::render() return; } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) + if (irr_driver->getPhase() == SOLID_LIT_PASS && immediate_draw && !isTransparent) { core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); - GLMesh* mesh; - for_in(mesh, MeshSolidMaterial[MAT_DEFAULT]) - pushVector(ListMatDefault::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_ALPHA_REF]) - pushVector(ListMatAlphaRef::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_SPHEREMAP]) - pushVector(ListMatSphereMap::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_DETAIL]) - pushVector(ListMatDetails::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - windDir = getWind(); - for_in(mesh, MeshSolidMaterial[MAT_GRASS]) - pushVector(ListMatGrass::getInstance(), mesh, AbsoluteTransformation, invmodel, windDir); - - for_in(mesh, MeshSolidMaterial[MAT_UNLIT]) - pushVector(ListMatUnlit::getInstance(), mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_SPLATTING]) - pushVector(ListMatSplatting::getInstance(), mesh, AbsoluteTransformation, invmodel); - - for_in(mesh, MeshSolidMaterial[MAT_NORMAL_MAP]) - pushVector(ListMatNormalMap::getInstance(), mesh, AbsoluteTransformation, invmodel, core::matrix4::EM4CONST_IDENTITY); - - return; - } - - if (irr_driver->getPhase() == SOLID_LIT_PASS) - { - core::matrix4 invmodel; - AbsoluteTransformation.getInverse(invmodel); - - if (immediate_draw) + glDisable(GL_CULL_FACE); + if (!spareWhiteTex) + spareWhiteTex = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program); + // Only untextured + for (unsigned i = 0; i < GLmeshes.size(); i++) { - return; - glDisable(GL_CULL_FACE); - if (!spareWhiteTex) - spareWhiteTex = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program); - // Only untextured - for (unsigned i = 0; i < GLmeshes.size(); i++) + irr_driver->IncreaseObjectCount(); + GLMesh &mesh = GLmeshes[i]; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + if (UserConfigParams::m_azdo) { irr_driver->IncreaseObjectCount(); GLMesh &mesh = GLmeshes[i]; @@ -325,10 +325,19 @@ void STKMeshSceneNode::render() glDrawElements(ptype, count, itype, 0); glBindVertexArray(0); } - glEnable(GL_CULL_FACE); - return; + else + MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector( + irr_driver->getRenderTargetTexture(RTT_DIFFUSE), + irr_driver->getRenderTargetTexture(RTT_SPECULAR), + irr_driver->getRenderTargetTexture(RTT_HALF1_R), + getTextureGLuint(mesh.textures[0]))); + MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix); + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); } - + glEnable(GL_CULL_FACE); return; } @@ -348,7 +357,7 @@ void STKMeshSceneNode::render() } } - if (irr_driver->getPhase() == TRANSPARENT_PASS) + if (irr_driver->getPhase() == TRANSPARENT_PASS && isTransparent) { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); @@ -383,6 +392,8 @@ void STKMeshSceneNode::render() tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); + if (!mesh.textures[0]) + mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); compressTexture(mesh.textures[0], true); if (UserConfigParams::m_azdo) { @@ -414,7 +425,8 @@ void STKMeshSceneNode::render() GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - + if (!mesh.textures[0]) + mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); compressTexture(mesh.textures[0], true); if (UserConfigParams::m_azdo) { @@ -440,42 +452,6 @@ void STKMeshSceneNode::render() } GLMesh* mesh; - - if (World::getWorld() && World::getWorld()->isFogEnabled()) - { - const Track * const track = World::getWorld()->getTrack(); - - // Todo : put everything in a ubo - const float fogmax = track->getFogMax(); - const float startH = track->getFogStartHeight(); - const float endH = track->getFogEndHeight(); - const float start = track->getFogStart(); - const float end = track->getFogEnd(); - const video::SColor tmpcol = track->getFogColor(); - - video::SColorf col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - for_in(mesh, TransparentMesh[TM_DEFAULT]) - pushVector(ListBlendTransparentFog::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix, - fogmax, startH, endH, start, end, col); - for_in(mesh, TransparentMesh[TM_ADDITIVE]) - pushVector(ListAdditiveTransparentFog::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix, - fogmax, startH, endH, start, end, col); - } - else - { - for_in(mesh, TransparentMesh[TM_DEFAULT]) - pushVector(ListBlendTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix); - - for_in(mesh, TransparentMesh[TM_ADDITIVE]) - pushVector(ListAdditiveTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix); - } - - for_in(mesh, TransparentMesh[TM_DISPLACEMENT]) - pushVector(ListDisplacement::getInstance(), mesh, AbsoluteTransformation); - if (!TransparentMesh[TM_BUBBLE].empty()) glUseProgram(MeshShader::BubbleShader::Program); if (irr_driver->hasARB_base_instance()) diff --git a/src/graphics/stkmeshscenenode.hpp b/src/graphics/stkmeshscenenode.hpp index 90f12007b..a8e8724ed 100644 --- a/src/graphics/stkmeshscenenode.hpp +++ b/src/graphics/stkmeshscenenode.hpp @@ -22,6 +22,8 @@ protected: bool immediate_draw; bool update_each_frame; bool isDisplacement; + bool isGlow; + video::SColor glowcolor; public: virtual void update(); void setReloadEachFrame(bool); @@ -46,6 +48,9 @@ public: mb->getMaterial().MaterialType = irr_driver->getShader(ES_DISPLACE); } } + virtual bool glow() const { return isGlow; } + void setGlowColors(const video::SColor &c) { isGlow = true; glowcolor = c; } + video::SColor getGlowColor() const { return glowcolor; } }; #endif diff --git a/src/graphics/stkscenemanager.cpp b/src/graphics/stkscenemanager.cpp new file mode 100644 index 000000000..5b58eec57 --- /dev/null +++ b/src/graphics/stkscenemanager.cpp @@ -0,0 +1,634 @@ +#include "stkscenemanager.hpp" +#include "stkmesh.hpp" +#include "stkinstancedscenenode.hpp" +#include "irr_driver.hpp" +#include +#include +#include "stkanimatedmesh.hpp" +#include "stkmeshscenenode.hpp" +#include "utils/ptr_vector.hpp" +#include +#include +#include "callbacks.hpp" +#include "utils/cpp2011.hpp" +#include +#include "modes/world.hpp" +#include "tracks/track.hpp" +#include "lod_node.hpp" + +static void +FillInstances_impl(std::vector > InstanceList, InstanceData * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, + size_t &InstanceBufferOffset, size_t &CommandBufferOffset, int cascade) +{ + // Should never be empty + GLMesh *mesh = InstanceList.front().first; + + DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++]; + CurrentCommand.baseVertex = mesh->vaoBaseVertex; + CurrentCommand.count = mesh->IndexCount; + CurrentCommand.firstIndex = mesh->vaoOffset / 2; + CurrentCommand.baseInstance = InstanceBufferOffset; + CurrentCommand.instanceCount = InstanceList.size(); + + irr_driver->IncreasePolyCount(InstanceList.size() * mesh->IndexCount / 3); + + for (unsigned i = 0; i < InstanceList.size(); i++) + { + auto &Tp = InstanceList[i]; + InstanceData &Instance = InstanceBuffer[InstanceBufferOffset++]; + scene::ISceneNode *node = Tp.second; + const core::matrix4 &mat = node->getAbsoluteTransformation(); + const core::vector3df &Origin = mat.getTranslation(); + const core::vector3df &Orientation = mat.getRotationDegrees(); + const core::vector3df &Scale = mat.getScale(); + Instance.Origin.X = Origin.X; + Instance.Origin.Y = Origin.Y; + Instance.Origin.Z = Origin.Z; + Instance.Orientation.X = Orientation.X; + Instance.Orientation.Y = Orientation.Y; + Instance.Orientation.Z = Orientation.Z; + Instance.Scale.X = Scale.X; + Instance.Scale.Y = Scale.Y; + Instance.Scale.Z = Scale.Z; + Instance.Texture = mesh->TextureHandles[0]; + Instance.SecondTexture = mesh->TextureHandles[1]; + } +} + + +static void +FillInstancesGlow_impl(std::vector > InstanceList, GlowInstanceData * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, +size_t &InstanceBufferOffset, size_t &CommandBufferOffset) +{ + // Should never be empty + GLMesh *mesh = InstanceList.front().first; + + DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++]; + CurrentCommand.baseVertex = mesh->vaoBaseVertex; + CurrentCommand.count = mesh->IndexCount; + CurrentCommand.firstIndex = mesh->vaoOffset / 2; + CurrentCommand.baseInstance = InstanceBufferOffset; + CurrentCommand.instanceCount = InstanceList.size(); + + irr_driver->IncreasePolyCount(InstanceList.size() * mesh->IndexCount / 3); + + for (unsigned i = 0; i < InstanceList.size(); i++) + { + STKMeshSceneNode *node = dynamic_cast(InstanceList[i].second); + GlowInstanceData &Instance = InstanceBuffer[InstanceBufferOffset++]; + const core::matrix4 &mat = node->getAbsoluteTransformation(); + const core::vector3df &Origin = mat.getTranslation(); + const core::vector3df &Orientation = mat.getRotationDegrees(); + const core::vector3df &Scale = mat.getScale(); + Instance.Color = node->getGlowColor().color; + Instance.Origin.X = Origin.X; + Instance.Origin.Y = Origin.Y; + Instance.Origin.Z = Origin.Z; + Instance.Orientation.X = Orientation.X; + Instance.Orientation.Y = Orientation.Y; + Instance.Orientation.Z = Orientation.Z; + Instance.Scale.X = Scale.X; + Instance.Scale.Y = Scale.Y; + Instance.Scale.Z = Scale.Z; + } +} + + +static +void FillInstances(const std::map > > &GatheredGLMesh, std::vector &InstancedList, + InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, int cascade) +{ + auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end(); + for (; It != E; ++It) + { + FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, cascade); + if (!UserConfigParams::m_azdo) + InstancedList.push_back(It->second.front().first); + } +} + +static +void FillInstancesGrass(const std::map > > &GatheredGLMesh, std::vector &InstancedList, + InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, int cascade, const core::vector3df &dir) +{ + auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end(); + SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT); + for (; It != E; ++It) + { + FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, cascade); + if (!UserConfigParams::m_azdo) + InstancedList.push_back(It->second.front().first); + } +} + +static std::map > > MeshForSolidPass[MAT_COUNT]; +static std::map > > MeshForShadowPass[4][MAT_COUNT]; +static std::map > > MeshForRSMPass[MAT_COUNT]; +static std::map > > MeshForGlowPass; + +static core::vector3df windDir; + +static void +handleSTKCommon(scene::ISceneNode *Node, std::vector *ImmediateDraw, bool IsCulledForSolid, bool IsCulledForShadow[4], bool IsCulledForRSM) +{ + STKMeshCommon *node = dynamic_cast(Node); + if (!node) + return; + node->update(); + + if (node->isImmediateDraw()) + { + ImmediateDraw->push_back(Node); + return; + } + for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat) + { + GLMesh *mesh; + if (!IsCulledForSolid) + { + if (irr_driver->hasARB_draw_indirect()) + { + for_in(mesh, node->MeshSolidMaterial[Mat]) + { + if (node->glow()) + MeshForGlowPass[mesh->mb].push_back(std::make_pair(mesh, node)); + core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; + ModelMatrix.getInverse(InvModelMatrix); + + if (mesh->TextureMatrix.isIdentity()) + MeshForSolidPass[Mat][mesh->mb].push_back(std::make_pair(mesh, Node)); + else + { + switch (Mat) + { + case MAT_DEFAULT: + ListMatDefault::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_ALPHA_REF: + ListMatAlphaRef::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_UNLIT: + ListMatUnlit::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + } + } + } + } + else + { + core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; + ModelMatrix.getInverse(InvModelMatrix); + + for_in(mesh, node->MeshSolidMaterial[Mat]) + { + switch (Mat) + { + case MAT_DEFAULT: + ListMatDefault::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_ALPHA_REF: + ListMatAlphaRef::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_NORMAL_MAP: + ListMatNormalMap::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_DETAIL: + ListMatDetails::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_UNLIT: + ListMatUnlit::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPHEREMAP: + ListMatSphereMap::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPLATTING: + ListMatSplatting::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix)); + break; + case MAT_GRASS: + ListMatGrass::getInstance()->SolidPass.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, windDir)); + break; + } + } + } + } + for (unsigned cascade = 0; cascade < 4; ++cascade) + { + if (!IsCulledForShadow[cascade]) + { + if (irr_driver->hasARB_draw_indirect()) + { + for_in(mesh, node->MeshSolidMaterial[Mat]) + MeshForShadowPass[cascade][Mat][mesh->mb].push_back(std::make_pair(mesh, Node)); + } + else + { + core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; + ModelMatrix.getInverse(InvModelMatrix); + + for_in(mesh, node->MeshSolidMaterial[Mat]) + { + switch (Mat) + { + case MAT_DEFAULT: + ListMatDefault::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_ALPHA_REF: + ListMatAlphaRef::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_NORMAL_MAP: + ListMatNormalMap::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_DETAIL: + ListMatDetails::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_UNLIT: + ListMatUnlit::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPHEREMAP: + ListMatSphereMap::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPLATTING: + ListMatSplatting::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix)); + break; + case MAT_GRASS: + ListMatGrass::getInstance()->Shadows[cascade].push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, windDir)); + } + } + } + } + } + if (!IsCulledForRSM) + { + if (irr_driver->hasARB_draw_indirect()) + { + for_in(mesh, node->MeshSolidMaterial[Mat]) + MeshForRSMPass[Mat][mesh->mb].push_back(std::make_pair(mesh, Node)); + } + else + { + core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; + ModelMatrix.getInverse(InvModelMatrix); + + for_in(mesh, node->MeshSolidMaterial[Mat]) + { + switch (Mat) + { + case MAT_DEFAULT: + ListMatDefault::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_ALPHA_REF: + ListMatAlphaRef::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_NORMAL_MAP: + ListMatNormalMap::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_DETAIL: + ListMatDetails::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_UNLIT: + ListMatUnlit::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPHEREMAP: + ListMatSphereMap::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix)); + break; + case MAT_SPLATTING: + ListMatSplatting::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix)); + break; + case MAT_GRASS: + ListMatGrass::getInstance()->RSM.push_back(STK::make_tuple(mesh, ModelMatrix, InvModelMatrix, windDir)); + break; + } + } + } + } + } + // Transparent + if (!IsCulledForSolid) + { + GLMesh *mesh; + if (World::getWorld() && World::getWorld()->isFogEnabled()) + { + const Track * const track = World::getWorld()->getTrack(); + + // Todo : put everything in a ubo + const float fogmax = track->getFogMax(); + const float startH = track->getFogStartHeight(); + const float endH = track->getFogEndHeight(); + const float start = track->getFogStart(); + const float end = track->getFogEnd(); + const video::SColor tmpcol = track->getFogColor(); + + video::SColorf col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + for_in(mesh, node->TransparentMesh[TM_DEFAULT]) + pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, + fogmax, startH, endH, start, end, col); + for_in(mesh, node->TransparentMesh[TM_ADDITIVE]) + pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, + fogmax, startH, endH, start, end, col); + } + else + { + for_in(mesh, node->TransparentMesh[TM_DEFAULT]) + pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix); + for_in(mesh, node->TransparentMesh[TM_ADDITIVE]) + pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix); + } + for_in(mesh, node->TransparentMesh[TM_DISPLACEMENT]) + pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation()); + } +} + +static void +parseSceneManager(core::list List, std::vector *ImmediateDraw, + scene::ICameraSceneNode *shadowCams[4], scene::ICameraSceneNode *RSM_cam) +{ + core::list::Iterator I = List.begin(), E = List.end(); + for (; I != E; ++I) + { + if (LODNode *node = dynamic_cast(*I)) + node->updateVisibility(); + if (!(*I)->isVisible()) + continue; + (*I)->updateAbsolutePosition(); + core::aabbox3d tbox = (*I)->getBoundingBox(); + (*I)->getAbsoluteTransformation().transformBoxEx(tbox); + + const scene::ICameraSceneNode* cam = irr_driver->getSceneManager()->getActiveCamera(); + bool IsCulledForSolid = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox())); + bool IsCulledForShadow[4]; + bool IsCulledForRSM = false; + for (unsigned i = 0; i < 4; ++i) + { + const scene::ICameraSceneNode* cam = shadowCams[i]; + IsCulledForShadow[i] = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox())); + } + + if (IsCulledForSolid && IsCulledForShadow[0] && IsCulledForShadow[1] && IsCulledForShadow[2] && IsCulledForShadow[3]) + continue; + + if (!IsCulledForSolid) + { + if (ParticleSystemProxy *node = dynamic_cast(*I)) + { + if (node->update()) + ParticlesList::getInstance()->push_back(node); + continue; + } + } + + handleSTKCommon(*I, ImmediateDraw, IsCulledForSolid, IsCulledForShadow, false); + + parseSceneManager((*I)->getChildren(), ImmediateDraw, shadowCams, RSM_cam); + } +} + +template static void +GenDrawCalls(unsigned cascade, std::vector &InstancedList, + InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset) +{ + if (irr_driver->hasARB_draw_indirect()) + ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset + FillInstances(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, cascade); + if (UserConfigParams::m_azdo) + ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat]; +} + +template static void +GenDrawCallsGrass(unsigned cascade, std::vector &InstancedList, +InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir) +{ + if (irr_driver->hasARB_draw_indirect()) + ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset + FillInstancesGrass(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, cascade, dir); + if (UserConfigParams::m_azdo) + ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat]; +} + +void IrrDriver::PrepareDrawCalls() +{ + windDir = getWindDir(); + ListBlendTransparent::getInstance()->clear(); + ListAdditiveTransparent::getInstance()->clear(); + ListBlendTransparentFog::getInstance()->clear(); + ListAdditiveTransparentFog::getInstance()->clear(); + ListDisplacement::getInstance()->clear(); + + ListMatDefault::getInstance()->clear(); + ListMatAlphaRef::getInstance()->clear(); + ListMatSphereMap::getInstance()->clear(); + ListMatDetails::getInstance()->clear(); + ListMatUnlit::getInstance()->clear(); + ListMatNormalMap::getInstance()->clear(); + ListMatGrass::getInstance()->clear(); + ListMatSplatting::getInstance()->clear(); + + ImmediateDrawList::getInstance()->clear(); + ParticlesList::getInstance()->clear(); + ListInstancedGlow::getInstance()->clear(); + + for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat) + { + MeshForSolidPass[Mat].clear(); + MeshForRSMPass[Mat].clear(); + for (unsigned cascade = 0; cascade < 4; ++cascade) + MeshForShadowPass[cascade][Mat].clear(); + } + MeshForGlowPass.clear(); + core::list List = m_scene_manager->getRootSceneNode()->getChildren(); + + bool isCulled[4] = {}; + parseSceneManager(List, ImmediateDrawList::getInstance(), m_shadow_camnodes, m_suncam); + if (!irr_driver->hasARB_draw_indirect()) + return; + InstanceData *InstanceBuffer; + InstanceData *ShadowInstanceBuffer; + InstanceData *RSMInstanceBuffer; + GlowInstanceData *GlowInstanceBuffer; + DrawElementsIndirectCommand *CmdBuffer; + DrawElementsIndirectCommand *ShadowCmdBuffer; + DrawElementsIndirectCommand *RSMCmdBuffer; + DrawElementsIndirectCommand *GlowCmdBuffer; + + if (irr_driver->hasBufferStorageExtension()) + { + InstanceBuffer = (InstanceData*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeDefault); + ShadowInstanceBuffer = (InstanceData*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeShadow); + RSMInstanceBuffer = (InstanceData*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeRSM); + GlowInstanceBuffer = (GlowInstanceData*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeGlow); + CmdBuffer = SolidPassCmd::getInstance()->Ptr; + ShadowCmdBuffer = ShadowPassCmd::getInstance()->Ptr; + GlowCmdBuffer = GlowPassCmd::getInstance()->Ptr; + RSMCmdBuffer = RSMPassCmd::getInstance()->Ptr; + } + + ListInstancedMatDefault::getInstance()->clear(); + ListInstancedMatAlphaRef::getInstance()->clear(); + ListInstancedMatGrass::getInstance()->clear(); + ListInstancedMatNormalMap::getInstance()->clear(); + ListInstancedMatSphereMap::getInstance()->clear(); + ListInstancedMatDetails::getInstance()->clear(); + ListInstancedMatUnlit::getInstance()->clear(); + +#pragma omp parallel sections + { +#pragma omp section + { + size_t offset = 0, current_cmd = 0; + if (!irr_driver->hasBufferStorageExtension()) + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeDefault)); + InstanceBuffer = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd); + CmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + // Default Material + SolidPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd; + FillInstances(MeshForSolidPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_DEFAULT]; + // Alpha Ref + SolidPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd; + FillInstances(MeshForSolidPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_ALPHA_REF]; + // Unlit + SolidPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd; + FillInstances(MeshForSolidPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_UNLIT]; + // Spheremap + SolidPassCmd::getInstance()->Offset[MAT_SPHEREMAP] = current_cmd; + FillInstances(MeshForSolidPass[MAT_SPHEREMAP], ListInstancedMatSphereMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_SPHEREMAP] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_SPHEREMAP]; + // Detail + SolidPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd; + FillInstances(MeshForSolidPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_DETAIL]; + // Normal Map + SolidPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd; + FillInstances(MeshForSolidPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1); + SolidPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_NORMAL_MAP]; + + // Grass + SolidPassCmd::getInstance()->Offset[MAT_GRASS] = current_cmd; + FillInstancesGrass(MeshForSolidPass[MAT_GRASS], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, -1, windDir); + SolidPassCmd::getInstance()->Size[MAT_GRASS] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_GRASS]; + + if (!irr_driver->hasBufferStorageExtension()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + } +#pragma omp section + { + size_t offset = 0, current_cmd = 0; + + if (!irr_driver->hasBufferStorageExtension()) + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeGlow)); + GlowInstanceBuffer = (GlowInstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd); + GlowCmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + // Glow + if (irr_driver->hasARB_draw_indirect()) + GlowPassCmd::getInstance()->Offset = offset; // Store command buffer offset + + auto It = MeshForGlowPass.begin(), E = MeshForGlowPass.end(); + for (; It != E; ++It) + { + FillInstancesGlow_impl(It->second, GlowInstanceBuffer, GlowCmdBuffer, offset, current_cmd); + if (!UserConfigParams::m_azdo) + ListInstancedGlow::getInstance()->push_back(It->second.front().first); + } + + if (UserConfigParams::m_azdo) + GlowPassCmd::getInstance()->Size = current_cmd - GlowPassCmd::getInstance()->Offset; + + if (!irr_driver->hasBufferStorageExtension()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + } +#pragma omp section + { + irr_driver->setPhase(SHADOW_PASS); + + size_t offset = 0, current_cmd = 0; + if (!irr_driver->hasBufferStorageExtension()) + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeShadow)); + ShadowInstanceBuffer = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ShadowPassCmd::getInstance()->drawindirectcmd); + ShadowCmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + for (unsigned i = 0; i < 4; i++) + { + // Mat default + GenDrawCalls(i, ListInstancedMatDefault::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat AlphaRef + GenDrawCalls(i, ListInstancedMatAlphaRef::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat Unlit + GenDrawCalls(i, ListInstancedMatUnlit::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat NormalMap + GenDrawCalls(i, ListInstancedMatNormalMap::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat Spheremap + GenDrawCalls(i, ListInstancedMatSphereMap::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat Detail + GenDrawCalls(i, ListInstancedMatDetails::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd); + // Mat Grass + GenDrawCallsGrass(i, ListInstancedMatGrass::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, windDir); + } + if (!irr_driver->hasBufferStorageExtension()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + } +#pragma omp section + { + size_t offset = 0, current_cmd = 0; + if (!irr_driver->hasBufferStorageExtension()) + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeRSM)); + RSMInstanceBuffer = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, RSMPassCmd::getInstance()->drawindirectcmd); + RSMCmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + // Default Material + RSMPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd; + FillInstances(MeshForRSMPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, -1); + RSMPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DEFAULT]; + // Alpha Ref + RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd; + FillInstances(MeshForRSMPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, -1); + RSMPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF]; + // Unlit + RSMPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd; + FillInstances(MeshForRSMPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, -1); + RSMPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_UNLIT]; + // Detail + RSMPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd; + FillInstances(MeshForRSMPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, -1); + RSMPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DETAIL]; + // Normal Map + RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd; + FillInstances(MeshForRSMPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, -1); + RSMPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP]; + + if (!irr_driver->hasBufferStorageExtension()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + } + } + + glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); +} \ No newline at end of file diff --git a/src/graphics/stkscenemanager.hpp b/src/graphics/stkscenemanager.hpp index fa924e05d..998fe2a72 100644 --- a/src/graphics/stkscenemanager.hpp +++ b/src/graphics/stkscenemanager.hpp @@ -7,6 +7,7 @@ #include "utils/singleton.hpp" #include "gl_headers.hpp" #include "stkmesh.hpp" +#include "gpuparticles.hpp" template class CommandBuffer : public Singleton @@ -16,15 +17,28 @@ public: DrawElementsIndirectCommand *Ptr; CommandBuffer() { -#ifdef Buffer_Storage glGenBuffers(1, &drawindirectcmd); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawindirectcmd); - glBufferStorage(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); - Ptr = (DrawElementsIndirectCommand *)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); +#ifdef Buffer_Storage + if (irr_driver->hasBufferStorageExtension()) + { + glBufferStorage(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); + Ptr = (DrawElementsIndirectCommand *)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); + } + else #endif + { + glBufferData(GL_DRAW_INDIRECT_BUFFER, 10000 * sizeof(DrawElementsIndirectCommand), 0, GL_STREAM_DRAW); + } } }; +class ImmediateDrawList : public Singleton, public std::vector +{}; + +class ParticlesList : public Singleton, public std::vector +{}; + class SolidPassCmd : public CommandBuffer { @@ -38,5 +52,17 @@ public: size_t Offset[4][MAT_COUNT], Size[4][MAT_COUNT]; }; +class RSMPassCmd : public CommandBuffer +{ +public: + size_t Offset[MAT_COUNT], Size[MAT_COUNT]; +}; + +class GlowPassCmd : public CommandBuffer +{ +public: + size_t Offset, Size; +}; + #endif \ No newline at end of file