#include "BsRenderer.h" #include "BsCoreThread.h" #include "BsRenderSystem.h" #include "BsMaterialProxy.h" #include "BsMesh.h" #include "BsBlendState.h" #include "BsDepthStencilState.h" #include "BsRasterizerState.h" namespace BansheeEngine { void Renderer::setPass(const MaterialProxy& material, UINT32 passIdx) { THROW_IF_NOT_CORE_THREAD; RenderSystem& rs = RenderSystem::instance(); const MaterialProxyPass& pass = material.passes[passIdx]; if (pass.vertexProg && pass.vertexProg.isLoaded()) { rs.bindGpuProgram(pass.vertexProg->getCore()); rs.bindGpuParams(GPT_VERTEX_PROGRAM, material.params[pass.vertexProgParamsIdx]); } else rs.unbindGpuProgram(GPT_VERTEX_PROGRAM); if (pass.fragmentProg && pass.fragmentProg.isLoaded()) { rs.bindGpuProgram(pass.fragmentProg->getCore()); rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material.params[pass.fragmentProgParamsIdx]); } else rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM); if (pass.geometryProg && pass.geometryProg.isLoaded()) { rs.bindGpuProgram(pass.geometryProg->getCore()); rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material.params[pass.geometryProgParamsIdx]); } else rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM); if (pass.hullProg && pass.hullProg.isLoaded()) { rs.bindGpuProgram(pass.hullProg->getCore()); rs.bindGpuParams(GPT_HULL_PROGRAM, material.params[pass.hullProgParamsIdx]); } else rs.unbindGpuProgram(GPT_HULL_PROGRAM); if (pass.domainProg && pass.domainProg.isLoaded()) { rs.bindGpuProgram(pass.domainProg->getCore()); rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material.params[pass.domainProgParamsIdx]); } else rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM); if (pass.computeProg && pass.computeProg.isLoaded()) { rs.bindGpuProgram(pass.computeProg->getCore()); rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material.params[pass.computeProgParamsIdx]); } else rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM); // TODO - Try to limit amount of state changes, if previous state is already the same // Set up non-texture related pass settings if (pass.blendState != nullptr) rs.setBlendState(pass.blendState->getCore()); else rs.setBlendState(BlendState::getDefault()->getCore()); if (pass.depthStencilState != nullptr) rs.setDepthStencilState(pass.depthStencilState->getCore(), pass.stencilRefValue); else rs.setDepthStencilState(DepthStencilState::getDefault()->getCore(), pass.stencilRefValue); if (pass.rasterizerState != nullptr) rs.setRasterizerState(pass.rasterizerState->getCore()); else rs.setRasterizerState(RasterizerState::getDefault()->getCore()); } void Renderer::draw(const SPtr& mesh, const SubMesh& subMesh) { THROW_IF_NOT_CORE_THREAD; RenderSystem& rs = RenderSystem::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(); } }