#include "BsCoreRenderer.h" #include "BsCoreThread.h" #include "BsRenderAPI.h" #include "BsMesh.h" #include "BsMaterial.h" #include "BsPass.h" #include "BsBlendState.h" #include "BsDepthStencilState.h" #include "BsRasterizerState.h" #include "BsGpuParams.h" namespace BansheeEngine { CoreRenderer::CoreRenderer() { } RendererMeshDataPtr CoreRenderer::_createMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType) { return bs_shared_ptr(new (bs_alloc()) RendererMeshData(numVertices, numIndices, layout, indexType)); } RendererMeshDataPtr CoreRenderer::_createMeshData(const MeshDataPtr& meshData) { return bs_shared_ptr(new (bs_alloc()) RendererMeshData(meshData)); } void CoreRenderer::_registerRenderCallback(const CameraCore* camera, INT32 index, const std::function& callback) { mRenderCallbacks[camera][index] = callback; } void CoreRenderer::_unregisterRenderCallback(const CameraCore* camera, INT32 index) { auto iterFind = mRenderCallbacks.find(camera); if (iterFind != mRenderCallbacks.end()) { iterFind->second.erase(index); if (iterFind->second.empty()) mRenderCallbacks.erase(iterFind); } } void CoreRenderer::setPass(const SPtr& material, UINT32 passIdx) { THROW_IF_NOT_CORE_THREAD; RenderAPICore& rs = RenderAPICore::instance(); SPtr pass = material->getPass(passIdx); SPtr passParams = material->getPassParameters(passIdx); struct StageData { GpuProgramType type; bool enable; SPtr params; SPtr program; }; const UINT32 numStages = 6; StageData stages[numStages] = { { GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), passParams->mVertParams, pass->getVertexProgram() }, { GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), passParams->mFragParams, pass->getFragmentProgram() }, { GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), passParams->mGeomParams, pass->getGeometryProgram() }, { GPT_HULL_PROGRAM, pass->hasHullProgram(), passParams->mHullParams, pass->getHullProgram() }, { GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), passParams->mDomainParams, pass->getDomainProgram() }, { GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(), passParams->mComputeParams, pass->getComputeProgram() } }; for (UINT32 i = 0; i < numStages; i++) { const StageData& stage = stages[i]; if (stage.enable) { rs.bindGpuProgram(stage.program); rs.setGpuParams(stage.type, stage.params); } else rs.unbindGpuProgram(stage.type); } // TODO - Try to limit amount of state changes, if previous state is already the same // Set up non-texture related pass settings if (pass->getBlendState() != nullptr) rs.setBlendState(pass->getBlendState()); else rs.setBlendState(BlendStateCore::getDefault()); if (pass->getDepthStencilState() != nullptr) rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue()); else rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue()); if (pass->getRasterizerState() != nullptr) rs.setRasterizerState(pass->getRasterizerState()); else rs.setRasterizerState(RasterizerStateCore::getDefault()); } void CoreRenderer::draw(const SPtr& mesh, const SubMesh& subMesh) { THROW_IF_NOT_CORE_THREAD; RenderAPICore& rs = RenderAPICore::instance(); const MeshProperties& meshProps = mesh->getProperties(); std::shared_ptr vertexData = mesh->getVertexData(); rs.setVertexDeclaration(vertexData->vertexDeclaration); auto& vertexBuffers = vertexData->getBuffers(); if (vertexBuffers.size() > 0) { SPtr buffers[MAX_BOUND_VERTEX_BUFFERS]; UINT32 endSlot = 0; UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS; for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter) { if (iter->first >= MAX_BOUND_VERTEX_BUFFERS) BS_EXCEPT(InvalidParametersException, "Buffer index out of range"); startSlot = std::min(iter->first, startSlot); endSlot = std::max(iter->first, endSlot); } for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter) { buffers[iter->first - startSlot] = iter->second; } rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1); } rs.setDrawOperation(subMesh.drawOp); SPtr indexBuffer = mesh->getIndexBuffer(); UINT32 indexCount = subMesh.indexCount; rs.setIndexBuffer(indexBuffer); rs.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(), vertexData->vertexCount); mesh->_notifyUsedOnGPU(); } }