| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "BsRendererUtility.h"
- #include "BsRenderAPI.h"
- #include "BsMesh.h"
- #include "BsVertexDataDesc.h"
- #include "BsMaterial.h"
- #include "BsPass.h"
- #include "BsBlendState.h"
- #include "BsDepthStencilState.h"
- #include "BsRasterizerState.h"
- #include "BsGpuParams.h"
- #include "BsGpuParamDesc.h"
- #include "BsGpuParamBlockBuffer.h"
- #include "BsShapeMeshes3D.h"
- #include "BsLight.h"
- #include "BsShader.h"
- namespace BansheeEngine
- {
- RendererUtility::RendererUtility()
- {
- {
- SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
- vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
- vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
- mFullScreenQuadMesh = MeshCore::create(4, 6, vertexDesc);
- }
- {
- SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
- vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
- UINT32 numVertices = 0;
- UINT32 numIndices = 0;
- ShapeMeshes3D::getNumElementsSphere(3, numVertices, numIndices);
- SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- Sphere localSphere(Vector3::ZERO, 1.0f);
- ShapeMeshes3D::solidSphere(localSphere, positionData, nullptr, 0,
- vertexDesc->getVertexStride(), indexData, 0, 3);
- mPointLightStencilMesh = MeshCore::create(meshData);
- }
- {
- UINT32 numSides = LightCore::LIGHT_CONE_NUM_SIDES;
- UINT32 numSlices = LightCore::LIGHT_CONE_NUM_SLICES;
- SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
- vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
- UINT32 numVertices = numSides * numSlices * 2;
- UINT32 numIndices = ((numSides * 2) * (numSlices - 1) * 2) * 3;
- SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
- UINT32* indexData = meshData->getIndices32();
- UINT8* positionData = meshData->getElementData(VES_POSITION);
- UINT32 stride = vertexDesc->getVertexStride();
- // Dummy vertex positions, actual ones generated in shader
- for (UINT32 i = 0; i < numVertices; i++)
- {
- memcpy(positionData, &Vector3::ZERO, sizeof(Vector3));
- positionData += stride;
- }
- // Cone indices
- UINT32 curIdx = 0;
- for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
- {
- for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
- {
- indexData[curIdx++] = sliceIdx * numSides + sideIdx;
- indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
- indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
- }
- }
- // Sphere cap indices
- UINT32 coneOffset = numSides * numSlices;
- for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
- {
- for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
- {
- indexData[curIdx++] = coneOffset + sliceIdx * numSides + sideIdx;
- indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
- indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
- indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
- }
- }
- mSpotLightStencilMesh = MeshCore::create(meshData);
- }
- // TODO - When I add proper preprocessor support, merge these into a single material
- mResolveMat = bs_shared_ptr_new<ResolveMat>();
- mBlitMat = bs_shared_ptr_new<BlitMat>();
- }
- RendererUtility::~RendererUtility()
- {
- }
- void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, bool bindParameters)
- {
- RenderAPICore& rapi = RenderAPICore::instance();
- SPtr<PassCore> pass = material->getPass(passIdx);
- SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
- struct StageData
- {
- GpuProgramType type;
- bool enable;
- SPtr<GpuParamsCore> params;
- SPtr<GpuProgramCore> program;
- };
- const UINT32 numStages = 5;
- 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()
- }
- };
- for (UINT32 i = 0; i < numStages; i++)
- {
- const StageData& stage = stages[i];
- if (stage.enable)
- {
- rapi.bindGpuProgram(stage.program);
- if(bindParameters)
- setGpuParams(stage.type, stage.params);
- }
- else
- rapi.unbindGpuProgram(stage.type);
- }
- // Set up non-texture related pass settings
- if (pass->getBlendState() != nullptr)
- rapi.setBlendState(pass->getBlendState());
- else
- rapi.setBlendState(BlendStateCore::getDefault());
- if (pass->getDepthStencilState() != nullptr)
- rapi.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
- else
- rapi.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
- if (pass->getRasterizerState() != nullptr)
- rapi.setRasterizerState(pass->getRasterizerState());
- else
- rapi.setRasterizerState(RasterizerStateCore::getDefault());
- }
- void RendererUtility::setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx, bool bindParameters)
- {
- RenderAPICore& rapi = RenderAPICore::instance();
- SPtr<PassCore> pass = material->getPass(passIdx);
- SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
- if(pass->hasComputeProgram())
- {
- rapi.bindGpuProgram(pass->getComputeProgram());
- if (bindParameters)
- setGpuParams(GPT_COMPUTE_PROGRAM, passParams->mComputeParams);
- }
- else
- rapi.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
- }
- void RendererUtility::setPassParams(const SPtr<MaterialCore>& material, UINT32 passIdx)
- {
- const SPtr<PassParametersCore>& passParams = material->getPassParameters(passIdx);
- struct StageData
- {
- GpuProgramType type;
- SPtr<GpuParamsCore> params;
- };
- const UINT32 numStages = 6;
- StageData stages[numStages] =
- {
- { GPT_VERTEX_PROGRAM, passParams->mVertParams },
- { GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
- { GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
- { GPT_HULL_PROGRAM, passParams->mHullParams },
- { GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
- { GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
- };
- for (UINT32 i = 0; i < numStages; i++)
- {
- const StageData& stage = stages[i];
- SPtr<GpuParamsCore> params = stage.params;
- if (params == nullptr)
- continue;
- setGpuParams(stage.type, params);
- }
- }
- void RendererUtility::setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params)
- {
- RenderAPICore& rapi = RenderAPICore::instance();
- const GpuParamDesc& paramDesc = params->getParamDesc();
- for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
- {
- SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
- if (samplerState == nullptr)
- rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
- else
- rapi.setSamplerState(type, iter->second.slot, samplerState);
- }
- for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
- {
- SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
- rapi.setTexture(type, iter->second.slot, texture);
- }
- for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
- {
- SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
- const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
- if (texture == nullptr)
- rapi.setLoadStoreTexture(type, iter->second.slot, false, nullptr, surface);
- else
- rapi.setLoadStoreTexture(type, iter->second.slot, true, texture, surface);
- }
- for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
- {
- SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
- bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
- iter->second.type != GPOT_STRUCTURED_BUFFER;
- rapi.setBuffer(type, iter->second.slot, buffer, isLoadStore);
- }
- for (auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
- {
- SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
- blockBuffer->flushToGPU();
- rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
- }
- }
- void RendererUtility::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, UINT32 numInstances)
- {
- RenderAPICore& rs = RenderAPICore::instance();
- SPtr<VertexData> vertexData = mesh->getVertexData();
- rs.setVertexDeclaration(vertexData->vertexDeclaration);
- auto& vertexBuffers = vertexData->getBuffers();
- if (vertexBuffers.size() > 0)
- {
- SPtr<VertexBufferCore> 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<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
- UINT32 indexCount = subMesh.indexCount;
- rs.setIndexBuffer(indexBuffer);
- rs.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(),
- vertexData->vertexCount, numInstances);
- mesh->_notifyUsedOnGPU();
- }
- void RendererUtility::blit(const SPtr<TextureCore>& texture, const Rect2I& area)
- {
- auto& texProps = texture->getProperties();
- SPtr<MaterialCore> mat;
- if (texProps.getMultisampleCount() > 1)
- {
- mat = mResolveMat->getMaterial();
- mResolveMat->setParameters(texture);
- }
- else
- {
- mat = mBlitMat->getMaterial();
- mBlitMat->setParameters(texture);
- }
- setPass(mat, 0);
- setPassParams(mat);
- Rect2 fArea((float)area.x, (float)area.y, (float)area.width, (float)area.height);
- if(area.width == 0 || area.height == 0)
- {
- fArea.x = 0.0f;
- fArea.y = 0.0f;
- fArea.width = (float)texProps.getWidth();
- fArea.height = (float)texProps.getHeight();
- }
- drawScreenQuad(fArea);
- }
- void RendererUtility::drawScreenQuad(const Rect2& uv, const Vector2I& textureSize, UINT32 numInstances)
- {
- // Note: Consider drawing the quad using a single large triangle for possibly better performance
- Vector3 vertices[4];
- vertices[0] = Vector3(-1.0f, 1.0f, 0.0f);
- vertices[1] = Vector3(1.0f, 1.0f, 0.0f);
- vertices[2] = Vector3(-1.0f, -1.0f, 0.0f);
- vertices[3] = Vector3(1.0f, -1.0f, 0.0f);
- Vector2 uvs[4];
- if (RenderAPICore::instance().getAPIInfo().getNDCYAxisDown())
- {
- uvs[0] = Vector2(uv.x, uv.y);
- uvs[1] = Vector2(uv.x + uv.width, uv.y);
- uvs[2] = Vector2(uv.x, uv.y + uv.height);
- uvs[3] = Vector2(uv.x + uv.width, uv.y + uv.height);
- }
- else
- {
- uvs[0] = Vector2(uv.x, uv.y + uv.height);
- uvs[1] = Vector2(uv.x + uv.width, uv.y + uv.height);
- uvs[2] = Vector2(uv.x, uv.y);
- uvs[3] = Vector2(uv.x + uv.width, uv.y);
- }
- for (int i = 0; i < 4; i++)
- {
- uvs[i].x /= (float)textureSize.x;
- uvs[i].y /= (float)textureSize.y;
- }
- SPtr<VertexDataDesc> vertexDesc = mFullScreenQuadMesh->getVertexDesc();
- SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(4, 6, vertexDesc);
- auto vecIter = meshData->getVec3DataIter(VES_POSITION);
- for (UINT32 i = 0; i < 4; i++)
- vecIter.addValue(vertices[i]);
- auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
- for (UINT32 i = 0; i < 4; i++)
- uvIter.addValue(uvs[i]);
- auto indices = meshData->getIndices32();
- indices[0] = 0;
- indices[1] = 1;
- indices[2] = 2;
- indices[3] = 1;
- indices[4] = 3;
- indices[5] = 2;
- mFullScreenQuadMesh->writeSubresource(0, *meshData, true, false);
- draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh(), numInstances);
- }
- RendererUtility& gRendererUtility()
- {
- return RendererUtility::instance();
- }
- BlitMat::BlitMat()
- {
- mSource = mMaterial->getParamTexture("gSource");
- }
- void BlitMat::_initDefines(ShaderDefines& defines)
- {
- // Do nothing
- }
- void BlitMat::setParameters(const SPtr<TextureCore>& source)
- {
- mSource.set(source);
- }
- ResolveMat::ResolveMat()
- {
- mSource = mMaterial->getParamTexture("gSource");
- mMaterial->getParam("gNumSamples", mNumSamples);
- }
- void ResolveMat::_initDefines(ShaderDefines& defines)
- {
- // Do nothing
- }
- void ResolveMat::setParameters(const SPtr<TextureCore>& source)
- {
- mSource.set(source);
- UINT32 sampleCount = source->getProperties().getMultisampleCount();
- mNumSamples.set(sampleCount);
- }
- }
|