BsBansheeRenderer.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. #include "BsBansheeRenderer.h"
  2. #include "BsCamera.h"
  3. #include "BsSceneObject.h"
  4. #include "BsSceneManager.h"
  5. #include "BsRenderable.h"
  6. #include "BsMaterial.h"
  7. #include "BsMesh.h"
  8. #include "BsPass.h"
  9. #include "BsBlendState.h"
  10. #include "BsRasterizerState.h"
  11. #include "BsDepthStencilState.h"
  12. #include "BsCoreApplication.h"
  13. #include "BsViewport.h"
  14. #include "BsRenderTarget.h"
  15. #include "BsRenderQueue.h"
  16. #include "BsOverlayManager.h"
  17. #include "BsGUIManager.h"
  18. #include "BsCoreThread.h"
  19. #include "BsGpuParams.h"
  20. #include "BsProfilerCPU.h"
  21. #include "BsShader.h"
  22. #include "BsTechnique.h"
  23. #include "BsDrawList.h"
  24. #include "BsHardwareBufferManager.h"
  25. #include "BsGpuParamBlockBuffer.h"
  26. #include "BsShader.h"
  27. #include "BsLitTexRenderableController.h"
  28. #include "BsTime.h"
  29. #include "BsRenderableElement.h"
  30. #include "BsFrameAlloc.h"
  31. #include "BsCoreObjectManager.h"
  32. #include "BsRenderBeastOptions.h"
  33. using namespace std::placeholders;
  34. namespace BansheeEngine
  35. {
  36. BansheeRenderer::BansheeRenderer()
  37. :mOptions(bs_shared_ptr<RenderBeastOptions>()), mOptionsDirty(true)
  38. {
  39. }
  40. const StringID& BansheeRenderer::getName() const
  41. {
  42. static StringID name = "BansheeRenderer";
  43. return name;
  44. }
  45. void BansheeRenderer::_onActivated()
  46. {
  47. CoreRenderer::_onActivated();
  48. gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::initializeCore, this));
  49. }
  50. void BansheeRenderer::_onDeactivated()
  51. {
  52. CoreRenderer::_onDeactivated();
  53. gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::destroyCore, this));
  54. gCoreAccessor().submitToCoreThread(true);
  55. }
  56. void BansheeRenderer::initializeCore()
  57. {
  58. mCoreOptions = bs_shared_ptr<RenderBeastOptions>();
  59. mLitTexHandler = bs_new<LitTexRenderableController>();
  60. SPtr<ShaderCore> shader = createDefaultShader();
  61. mDummyMaterial = MaterialCore::create(shader);
  62. }
  63. void BansheeRenderer::destroyCore()
  64. {
  65. if (mLitTexHandler != nullptr)
  66. bs_delete(mLitTexHandler);
  67. mRenderTargets.clear();
  68. mCameraData.clear();
  69. mRenderables.clear();
  70. mDummyMaterial = nullptr;
  71. }
  72. void BansheeRenderer::_notifyRenderableAdded(RenderableHandlerCore* renderable)
  73. {
  74. UINT32 renderableId = (UINT32)mRenderables.size();
  75. renderable->setRendererId(renderableId);
  76. mRenderables.push_back(RenderableData());
  77. mWorldTransforms.push_back(renderable->getTransform());
  78. mWorldBounds.push_back(renderable->getBounds());
  79. RenderableData& renderableData = mRenderables.back();
  80. renderableData.renderable = renderable;
  81. if (renderable->getRenderableType() == RenType_LitTextured)
  82. renderableData.controller = mLitTexHandler;
  83. else
  84. renderableData.controller = nullptr;
  85. SPtr<MeshCore> mesh = renderable->getMesh();
  86. if (mesh != nullptr)
  87. {
  88. const MeshProperties& meshProps = mesh->getProperties();
  89. for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
  90. {
  91. renderableData.elements.push_back(RenderableElement());
  92. RenderableElement& renElement = renderableData.elements.back();
  93. renElement.mesh = mesh;
  94. renElement.subMesh = meshProps.getSubMesh(i);
  95. renElement.material = renderable->getMaterial(i);
  96. if (renElement.material == nullptr)
  97. renElement.material = renderable->getMaterial(0);
  98. if (renElement.material == nullptr)
  99. renElement.material = mDummyMaterial;
  100. renElement.samplerOverrides = nullptr; // TODO
  101. if (renderableData.controller != nullptr)
  102. renderableData.controller->initializeRenderElem(renElement);
  103. }
  104. }
  105. }
  106. void BansheeRenderer::_notifyRenderableRemoved(RenderableHandlerCore* renderable)
  107. {
  108. UINT32 renderableId = renderable->getRendererId();
  109. RenderableHandlerCore* lastRenerable = mRenderables.back().renderable;
  110. UINT32 lastRenderableId = lastRenerable->getRendererId();
  111. if (renderableId != lastRenderableId)
  112. {
  113. // Swap current last element with the one we want to erase
  114. std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
  115. std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
  116. std::swap(mWorldTransforms[renderableId], mWorldTransforms[lastRenderableId]);
  117. lastRenerable->setRendererId(renderableId);
  118. }
  119. // Last element is the one we want to erase
  120. mRenderables.erase(mRenderables.end() - 1);
  121. mWorldBounds.erase(mWorldBounds.end() - 1);
  122. mWorldTransforms.erase(mWorldTransforms.end() - 1);
  123. }
  124. void BansheeRenderer::_notifyRenderableUpdated(RenderableHandlerCore* renderable)
  125. {
  126. UINT32 renderableId = renderable->getRendererId();
  127. mWorldTransforms[renderableId] = renderable->getTransform();
  128. mWorldBounds[renderableId] = renderable->getBounds();
  129. }
  130. void BansheeRenderer::_notifyLightAdded(const LightInternalCore* light)
  131. {
  132. // TODO
  133. }
  134. void BansheeRenderer::_notifyLightRemoved(const LightInternalCore* light)
  135. {
  136. // TODO
  137. }
  138. void BansheeRenderer::_notifyCameraAdded(const CameraHandlerCore* camera)
  139. {
  140. CameraData& camData = mCameraData[camera];
  141. camData.renderQueue = bs_shared_ptr<RenderQueue>();
  142. }
  143. void BansheeRenderer::_notifyCameraRemoved(const CameraHandlerCore* camera)
  144. {
  145. mCameraData.erase(camera);
  146. }
  147. void BansheeRenderer::setOptions(const SPtr<CoreRendererOptions>& options)
  148. {
  149. mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
  150. mOptionsDirty = true;
  151. }
  152. SPtr<CoreRendererOptions> BansheeRenderer::getOptions() const
  153. {
  154. return mOptions;
  155. }
  156. void BansheeRenderer::renderAll()
  157. {
  158. // Populate direct draw lists
  159. const Map<CameraHandler*, SceneCameraData>& allCameras = gSceneManager().getAllCameras();
  160. for (auto& cameraData : allCameras)
  161. {
  162. CameraHandlerPtr camera = cameraData.second.camera;
  163. HSceneObject cameraSO = cameraData.second.sceneObject;
  164. DrawListPtr drawList = bs_shared_ptr<DrawList>();
  165. // Get GUI render operations
  166. GUIManager::instance().render(camera->getViewport(), *drawList);
  167. // Get overlay render operations
  168. OverlayManager::instance().render(camera->getViewport(), *drawList);
  169. // Get any operations from hooked up callbacks
  170. const Viewport* viewportRawPtr = camera->getViewport().get();
  171. onRenderViewport(viewportRawPtr, *drawList);
  172. RenderQueuePtr renderQueue = bs_shared_ptr<RenderQueue>();
  173. const Vector<DrawOperation>& drawOps = drawList->getDrawOperations();
  174. for (auto& drawOp : drawOps)
  175. {
  176. SPtr<MaterialCore> materialCore = drawOp.material->getCore();
  177. SPtr<MeshCoreBase> meshCore = drawOp.mesh->getCore();
  178. SubMesh subMesh = meshCore->getProperties().getSubMesh(drawOp.submeshIdx);
  179. float distanceToCamera = (cameraSO->getPosition() - drawOp.worldPosition).length();
  180. renderQueue->add(materialCore, meshCore, subMesh, distanceToCamera);
  181. }
  182. gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->getCore(), renderQueue));
  183. }
  184. // Sync all dirty sim thread CoreObject data to core thread
  185. CoreObjectManager::instance().syncToCore(gCoreAccessor());
  186. if (mOptionsDirty)
  187. {
  188. gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::syncRenderOptions, this, *mOptions));
  189. mOptionsDirty = false;
  190. }
  191. gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
  192. }
  193. void BansheeRenderer::addToRenderQueue(const SPtr<CameraHandlerCore>& camera, RenderQueuePtr renderQueue)
  194. {
  195. RenderQueuePtr cameraRenderQueue = mCameraData[camera.get()].renderQueue;
  196. cameraRenderQueue->add(*renderQueue);
  197. }
  198. void BansheeRenderer::syncRenderOptions(const RenderBeastOptions& options)
  199. {
  200. bool filteringChanged = mCoreOptions->filtering != options.filtering;
  201. if (options.filtering == RenderBeastFiltering::Anisotropic)
  202. filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
  203. if (filteringChanged)
  204. {
  205. // TODO - Rebuild sample overrides
  206. }
  207. *mCoreOptions = options;
  208. }
  209. void BansheeRenderer::renderAllCore(float time)
  210. {
  211. THROW_IF_NOT_CORE_THREAD;
  212. // Update global per-frame hardware buffers
  213. mLitTexHandler->updatePerFrameBuffers(time);
  214. // Sort cameras by render target
  215. for (auto& cameraData : mCameraData)
  216. {
  217. const CameraHandlerCore* camera = cameraData.first;
  218. SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
  219. if (renderTarget == nullptr)
  220. continue;
  221. auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
  222. if (findIter != mRenderTargets.end())
  223. {
  224. findIter->cameras.push_back(camera);
  225. }
  226. else
  227. {
  228. mRenderTargets.push_back(RenderTargetData());
  229. RenderTargetData& renderTargetData = mRenderTargets.back();
  230. renderTargetData.target = renderTarget;
  231. renderTargetData.cameras.push_back(camera);
  232. }
  233. }
  234. // Sort everything based on priority
  235. auto cameraComparer = [&](const CameraHandlerCore* a, const CameraHandlerCore* b) { return a->getPriority() > b->getPriority(); };
  236. auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
  237. { return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
  238. std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
  239. for (auto& camerasPerTarget : mRenderTargets)
  240. {
  241. Vector<const CameraHandlerCore*>& cameras = camerasPerTarget.cameras;
  242. std::sort(begin(cameras), end(cameras), cameraComparer);
  243. }
  244. // Render everything, target by target
  245. for (auto& renderTargetData : mRenderTargets)
  246. {
  247. SPtr<RenderTargetCore> target = renderTargetData.target;
  248. Vector<const CameraHandlerCore*>& cameras = renderTargetData.cameras;
  249. RenderAPICore::instance().beginFrame();
  250. RenderAPICore::instance().setRenderTarget(target);
  251. for(auto& camera : cameras)
  252. {
  253. SPtr<ViewportCore> viewport = camera->getViewport();
  254. RenderAPICore::instance().setViewport(viewport->getNormArea());
  255. UINT32 clearBuffers = 0;
  256. if(viewport->getRequiresColorClear())
  257. clearBuffers |= FBT_COLOR;
  258. if(viewport->getRequiresDepthClear())
  259. clearBuffers |= FBT_DEPTH;
  260. if(viewport->getRequiresStencilClear())
  261. clearBuffers |= FBT_STENCIL;
  262. if(clearBuffers != 0)
  263. RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
  264. render(*camera, mCameraData[camera].renderQueue);
  265. }
  266. RenderAPICore::instance().endFrame();
  267. RenderAPICore::instance().swapBuffers(target);
  268. }
  269. mRenderTargets.clear();
  270. }
  271. void BansheeRenderer::render(const CameraHandlerCore& camera, RenderQueuePtr& renderQueue)
  272. {
  273. THROW_IF_NOT_CORE_THREAD;
  274. RenderAPICore& rs = RenderAPICore::instance();
  275. // Update global per-frame hardware buffers
  276. mLitTexHandler->updatePerCameraBuffers(camera.getForward());
  277. Matrix4 projMatrixCstm = camera.getProjectionMatrixRS();
  278. Matrix4 viewMatrixCstm = camera.getViewMatrix();
  279. Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
  280. // Trigger pre-render callbacks
  281. auto iterCameraCallbacks = mRenderCallbacks.find(&camera);
  282. if (iterCameraCallbacks != mRenderCallbacks.end())
  283. {
  284. for (auto& callbackPair : iterCameraCallbacks->second)
  285. {
  286. if (callbackPair.first >= 0)
  287. break;
  288. callbackPair.second();
  289. }
  290. }
  291. UINT64 cameraLayers = camera.getLayers();
  292. ConvexVolume worldFrustum = camera.getWorldFrustum();
  293. // Update per-object param buffers and queue render elements
  294. for (auto& renderableData : mRenderables)
  295. {
  296. RenderableHandlerCore* renderable = renderableData.renderable;
  297. RenderableController* controller = renderableData.controller;
  298. UINT32 renderableType = renderable->getRenderableType();
  299. UINT32 rendererId = renderable->getRendererId();
  300. if ((renderable->getLayer() & cameraLayers) == 0)
  301. continue;
  302. // Update buffers
  303. for (auto& renderElem : renderableData.elements)
  304. {
  305. if (controller != nullptr)
  306. controller->bindPerObjectBuffers(renderElem);
  307. if (renderableType == RenType_LitTextured)
  308. {
  309. Matrix4 worldViewProjMatrix = viewProjMatrix * mWorldTransforms[rendererId];
  310. mLitTexHandler->updatePerObjectBuffers(renderElem, worldViewProjMatrix);
  311. }
  312. UINT32 numPasses = renderElem.material->getNumPasses();
  313. for (UINT32 i = 0; i < numPasses; i++)
  314. {
  315. SPtr<PassParametersCore> passParams = renderElem.material->getPassParameters(i);
  316. for (UINT32 j = 0; j < passParams->getNumParams(); j++)
  317. {
  318. SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
  319. if (params != nullptr)
  320. params->updateHardwareBuffers();
  321. }
  322. }
  323. }
  324. // Do frustum culling
  325. // TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
  326. // methods use vector operations, as it is trivial to update them.
  327. const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
  328. if (worldFrustum.intersects(boundingSphere))
  329. {
  330. // More precise with the box
  331. const AABox& boundingBox = mWorldBounds[rendererId].getBox();
  332. if (worldFrustum.intersects(boundingBox))
  333. {
  334. float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
  335. for (auto& renderElem : renderableData.elements)
  336. renderQueue->add(&renderElem, distanceToCamera);
  337. }
  338. }
  339. }
  340. renderQueue->sort();
  341. const Vector<RenderQueueElement>& sortedRenderElements = renderQueue->getSortedElements();
  342. for(auto iter = sortedRenderElements.begin(); iter != sortedRenderElements.end(); ++iter)
  343. {
  344. SPtr<MaterialCore> material = iter->material;
  345. RenderableElement* renderable = iter->renderElem;
  346. if (renderable != nullptr && renderable->samplerOverrides != nullptr)
  347. setPass(material, iter->passIdx, renderable->samplerOverrides[iter->passIdx]);
  348. else
  349. setPass(material, iter->passIdx, nullptr);
  350. draw(iter->mesh, iter->subMesh);
  351. }
  352. renderQueue->clear();
  353. // Trigger post-render callbacks
  354. if (iterCameraCallbacks != mRenderCallbacks.end())
  355. {
  356. for (auto& callbackPair : iterCameraCallbacks->second)
  357. {
  358. if (callbackPair.first < 0)
  359. continue;
  360. callbackPair.second();
  361. }
  362. }
  363. }
  364. void BansheeRenderer::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, SPtr<SamplerStateCore>* samplerOverrides)
  365. {
  366. THROW_IF_NOT_CORE_THREAD;
  367. RenderAPICore& rs = RenderAPICore::instance();
  368. SPtr<PassCore> pass = material->getPass(passIdx);
  369. SPtr<PassParametersCore> passParams = material->getPassParameters(passIdx);
  370. struct StageData
  371. {
  372. GpuProgramType type;
  373. bool enable;
  374. SPtr<GpuParamsCore> params;
  375. SPtr<GpuProgramCore> program;
  376. };
  377. const UINT32 numStages = 6;
  378. StageData stages[numStages] =
  379. {
  380. {
  381. GPT_VERTEX_PROGRAM, pass->hasVertexProgram(),
  382. passParams->mVertParams, pass->getVertexProgram()
  383. },
  384. {
  385. GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(),
  386. passParams->mFragParams, pass->getFragmentProgram()
  387. },
  388. {
  389. GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(),
  390. passParams->mGeomParams, pass->getGeometryProgram()
  391. },
  392. {
  393. GPT_HULL_PROGRAM, pass->hasHullProgram(),
  394. passParams->mHullParams, pass->getHullProgram()
  395. },
  396. {
  397. GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(),
  398. passParams->mDomainParams, pass->getDomainProgram()
  399. },
  400. {
  401. GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(),
  402. passParams->mComputeParams, pass->getComputeProgram()
  403. }
  404. };
  405. for (UINT32 i = 0; i < numStages; i++)
  406. {
  407. const StageData& stage = stages[i];
  408. if (stage.enable)
  409. {
  410. rs.bindGpuProgram(stage.program);
  411. SPtr<GpuParamsCore> params = stage.params;
  412. const GpuParamDesc& paramDesc = params->getParamDesc();
  413. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  414. {
  415. SPtr<SamplerStateCore> samplerState;
  416. if (samplerOverrides != nullptr)
  417. samplerState = samplerOverrides[iter->second.slot];
  418. else
  419. samplerState = params->getSamplerState(iter->second.slot);
  420. if (samplerState == nullptr)
  421. rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
  422. else
  423. rs.setSamplerState(stage.type, iter->second.slot, samplerState);
  424. }
  425. for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
  426. {
  427. SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
  428. if (!params->isLoadStoreTexture(iter->second.slot))
  429. {
  430. if (texture == nullptr)
  431. rs.setTexture(stage.type, iter->second.slot, false, nullptr);
  432. else
  433. rs.setTexture(stage.type, iter->second.slot, true, texture);
  434. }
  435. else
  436. {
  437. const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
  438. if (texture == nullptr)
  439. rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
  440. else
  441. rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
  442. }
  443. }
  444. rs.setConstantBuffers(stage.type, params);
  445. }
  446. else
  447. rs.unbindGpuProgram(stage.type);
  448. }
  449. // TODO - Try to limit amount of state changes, if previous state is already the same
  450. // Set up non-texture related pass settings
  451. if (pass->getBlendState() != nullptr)
  452. rs.setBlendState(pass->getBlendState());
  453. else
  454. rs.setBlendState(BlendStateCore::getDefault());
  455. if (pass->getDepthStencilState() != nullptr)
  456. rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
  457. else
  458. rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
  459. if (pass->getRasterizerState() != nullptr)
  460. rs.setRasterizerState(pass->getRasterizerState());
  461. else
  462. rs.setRasterizerState(RasterizerStateCore::getDefault());
  463. }
  464. SPtr<ShaderCore> BansheeRenderer::createDefaultShader()
  465. {
  466. StringID rsName = RenderAPICore::instance().getName();
  467. SPtr<GpuProgramCore> vsProgram;
  468. SPtr<GpuProgramCore> psProgram;
  469. if (rsName == RenderAPIDX11)
  470. {
  471. String vsCode = R"(
  472. cbuffer PerObject
  473. {
  474. float4x4 matWorldViewProj;
  475. }
  476. void vs_main(
  477. in float3 inPos : POSITION,
  478. out float4 oPosition : SV_Position)
  479. {
  480. oPosition = mul(matWorldViewProj, float4(inPos.xyz, 1));
  481. })";
  482. String psCode = R"(
  483. float4 ps_main() : SV_Target
  484. {
  485. return float4(0.3f, 0.9f, 0.3f, 1.0f);
  486. })";
  487. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  488. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  489. }
  490. else if (rsName == RenderAPIDX9)
  491. {
  492. String vsCode = R"(
  493. BS_PARAM_BLOCK PerObject { matWorldViewProj }
  494. float4x4 matWorldViewProj;
  495. void vs_main(
  496. in float3 inPos : POSITION,
  497. out float4 oPosition : POSITION)
  498. {
  499. oPosition = mul(matWorldViewProj, float4(inPos.xyz, 1));
  500. })";
  501. String psCode = R"(
  502. float4 ps_main() : COLOR0
  503. {
  504. return float4(0.3f, 0.9f, 0.3f, 1.0f);
  505. })";
  506. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl9", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
  507. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl9", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
  508. }
  509. else if (rsName == RenderAPIOpenGL)
  510. {
  511. String vsCode = R"(
  512. uniform PerObject
  513. {
  514. mat4 matWorldViewProj;
  515. };
  516. in vec3 bs_position;
  517. out gl_PerVertex
  518. {
  519. vec4 gl_Position;
  520. };
  521. void main()
  522. {
  523. gl_Position = matWorldViewProj * vec4(bs_position.xyz, 1);
  524. })";
  525. String psCode = R"(
  526. out vec4 fragColor;
  527. void main()
  528. {
  529. fragColor = vec4(0.3f, 0.9f, 0.3f, 1.0f);
  530. })";
  531. vsProgram = GpuProgramCore::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  532. psProgram = GpuProgramCore::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  533. }
  534. PASS_DESC_CORE passDesc;
  535. passDesc.vertexProgram = vsProgram;
  536. passDesc.fragmentProgram = psProgram;
  537. SPtr<PassCore> newPass = PassCore::create(passDesc);
  538. SPtr<TechniqueCore> newTechnique = TechniqueCore::create(rsName, RendererDefault, { newPass });
  539. SHADER_DESC_CORE shaderDesc;
  540. shaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
  541. shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
  542. SPtr<ShaderCore> defaultShader = ShaderCore::create("DummyShader", shaderDesc, { newTechnique });
  543. return defaultShader;
  544. }
  545. }