| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include "anki/renderer/Renderer.h"
- #include "anki/scene/Camera.h"
- #include "anki/scene/SceneGraph.h"
- #include "anki/core/Counters.h"
- #include "anki/misc/ConfigSet.h"
- #include "anki/renderer/Ms.h"
- #include "anki/renderer/Is.h"
- #include "anki/renderer/Pps.h"
- #include "anki/renderer/Fs.h"
- #include "anki/renderer/Lf.h"
- #include "anki/renderer/Dbg.h"
- #include "anki/renderer/Tiler.h"
- namespace anki {
- //==============================================================================
- Renderer::Renderer()
- : m_sceneDrawer(this)
- {}
- //==============================================================================
- Renderer::~Renderer()
- {}
- //==============================================================================
- Error Renderer::init(
- ThreadPool* threadpool,
- ResourceManager* resources,
- GrManager* gl,
- HeapAllocator<U8> alloc,
- StackAllocator<U8> frameAlloc,
- const ConfigSet& config,
- const Timestamp* globalTimestamp,
- TexturePtr reflections)
- {
- m_globalTimestamp = globalTimestamp;
- m_threadpool = threadpool;
- m_resources = resources;
- m_gr = gl;
- m_alloc = alloc;
- m_frameAlloc = frameAlloc;
- m_reflectionsCubemapArr = reflections;
- Error err = initInternal(config);
- if(err)
- {
- ANKI_LOGE("Failed to initialize the renderer");
- }
- return err;
- }
- //==============================================================================
- Error Renderer::initInternal(const ConfigSet& config)
- {
- // Set from the config
- m_width = getAlignedRoundDown(TILE_SIZE, U(config.getNumber("width")));
- m_height = getAlignedRoundDown(TILE_SIZE, U(config.getNumber("height")));
- m_lodDistance = config.getNumber("lodDistance");
- m_framesNum = 0;
- m_samples = config.getNumber("samples");
- m_tileCountXY.x() = m_width / TILE_SIZE;
- m_tileCountXY.y() = m_height / TILE_SIZE;
- m_tileCount = m_tileCountXY.x() * m_tileCountXY.y();
- m_clusterer.init(getAllocator(), m_tileCountXY.x(), m_tileCountXY.y(),
- config.getNumber("clusterSizeZ"));
- m_tessellation = config.getNumber("tessellation");
- // A few sanity checks
- if(m_samples != 1 && m_samples != 4 && m_samples != 8 && m_samples != 16
- && m_samples != 32)
- {
- ANKI_LOGE("Incorrect samples");
- return ErrorCode::USER_DATA;
- }
- if(m_width < 10 || m_height < 10)
- {
- ANKI_LOGE("Incorrect sizes");
- return ErrorCode::USER_DATA;
- }
- if(m_width % m_tileCountXY.x() != 0)
- {
- ANKI_LOGE("Width is not multiple of tile width");
- return ErrorCode::USER_DATA;
- }
- if(m_height % m_tileCountXY.y() != 0)
- {
- ANKI_LOGE("Height is not multiple of tile height");
- return ErrorCode::USER_DATA;
- }
- // quad setup
- ANKI_CHECK(
- m_resources->loadResource("shaders/Quad.vert.glsl", m_drawQuadVert));
- // Init the stages. Careful with the order!!!!!!!!!!
- m_ms.reset(m_alloc.newInstance<Ms>(this));
- ANKI_CHECK(m_ms->init(config));
- m_tiler.reset(m_alloc.newInstance<Tiler>(this));
- ANKI_CHECK(m_tiler->init());
- m_is.reset(m_alloc.newInstance<Is>(this));
- ANKI_CHECK(m_is->init(config));
- m_fs.reset(m_alloc.newInstance<Fs>(this));
- ANKI_CHECK(m_fs->init(config));
- m_lf.reset(m_alloc.newInstance<Lf>(this));
- ANKI_CHECK(m_lf->init(config));
- m_pps.reset(m_alloc.newInstance<Pps>(this));
- ANKI_CHECK(m_pps->init(config));
- m_dbg.reset(m_alloc.newInstance<Dbg>(this));
- ANKI_CHECK(m_dbg->init(config));
- return ErrorCode::NONE;
- }
- //==============================================================================
- Error Renderer::render(SceneNode& frustumableNode, U frustumIdx,
- Array<CommandBufferPtr, RENDERER_COMMAND_BUFFERS_COUNT>& cmdb)
- {
- m_frc = nullptr;
- Error err = frustumableNode.iterateComponentsOfType<FrustumComponent>(
- [&](FrustumComponent& frc) -> Error
- {
- if(frustumIdx == 0)
- {
- m_frc = &frc;
- }
- else
- {
- --frustumIdx;
- }
- return ErrorCode::NONE;
- });
- (void)err;
- ANKI_ASSERT(m_frc && "Not enough frustum components");
- m_frameAlloc.getMemoryPool().reset();
- // Calc a few vars
- //
- if(m_frc->getProjectionParameters() != m_projectionParams)
- {
- m_projectionParams = m_frc->getProjectionParameters();
- m_projectionParamsUpdateTimestamp = getGlobalTimestamp();
- }
- ANKI_ASSERT(m_frc->getFrustum().getType() == Frustum::Type::PERSPECTIVE);
- m_clusterer.prepare(getThreadPool(), frustumableNode);
- ANKI_COUNTER_START_TIMER(RENDERER_MS_TIME);
- ANKI_CHECK(m_ms->run(cmdb[0]));
- ANKI_COUNTER_STOP_TIMER_INC(RENDERER_MS_TIME);
- m_lf->runOcclusionTests(cmdb[0]);
- m_ms->generateMipmaps(cmdb[0]);
- m_tiler->run(cmdb[0]);
- ANKI_COUNTER_START_TIMER(RENDERER_IS_TIME);
- ANKI_CHECK(m_is->run(cmdb[1]));
- ANKI_COUNTER_STOP_TIMER_INC(RENDERER_IS_TIME);
- ANKI_CHECK(m_fs->run(cmdb[1]));
- m_lf->run(cmdb[1]);
- ANKI_COUNTER_START_TIMER(RENDERER_PPS_TIME);
- if(m_pps->getEnabled())
- {
- m_pps->run(cmdb[1]);
- }
- ANKI_COUNTER_STOP_TIMER_INC(RENDERER_PPS_TIME);
- if(m_dbg->getEnabled())
- {
- ANKI_CHECK(m_dbg->run(cmdb[1]));
- }
- ++m_framesNum;
- return ErrorCode::NONE;
- }
- //==============================================================================
- Vec3 Renderer::unproject(const Vec3& windowCoords, const Mat4& modelViewMat,
- const Mat4& projectionMat, const int view[4])
- {
- Mat4 invPm = projectionMat * modelViewMat;
- invPm.invert();
- // the vec is in NDC space meaning: -1<=vec.x<=1 -1<=vec.y<=1 -1<=vec.z<=1
- Vec4 vec;
- vec.x() = (2.0 * (windowCoords.x() - view[0])) / view[2] - 1.0;
- vec.y() = (2.0 * (windowCoords.y() - view[1])) / view[3] - 1.0;
- vec.z() = 2.0 * windowCoords.z() - 1.0;
- vec.w() = 1.0;
- Vec4 out = invPm * vec;
- out /= out.w();
- return out.xyz();
- }
- //==============================================================================
- void Renderer::createRenderTarget(U32 w, U32 h, const PixelFormat& format,
- U32 samples, SamplingFilter filter, U mipsCount, TexturePtr& rt)
- {
- // Not very important but keep the resolution of render targets aligned to
- // 16
- if(0)
- {
- ANKI_ASSERT(isAligned(16, w));
- ANKI_ASSERT(isAligned(16, h));
- }
- TextureInitializer init;
- init.m_width = w;
- init.m_height = h;
- init.m_depth = 0;
- init.m_type = TextureType::_2D;
- init.m_format = format;
- init.m_mipmapsCount = mipsCount;
- init.m_samples = samples;
- init.m_sampling.m_minMagFilter = filter;
- if(mipsCount > 1)
- {
- init.m_sampling.m_mipmapFilter = filter;
- }
- else
- {
- init.m_sampling.m_mipmapFilter = SamplingFilter::BASE;
- }
- init.m_sampling.m_repeat = false;
- init.m_sampling.m_anisotropyLevel = 0;
- rt = m_gr->newInstance<Texture>(init);
- }
- //==============================================================================
- void Renderer::createDrawQuadPipeline(
- ShaderPtr frag, const ColorStateInfo& colorState,
- PipelinePtr& ppline)
- {
- PipelineInitializer init;
- init.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLE_STRIP;
- init.m_depthStencil.m_depthWriteEnabled = false;
- init.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS;
- init.m_color = colorState;
- init.m_shaders[U(ShaderType::VERTEX)] = m_drawQuadVert->getGrShader();
- init.m_shaders[U(ShaderType::FRAGMENT)] = frag;
- ppline = m_gr->newInstance<Pipeline>(init);
- }
- //==============================================================================
- void Renderer::prepareForVisibilityTests(const SceneNode& cam)
- {
- m_tiler->prepareForVisibilityTests(cam);
- }
- //==============================================================================
- Bool Renderer::doGpuVisibilityTest(const CollisionShape& cs,
- const Aabb& aabb) const
- {
- return m_tiler->test(cs, aabb);
- }
- } // end namespace anki
|