| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- #include "anki/renderer/Drawer.h"
- #include "anki/resource/ShaderProgramResource.h"
- #include "anki/scene/Frustumable.h"
- #include "anki/resource/Material.h"
- #include "anki/scene/Renderable.h"
- #include "anki/scene/Camera.h"
- #include "anki/scene/ModelNode.h"
- #include "anki/resource/TextureResource.h"
- #include "anki/renderer/Renderer.h"
- namespace anki {
- //==============================================================================
- /// Visitor that sets a uniform
- struct SetupMaterialVariableVisitor
- {
- PassLevelKey key;
- const Frustumable* fr = nullptr;
- Renderer* r = nullptr;
- Renderable* renderable = nullptr;
- Array<U8, RenderableDrawer::UNIFORM_BLOCK_MAX_SIZE> clientBlock;
- RenderableMaterialVariable* rvar = nullptr;
- /// Set a uniform in a client block
- template<typename T>
- void uniSet(const ShaderProgramUniformVariable& uni, const T& value)
- {
- ANKI_ASSERT(0);
- }
- template<typename TProp>
- void visit(TProp& x)
- {
- const MaterialVariable& mv = rvar->getMaterialVariable();
- const ShaderProgramUniformVariable* uni =
- mv.findShaderProgramUniformVariable(key);
- if(!uni)
- {
- return;
- }
- // Set uniform
- //
- const Transform* rwtrf = renderable->getRenderableWorldTransform();
- Mat4 mMat = (rwtrf) ? Mat4(*rwtrf) : Mat4::getIdentity();
- const Mat4& vpMat = fr->getViewProjectionMatrix();
- Mat4 mvMat;
- Bool mvMatCalculated = false; // Opt
- switch(rvar->getBuildinId())
- {
- case BMV_NO_BUILDIN:
- uniSet(*uni, x);
- break;
- case BMV_MODEL_VIEW_PROJECTION_MATRIX:
- {
- Mat4 mvpMat = vpMat * mMat;
- uniSet(*uni, mvpMat);
- }
- break;
- case BMV_MODEL_VIEW_MATRIX:
- if(!mvMatCalculated)
- {
- mvMat = fr->getViewMatrix() * mMat;
- mvMatCalculated = true;
- }
- uniSet(*uni, mvMat);
- break;
- case BMV_NORMAL_MATRIX:
- if(!mvMatCalculated)
- {
- mvMat = fr->getViewMatrix() * mMat;
- mvMatCalculated = true;
- }
- uniSet(*uni, mvMat.getRotationPart());
- break;
- case BMV_INSTANCING_MODEL_VIEW_PROJECTION_MATRICES:
- {
- U32 instancesCount = renderable->getRenderableInstancesCount();
- Array<Mat4, 64> mvps;
- ANKI_ASSERT(mvps.getSize() >= instancesCount);
- const Transform* trfs =
- renderable->getRenderableInstancingWorldTransforms();
- ANKI_ASSERT(trfs != nullptr);
- for(U i = 0; i < instancesCount; i++)
- {
- mvps[i] = vpMat * Mat4(trfs[i]);
- }
- uni->set(&mvps[0], instancesCount);
- }
- break;
- case BMV_BLURRING:
- uniSet(*uni, 0.0);
- break;
- default:
- ANKI_ASSERT(0);
- break;
- }
- }
- };
- /// Specialize the material accepted types. The un-specialized will be used for
- /// all Property types like strings, we don't need strings in our case
- #define TEMPLATE_SPECIALIZATION(type) \
- template<> \
- void SetupMaterialVariableVisitor::uniSet<type>( \
- const ShaderProgramUniformVariable& uni, const type& value) \
- { \
- if(uni.getUniformBlock()) \
- { \
- uni.setClientMemory(&clientBlock[0], \
- RenderableDrawer::UNIFORM_BLOCK_MAX_SIZE, \
- &value, 1); \
- } \
- else \
- { \
- uni.set(value); \
- } \
- }
- TEMPLATE_SPECIALIZATION(F32)
- TEMPLATE_SPECIALIZATION(Vec2)
- TEMPLATE_SPECIALIZATION(Vec3)
- TEMPLATE_SPECIALIZATION(Vec4)
- TEMPLATE_SPECIALIZATION(Mat3)
- TEMPLATE_SPECIALIZATION(Mat4)
- // Texture specialization
- template<>
- void SetupMaterialVariableVisitor::uniSet<TextureResourcePointer>(
- const ShaderProgramUniformVariable& uni,
- const TextureResourcePointer& value)
- {
- const Texture* tex = value.get();
- uni.set(*tex);
- }
- //==============================================================================
- void RenderableDrawer::setupShaderProg(
- const PassLevelKey& key,
- const Frustumable& fr,
- Renderable& renderable)
- {
- const Material& mtl = renderable.getRenderableMaterial();
- const ShaderProgram& sprog = mtl.findShaderProgram(key);
- sprog.bind();
-
- SetupMaterialVariableVisitor vis;
- vis.fr = &fr;
- vis.key = key;
- vis.renderable = &renderable;
- vis.r = r;
- // Set the uniforms
- for(auto it = renderable.getVariablesBegin();
- it != renderable.getVariablesEnd(); ++it)
- {
- RenderableMaterialVariable* rvar = *it;
- vis.rvar = rvar;
- rvar->getMaterialVariable().acceptVisitor(vis);
- }
- // Write the block
- const ShaderProgramUniformBlock* block = mtl.getCommonUniformBlock();
- if(block)
- {
- ANKI_ASSERT(block->getSize() <= UNIFORM_BLOCK_MAX_SIZE);
- ANKI_ASSERT(block->getBinding() == 0);
- renderable.getUbo().write(&vis.clientBlock[0]);
- renderable.getUbo().setBinding(0);
- }
- }
- //==============================================================================
- void RenderableDrawer::render(const Frustumable& fr, RenderingStage stage,
- U32 pass, Renderable& renderable)
- {
- const Material& mtl = renderable.getRenderableMaterial();
- Bool blending = mtl.isBlendingEnabled();
- if(blending)
- {
- if(stage != RS_BLEND)
- {
- return;
- }
- GlStateSingleton::get().setBlendFunctions(
- mtl.getBlendingSfactor(), mtl.getBlendingDfactor());
- }
- else
- {
- if(stage == RS_BLEND)
- {
- return;
- }
- }
- GlStateSingleton::get().enable(GL_BLEND, blending);
- /*float dist = (node.getWorldTransform().getOrigin() -
- cam.getWorldTransform().getOrigin()).getLength();
- uint lod = std::min(r.calculateLod(dist), mtl.getLevelsOfDetail() - 1);*/
- U32 instancesCount = renderable.getRenderableInstancesCount();
- if(instancesCount < 1)
- {
- return;
- }
- PassLevelKey key(pass, 0);
- // Setup shader
- setupShaderProg(key, fr, renderable);
- // Render
- U32 indicesCount =
- renderable.getRenderableModelPatchBase().getIndecesCount(0);
- const Vao& vao = renderable.getRenderableModelPatchBase().getVao(key);
- ANKI_ASSERT(vao.getAttachmentsCount() > 1);
- vao.bind();
- if(instancesCount == 1)
- {
- glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, 0);
- }
- else
- {
- glDrawElementsInstanced(
- GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, 0, instancesCount);
- }
- }
- } // end namespace anki
|