//----------------------------------------------------------------------------------- PbsMaterial::PbsMaterial() : mAlbedo(1, 1, 1, 0), mF0(0.1f, 0.1f, 0.1f, 1.0f), mRoughness(0.1f), mLightRoughnessOffset(0.0f), /*header initial values*/ mMainUvSetIndex(0), mD1UvSetIndex(0), mD2UvSetIndex(0), _hasSamplerListChanged(false), _hasSamplerChanged(false) { //Header initial values mMainOffset = Vector2::ZERO; mMainScale = Vector2::UNIT_SCALE; mD1Offset = Vector2::ZERO; mD1Scale = Vector2::UNIT_SCALE; mD2Offset = Vector2::ZERO; mD2Scale = Vector2::UNIT_SCALE; _samplers[ST_ENV_MAP].init("environment", false, false, false, false, true, true, TEX_TYPE_CUBE_MAP); _samplers[ST_MAIN_ALBEDO].init("main_albedo", true, true, false, true); _samplers[ST_MAIN_NORMALR].init("main_normalr", false, true, true); _samplers[ST_MAIN_F0].init("main_f0", true, true); _samplers[ST_D1_ALBEDO].init("d1_albedo", true, true, false, true); _samplers[ST_D1_NORMALR].init("d1_normalr", false, true, true); _samplers[ST_D1_F0].init("d1_f0", true, true); _samplers[ST_D2_ALBEDO].init("d2_albedo", true, true, false, true); _samplers[ST_D2_NORMALR].init("d2_normalr", false, true, true); _samplers[ST_D2_F0].init("d2_f0", true, true); RenderSystem* rs = Root::getSingleton().getRenderSystem(); String language = ""; if (rs->getCapabilities()->isShaderProfileSupported("hlsl")) { language = "hlsl"; mVertexDatablock.addProfile("vs_3_0"); mFragmentDatablock.addProfile("ps_3_0"); } else if (rs->getCapabilities()->isShaderProfileSupported("glsl")) { language = "glsl"; } else { language = "glsles"; } mVertexDatablock.setLanguage(language); mFragmentDatablock.setLanguage(language); mVertexDatablock.setTemplateName("PBS"); mFragmentDatablock.setTemplateName("PBS"); // TODO check if the hardware supports gamma correction "Root::getSingleton().getRenderSystem()->getCapabilities()" doesen't support this check mCanHardwareGamma = false; }
//--------------------------------------------------------------------------- const GpuProgramManager::SyntaxCodes& GpuProgramManager::getSupportedSyntax(void) const { // Use the current render system RenderSystem* rs = Root::getSingleton().getRenderSystem(); // Get the supported syntaxed from RenderSystemCapabilities return rs->getCapabilities()->getSupportedShaderProfiles(); }
//--------------------------------------------------------------------- bool GpuProgramManager::canGetCompiledShaderBuffer() { // Use the current render system RenderSystem* rs = Root::getSingleton().getRenderSystem(); // Check if the supported return rs->getCapabilities()->hasCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER); }
//--------------------------------------------------------------------------- bool GpuProgramManager::isSyntaxSupported(const String& syntaxCode) const { // Use the current render system RenderSystem* rs = Root::getSingleton().getRenderSystem(); // Get the supported syntax from RenderSystemCapabilities return rs->getCapabilities()->isShaderProfileSupported(syntaxCode); }
//----------------------------------------------------------------------- bool D3D10HLSLProgram::isSupported(void) const { // Use the current render system RenderSystem* rs = Root::getSingleton().getRenderSystem(); // Get the supported syntaxed from RenderSystemCapabilities return rs->getCapabilities()->isShaderProfileSupported(mTarget) && GpuProgram::isSupported(); }
//----------------------------------------------------------------------------------- void CompositorPass::addResourceTransition( ResourceLayoutMap::iterator currentLayout, ResourceLayout::Layout newLayout, uint32 readBarrierBits ) { ResourceTransition transition; //transition.resource = ; TODO transition.oldLayout = currentLayout->second; transition.newLayout = newLayout; transition.writeBarrierBits = transitionWriteBarrierBits( transition.oldLayout ); transition.readBarrierBits = readBarrierBits; RenderSystem *renderSystem = mParentNode->getRenderSystem(); const RenderSystemCapabilities *caps = renderSystem->getCapabilities(); if( !caps->hasCapability( RSC_EXPLICIT_API ) ) { //OpenGL. Merge the bits and use only one global barrier. //Keep the extra barriers uninitialized for debugging purposes, //but we won't be really using them. if( mResourceTransitions.empty() ) { ResourceTransition globalBarrier; globalBarrier.oldLayout = ResourceLayout::Undefined; globalBarrier.newLayout = ResourceLayout::Undefined; globalBarrier.writeBarrierBits = transition.writeBarrierBits; globalBarrier.readBarrierBits = transition.readBarrierBits; globalBarrier.mRsData = 0; renderSystem->_resourceTransitionCreated( &globalBarrier ); mResourceTransitions.push_back( globalBarrier ); } else { ResourceTransition &globalBarrier = mResourceTransitions.front(); renderSystem->_resourceTransitionDestroyed( &globalBarrier ); globalBarrier.writeBarrierBits |= transition.writeBarrierBits; globalBarrier.readBarrierBits |= transition.readBarrierBits; renderSystem->_resourceTransitionCreated( &globalBarrier ); } mNumValidResourceTransitions = 1; } else { //D3D12, Vulkan, Mantle. Takes advantage of per-resource barriers renderSystem->_resourceTransitionCreated( &transition ); ++mNumValidResourceTransitions; } mResourceTransitions.push_back( transition ); currentLayout->second = transition.newLayout; }
int main(int numargs, char** args) { if (numargs != 1) { help(); return -1; } RenderSystemCapabilities* glCaps = 0; RenderSystemCapabilities* d3d9Caps = 0; RenderSystemCapabilitiesSerializer serializer; // query openGL for caps if available Root* root = new Root("plugins.cfg"); RenderSystem* rsGL = root->getRenderSystemByName("OpenGL Rendering Subsystem"); if(rsGL) { setUpGLRenderSystemOptions(rsGL); root->setRenderSystem(rsGL); root->initialise(true, "OGRE rcapsdump GL Window"); glCaps = const_cast<RenderSystemCapabilities *>(rsGL->getCapabilities()); } if(glCaps) { serializer.writeScript(glCaps, glCaps->getDeviceName(), "rcapsdump_gl.rendercaps"); } delete root; // query D3D9 for caps if available root = new Root("plugins.cfg"); RenderSystem* rsD3D9 = root->getRenderSystemByName("Direct3D9 Rendering Subsystem"); if(rsD3D9) { setUpD3D9RenderSystemOptions(rsD3D9); root->setRenderSystem(rsD3D9); root->initialise(true, "OGRE rcapsdump D3D9 Window"); d3d9Caps = const_cast<RenderSystemCapabilities *>(rsD3D9->getCapabilities()); } if(d3d9Caps) { serializer.writeScript(d3d9Caps, d3d9Caps->getDeviceName(), "rcapsdump_d3d9.rendercaps"); } delete root; return 0; }
//----------------------------------------------------------------------- size_t LightInstanceBatchHW::calculateMaxNumInstances( const SubMesh *baseSubMesh, uint16 flags ) const { size_t retVal = 0; RenderSystem *renderSystem = Root::getSingleton().getRenderSystem(); const RenderSystemCapabilities *capabilities = renderSystem->getCapabilities(); if( capabilities->hasCapability( RSC_VERTEX_BUFFER_INSTANCE_DATA ) ) { //This value is arbitrary (theorical max is 2^30 for D3D9) but is big enough and safe retVal = 65535; } return retVal; }
//----------------------------------------------------------------------- size_t InstanceBatchHW_VTF::calculateMaxNumInstances( const SubMesh *baseSubMesh, uint16 flags ) const { size_t retVal = 0; RenderSystem *renderSystem = Root::getSingleton().getRenderSystem(); const RenderSystemCapabilities *capabilities = renderSystem->getCapabilities(); //VTF & HW Instancing must be supported if( capabilities->hasCapability( RSC_VERTEX_BUFFER_INSTANCE_DATA ) && capabilities->hasCapability( RSC_VERTEX_TEXTURE_FETCH ) ) { //TODO: Check PF_FLOAT32_RGBA is supported (should be, since it was the 1st one) const size_t numBones = std::max<size_t>( 1, baseSubMesh->blendIndexToBoneIndexMap.size() ); const size_t maxUsableWidth = c_maxTexWidthHW - (c_maxTexWidthHW % (numBones * mRowLength)); //See InstanceBatchHW::calculateMaxNumInstances for the 65535 retVal = std::min<size_t>( 65535, maxUsableWidth * c_maxTexHeightHW / mRowLength / numBones ); if( flags & IM_VTFBESTFIT ) { size_t numUsedSkeletons = mInstancesPerBatch; if (flags & IM_VTFBONEMATRIXLOOKUP) numUsedSkeletons = std::min<size_t>(getMaxLookupTableInstances(), numUsedSkeletons); const size_t instancesPerBatch = std::min( retVal, numUsedSkeletons ); //Do the same as in createVertexTexture(), but changing c_maxTexWidthHW for maxUsableWidth const size_t numWorldMatrices = instancesPerBatch * numBones; size_t texWidth = std::min<size_t>( numWorldMatrices * mRowLength, maxUsableWidth ); size_t texHeight = numWorldMatrices * mRowLength / maxUsableWidth; const size_t remainder = (numWorldMatrices * mRowLength) % maxUsableWidth; if( remainder && texHeight > 0 ) retVal = static_cast<size_t>(texWidth * texHeight / (float)mRowLength / (float)(numBones)); } } return retVal; }
// Just override the mandatory create scene method void createScene(void) { RenderSystem *rs = Root::getSingleton().getRenderSystem(); const RenderSystemCapabilities* caps = rs->getCapabilities(); if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM))) { OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support vertex and fragment programs, so cannot " "run this demo. Sorry!", "DeferredShading::createScene"); } if (caps->getNumMultiRenderTargets()<2) { OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support at least two simultaneous render targets, so cannot " "run this demo. Sorry!", "DeferredShading::createScene"); } // Prepare athene mesh for normalmapping MeshPtr pAthene = MeshManager::getSingleton().load("athene.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); unsigned short src, dest; if (!pAthene->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) pAthene->buildTangentVectors(VES_TANGENT, src, dest); // Prepare knot mesh for normal mapping pAthene = MeshManager::getSingleton().load("knot.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (!pAthene->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) pAthene->buildTangentVectors(VES_TANGENT, src, dest); // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.15)); // Skybox mSceneMgr->setSkyBox(true, "DeferredDemo/SkyBox"); // Create "root" node SceneNode* rootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); Entity* athena = mSceneMgr->createEntity("Athena", "athene.mesh"); athena->setMaterialName("DeferredDemo/DeferredAthena"); SceneNode *aNode = rootNode->createChildSceneNode(); aNode->attachObject( athena ); aNode->setPosition(-100, 40, 100); // Create a prefab plane mPlane = new MovablePlane("ReflectPlane"); mPlane->d = 0; mPlane->normal = Vector3::UNIT_Y; MeshManager::getSingleton().createCurvedPlane("ReflectionPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, *mPlane, 2000, 2000, -1000, 20, 20, true, 1, 10, 10, Vector3::UNIT_Z); mPlaneEnt = mSceneMgr->createEntity( "Plane", "ReflectionPlane" ); mPlaneNode = rootNode->createChildSceneNode(); mPlaneNode->attachObject(mPlaneEnt); mPlaneNode->translate(-5, -30, 0); //mPlaneNode->roll(Degree(5)); mPlaneEnt->setMaterialName("DeferredDemo/Ground"); // Create an entity from a model (will be loaded automatically) Entity* knotEnt = mSceneMgr->createEntity("Knot", "knot.mesh"); knotEnt->setMaterialName("DeferredDemo/RockWall"); knotEnt->setMeshLodBias(0.25f); // Create an entity from a model (will be loaded automatically) Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh"); ogreHead->getSubEntity(0)->setMaterialName("DeferredDemo/Ogre/Eyes");// eyes ogreHead->getSubEntity(1)->setMaterialName("DeferredDemo/Ogre/Skin"); ogreHead->getSubEntity(2)->setMaterialName("DeferredDemo/Ogre/EarRing"); // earrings ogreHead->getSubEntity(3)->setMaterialName("DeferredDemo/Ogre/Tusks"); // tusks rootNode->createChildSceneNode( "Head" )->attachObject( ogreHead ); // Add a whole bunch of extra entities to fill the scene a bit Entity *cloneEnt; int N=4; for (int n = 0; n < N; ++n) { float theta = 2.0f*Math::PI*(float)n/(float)N; // Create a new node under the root SceneNode* node = mSceneMgr->createSceneNode(); // Random translate Vector3 nodePos; nodePos.x = Math::SymmetricRandom() * 40.0 + Math::Sin(theta) * 500.0; nodePos.y = Math::SymmetricRandom() * 20.0 - 40.0; nodePos.z = Math::SymmetricRandom() * 40.0 + Math::Cos(theta) * 500.0; node->setPosition(nodePos); Quaternion orientation(Math::SymmetricRandom(),Math::SymmetricRandom(),Math::SymmetricRandom(),Math::SymmetricRandom()); orientation.normalise(); node->setOrientation(orientation); rootNode->addChild(node); // Clone knot char cloneName[12]; sprintf(cloneName, "Knot%d", n); cloneEnt = knotEnt->clone(cloneName); // Attach to new node node->attachObject(cloneEnt); } mCamera->setPosition(-50, 100, 500); mCamera->lookAt(0,0,0); // show overlay Overlay* overlay = OverlayManager::getSingleton().getByName("Example/ShadowsOverlay"); overlay->show(); mSystem = new DeferredShadingSystem(mWindow->getViewport(0), mSceneMgr, mCamera); // Create main, moving light MLight* l1 = mSystem->createMLight();//"MainLight"); l1->setDiffuseColour(0.75f, 0.7f, 0.8f); l1->setSpecularColour(0.85f, 0.9f, 1.0f); SceneNode *lightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); lightNode->attachObject(l1); // Create a track for the light Animation* anim = mSceneMgr->createAnimation("LightTrack", 16); // Spline it for nice curves anim->setInterpolationMode(Animation::IM_SPLINE); // Create a track to animate the camera's node NodeAnimationTrack* track = anim->createNodeTrack(0, lightNode); // Setup keyframes TransformKeyFrame* key = track->createNodeKeyFrame(0); // A start position key->setTranslate(Vector3(300,300,-300)); key = track->createNodeKeyFrame(4);//B key->setTranslate(Vector3(300,300,300)); key = track->createNodeKeyFrame(8);//C key->setTranslate(Vector3(-300,300,300)); key = track->createNodeKeyFrame(12);//D key->setTranslate(Vector3(-300,300,-300)); key = track->createNodeKeyFrame(16);//D key->setTranslate(Vector3(300,300,-300)); // Create a new animation state to track this SharedData::getSingleton().mAnimState = mSceneMgr->createAnimationState("LightTrack"); SharedData::getSingleton().mAnimState->setEnabled(true); // Create some happy little lights createSampleLights(); // safely setup application's (not postfilter!) shared data SharedData::getSingleton().iCamera = mCamera; SharedData::getSingleton().iRoot = mRoot; SharedData::getSingleton().iWindow = mWindow; SharedData::getSingleton().iActivate = true; SharedData::getSingleton().iGlobalActivate = true; SharedData::getSingleton().iSystem = mSystem; SharedData::getSingleton().iMainLight = l1; }
//----------------------------------------------------------------------------------- void CompositorPass::_placeBarriersAndEmulateUavExecution( BoundUav boundUavs[64], ResourceAccessMap &uavsAccess, ResourceLayoutMap &resourcesLayout ) { RenderSystem *renderSystem = mParentNode->getRenderSystem(); const RenderSystemCapabilities *caps = renderSystem->getCapabilities(); const bool explicitApi = caps->hasCapability( RSC_EXPLICIT_API ); { //mResourceTransitions will be non-empty if we call _placeBarriersAndEmulateUavExecution //for a second time (i.e. 2nd pass to check frame-to-frame dependencies). We need //to tell what is shielded. On the first time, it should be empty. ResourceTransitionVec::const_iterator itor = mResourceTransitions.begin(); ResourceTransitionVec::const_iterator end = mResourceTransitions.end(); while( itor != end ) { if( itor->newLayout == ResourceLayout::Uav && itor->writeBarrierBits & WriteBarrier::Uav && itor->readBarrierBits & ReadBarrier::Uav ) { RenderTarget *renderTarget = 0; resourcesLayout[renderTarget] = ResourceLayout::Uav; //Set to undefined so that following passes //can see it's safe / shielded by a barrier uavsAccess[renderTarget] = ResourceAccess::Undefined; } ++itor; } } { //Check <anything> -> RT ResourceLayoutMap::iterator currentLayout = resourcesLayout.find( mTarget ); if( (currentLayout->second != ResourceLayout::RenderTarget && explicitApi) || currentLayout->second == ResourceLayout::Uav ) { addResourceTransition( currentLayout, ResourceLayout::RenderTarget, ReadBarrier::RenderTarget ); } } { //Check <anything> -> Texture CompositorTextureVec::const_iterator itDep = mTextureDependencies.begin(); CompositorTextureVec::const_iterator enDep = mTextureDependencies.end(); while( itDep != enDep ) { TexturePtr texture = itDep->textures->front(); RenderTarget *renderTarget = texture->getBuffer()->getRenderTarget(); ResourceLayoutMap::iterator currentLayout = resourcesLayout.find( renderTarget ); if( (currentLayout->second != ResourceLayout::Texture && explicitApi) || currentLayout->second == ResourceLayout::Uav ) { //TODO: Account for depth textures. addResourceTransition( currentLayout, ResourceLayout::Texture, ReadBarrier::Texture ); } ++itDep; } } //Check <anything> -> UAV; including UAV -> UAV //Except for RaR (Read after Read) and some WaW (Write after Write), //Uavs are always hazardous, an UAV->UAV 'transition' is just a memory barrier. CompositorPassDef::UavDependencyVec::const_iterator itor = mDefinition->mUavDependencies.begin(); CompositorPassDef::UavDependencyVec::const_iterator end = mDefinition->mUavDependencies.end(); while( itor != end ) { GpuResource *uavRt = boundUavs[itor->uavSlot].rttOrBuffer; if( !uavRt ) { OGRE_EXCEPT( Exception::ERR_INVALID_STATE, "No UAV is bound at slot " + StringConverter::toString( itor->uavSlot ) + " but it is marked as used by node " + mParentNode->getName().getFriendlyText() + "; pass #" + StringConverter::toString( mParentNode->getPassNumber( this ) ), "CompositorPass::emulateUavExecution" ); } if( !(itor->access & boundUavs[itor->uavSlot].boundAccess) ) { OGRE_EXCEPT( Exception::ERR_INVALID_STATE, "Node " + mParentNode->getName().getFriendlyText() + "; pass #" + StringConverter::toString( mParentNode->getPassNumber( this ) ) + " marked " + ResourceAccess::toString( itor->access ) + " access to UAV at slot " + StringConverter::toString( itor->uavSlot ) + " but this UAV is bound for " + ResourceAccess::toString( boundUavs[itor->uavSlot].boundAccess ) + " access.", "CompositorPass::emulateUavExecution" ); } ResourceAccessMap::iterator itResAccess = uavsAccess.find( uavRt ); if( itResAccess == uavsAccess.end() ) { //First time accessing the UAV. If we need a barrier, //we will see it in the second pass. uavsAccess[uavRt] = ResourceAccess::Undefined; itResAccess = uavsAccess.find( uavRt ); } ResourceLayoutMap::iterator currentLayout = resourcesLayout.find( uavRt ); if( currentLayout->second != ResourceLayout::Uav || !( (itor->access == ResourceAccess::Read && itResAccess->second == ResourceAccess::Read) || (itor->access == ResourceAccess::Write && itResAccess->second == ResourceAccess::Write && itor->allowWriteAfterWrite) || itResAccess->second == ResourceAccess::Undefined ) ) { //Not RaR (or not WaW when they're explicitly allowed). Insert the barrier. //We also may need the barrier if the resource wasn't an UAV. addResourceTransition( currentLayout, ResourceLayout::Uav, ReadBarrier::Uav ); } itResAccess->second = itor->access; ++itor; } }