1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     DynamicMaterialDemo.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #define NW_DEBUG_CHECK_MEMORY_LEAK
19 
20 #include <nn/os.h>
21 #include <nn/fs.h>
22 
23 #include <nw/types.h>
24 
25 #include <nw/demo.h>
26 #include <nw/dev.h>
27 #include <nw/gfx.h>
28 #include <nw/ut.h>
29 #include <nw/anim.h>
30 
31 namespace
32 {
33 
34 //----------------------------------------
35 // マテリアル関係
36 // マテリアルの状態を表す UserFlag です
37 enum UserFlags
38 {
39     MATERIAL_DEFAULT_SHIFT,
40     MATERIAL_CHANGE_SHIFT,
41 
42     MATERIAL_DEFAULT = 0x1 << MATERIAL_DEFAULT_SHIFT,
43     MATERIAL_CHANGE = 0x1 << MATERIAL_CHANGE_SHIFT
44 };
45 
46 // Material の default が指定されたモデルのみを描画要素に加える関数オブジェクトです。
47 class IsMaterialDefaultModelFunctor : public nw::gfx::ISceneUpdater::IsVisibleModelFunctor
48 {
49 public:
IsVisible(const nw::gfx::Model * model)50     virtual bool IsVisible(const nw::gfx::Model* model)
51     {
52         return nw::ut::CheckFlag(model->GetUserParameter<u32>(), MATERIAL_DEFAULT);
53     }
54 };
55 
56 // Material の change が指定されたモデルのみを描画要素に加える関数オブジェクトです。
57 class IsMaterialChangeModelFunctor : public nw::gfx::ISceneUpdater::IsVisibleModelFunctor
58 {
59 public:
IsVisible(const nw::gfx::Model * model)60     virtual bool IsVisible(const nw::gfx::Model* model)
61     {
62         return nw::ut::CheckFlag(model->GetUserParameter<u32>(), MATERIAL_CHANGE);
63     }
64 };
65 
66 IsMaterialDefaultModelFunctor s_MaterialDefaultModel;
67 IsMaterialChangeModelFunctor s_MaterialChangeModel;
68 
69 // マテリアルの差し替え設定を行うレンダーコマンドです。
70 class StartMaterialChangeRenderCommand : public nw::gfx::RenderCommand
71 {
72     NW_DISALLOW_COPY_AND_ASSIGN(StartMaterialChangeRenderCommand);
73 
74 public:
StartMaterialChangeRenderCommand(nw::gfx::Material * changeMaterial)75     StartMaterialChangeRenderCommand(nw::gfx::Material* changeMaterial)
76         : m_ChangeMaterial(changeMaterial)
77     {}
~StartMaterialChangeRenderCommand()78     virtual ~StartMaterialChangeRenderCommand() {}
79 
Invoke(nw::gfx::RenderContext * renderContext)80     virtual void Invoke(nw::gfx::RenderContext* renderContext)
81     {
82         // マテリアルを差し替えます。
83         renderContext->SetMaterial(m_ChangeMaterial);
84         renderContext->ActivateContext();
85 
86         // RENDERMODE_IGNORE_MATERIAL を用いて以降のマテリアル設定を行いません。
87         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_IGNORE_MATERIAL);
88     }
89 
90 private:
91     nw::gfx::Material* m_ChangeMaterial;
92 };
93 
94 // マテリアルの差し替えの後処理を行うレンダーコマンドです。
95 class EndMaterialChangeRenderCommand : public nw::gfx::RenderCommand
96 {
97     NW_DISALLOW_COPY_AND_ASSIGN(EndMaterialChangeRenderCommand);
98 
99 public:
EndMaterialChangeRenderCommand()100     EndMaterialChangeRenderCommand()
101     {}
~EndMaterialChangeRenderCommand()102     virtual ~EndMaterialChangeRenderCommand() {}
103 
Invoke(nw::gfx::RenderContext * renderContext)104     virtual void Invoke(nw::gfx::RenderContext* renderContext)
105     {
106         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_DEFAULT);
107     }
108 };
109 
110 StartMaterialChangeRenderCommand* s_StartMaterialChangeRenderCommand = NULL;
111 EndMaterialChangeRenderCommand* s_EndMaterialChangeRenderCommand = NULL;
112 
113 //----------------------------------------
114 // メモリ関係
115 
116 // デバイスメモリを確保するためのアロケータです。
117 nw::demo::DemoAllocator s_DeviceAllocator;
118 
119 //----------------------------------------
120 // ファイル名の定義です。
121 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
122 
123 const wchar_t* MODEL_RESOURCE_FILES[] =
124 {
125     NW_DEMO_FILE_PATH(L"DynamicMaterial.bcmdl"),
126     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
127     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
128 };
129 
130 //----------------------------------------
131 // 描画関係
132 const int RENDER_TARGET_COUNT = 1;
133 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
134 
135 RenderTargetArray s_RenderTargets;
136 nw::demo::SceneSystem*  s_SceneSystem = NULL;
137 nw::demo::RenderSystem* s_RenderSystem = NULL;
138 
139 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
140 
141 //----------------------------------------
142 // リソース関係
143 nw::demo::ResourceArray s_Resources;
144 nw::demo::ResourceSet s_LutResource;
145 nw::demo::ResourceSet s_TextureResource;
146 
147 static const wchar_t* LUT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"Lutset.bclts");
148 static const wchar_t* TEXTURE_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"Texture2.bctex");
149 
150 //----------------------------------------
151 // シーン関係
152 const int SCENE_NODE_COUNT = 7;
153 nw::gfx::SceneNode* s_SceneRoot = NULL;
154 nw::gfx::SceneNode* s_ModelRoot = NULL;
155 s32 s_FrameCount = 0;
156 s32 s_ChangeFrameCount = 0;
157 const s32 s_ChangeFrame = 100;
158 bool s_ChangeMaterial = false;
159 nw::gfx::Camera* s_BaseCamera = NULL;
160 nw::gfx::Camera* s_LeftCamera = NULL;
161 nw::gfx::Camera* s_RightCamera = NULL;
162 const f32 s_fNearPlane = 0.1f;
163 f32 s_TorusTranslate = 0.0f;
164 
165 nw::gfx::Model* s_BufferTorus = NULL;
166 nw::gfx::Model* s_LutTorus = NULL;
167 nw::gfx::Model* s_TextureTorus = NULL;
168 nw::gfx::Material* s_EdgeMaterial = NULL;
169 
170 nw::gfx::res::ResTexture s_ChangedTexture;
171 nw::gfx::res::ResLookupTable s_ChangedLut;
172 nw::ut::FloatColor s_DiffuseColor(1.0f, 0.0f, 0.0f, 1.0f);
173 
174 //----------------------------------------
175 // シーン環境関係
176 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
177 
178 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
179 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
180 
181 const s32 s_BaseCameraIndex = 0;
182 
183 /*!--------------------------------------------------------------------------*
184   @brief        グラフィックス関連の初期化を行います。
185  *---------------------------------------------------------------------------*/
186 void
InitializeGraphics()187 InitializeGraphics()
188 {
189     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
190 
191     // renderDescriptionへステレオの設定を行います。
192     nw::demo::RenderSystem::Description renderDescription;
193 
194     renderDescription.reusableCommandBufferSize = 0x100000;
195     renderDescription.reusableCommandRequestCount = 512;
196     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
197 
198     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
199 
200     s_GraphicsDrawing.SetScreenSize(
201         renderDescription.lowerScreenDescription.width,
202         renderDescription.lowerScreenDescription.height
203     );
204 
205     nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
206 
207     s_RenderTargets.push_back(
208         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
209     );
210     NW_ASSERT(!s_RenderTargets.empty());
211     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
212 
213     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
214     nw::demo::SceneSystem::Description sceneDescription;
215     sceneDescription.isFixedSizeMemory = true;
216     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
217 
218     // デモ用の最遠景モデルをレンダリングシステムに設定します。
219     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
220     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
221 
222     NW_GL_ASSERT();
223 }
224 
225 /*!--------------------------------------------------------------------------*
226   @brief        グラフィックス関連の後始末をします。
227  *---------------------------------------------------------------------------*/
228 void
TerminateGraphics()229 TerminateGraphics()
230 {
231     nw::gfx::SafeDestroy(s_LeftCamera);
232 
233     nw::gfx::SafeDestroy(s_RightCamera);
234 
235     nw::gfx::SafeDestroy(s_SceneSystem);
236 
237     nw::gfx::SafeDestroyAll(s_RenderTargets);
238 
239     s_GraphicsDrawing.Finalize();
240 
241     nw::gfx::SafeDestroy(s_RenderSystem);
242 
243     NW_GL_ASSERT();
244 }
245 
246 /*!--------------------------------------------------------------------------*
247   @brief        ルートノード関連の構築をします。
248  *---------------------------------------------------------------------------*/
249 void
BuildRootNodes()250 BuildRootNodes()
251 {
252     NW_ASSERT(s_SceneRoot == NULL);
253     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
254         .Create(&s_DeviceAllocator);
255     NW_NULL_ASSERT(s_SceneRoot);
256 
257     NW_ASSERT(s_ModelRoot == NULL);
258     s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
259         .Create(&s_DeviceAllocator);
260     s_SceneRoot->AttachChild(s_ModelRoot);
261     NW_NULL_ASSERT(s_ModelRoot);
262 }
263 
264 /*!--------------------------------------------------------------------------*
265   @brief        カメラ関連の構築をします。
266  *---------------------------------------------------------------------------*/
267 void
BuildCameras()268 BuildCameras()
269 {
270     nw::demo::Utility::CreateStereoCameras(
271         &s_BaseCamera,
272         &s_LeftCamera,
273         &s_RightCamera,
274         &s_DeviceAllocator,
275         nw::math::VEC3(0.0f, 2.25f, 10.0f),
276         nw::math::VEC3(0.0f, 2.25f, 0.0f),
277         s_fNearPlane
278     );
279 
280     s_SceneRoot->AttachChild(s_BaseCamera);
281     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
282 }
283 
284 /*!--------------------------------------------------------------------------*
285   @brief        リソース関連の構築をします。
286  *---------------------------------------------------------------------------*/
287 void
BuildResources(nw::demo::ResourceSet * resourceSet)288 BuildResources(nw::demo::ResourceSet* resourceSet)
289 {
290     resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
291     resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
292     resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
293 
294     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
295     if (result.IsFailure())
296     {
297         if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT)
298         {
299             // 参照テーブルが見つからなかったときは、外部ファイルを指定して再びセットアップします。
300             result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResource.resource);
301         }
302 
303         if (result.IsFailure())
304         {
305             NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
306         }
307     }
308 
309     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
310 
311     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
312     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
313     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
314          modelResource != modelsEnd; ++modelResource)
315     {
316         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
317             &s_DeviceAllocator,
318             (*modelResource),
319             false
320         );
321         NW_NULL_ASSERT(node);
322 
323         nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(node);
324         NW_NULL_ASSERT(model);
325 
326         if (::std::strcmp(model->GetName(), "Edge") == 0)
327         {
328             model->SetVisible(false);
329             s_EdgeMaterial = model->GetMaterial(0);
330         }
331         else if(::std::strcmp(model->GetName(), "LutTorus") == 0)
332         {
333             model->Transform().SetTranslate(0.0f, s_TorusTranslate, 0.0f);
334             model->SetUserParameter(MATERIAL_DEFAULT);
335             s_TorusTranslate += 1.5f;
336             s_LutTorus = model;
337         }
338         else if(::std::strcmp(model->GetName(), "TextureTorus") == 0)
339         {
340             model->Transform().SetTranslate(0.0f, s_TorusTranslate, 0.0f);
341             model->SetUserParameter(MATERIAL_DEFAULT);
342             s_TorusTranslate += 1.5f;
343             s_TextureTorus = model;
344         }
345         else if(::std::strcmp(model->GetName(), "Torus") == 0)
346         {
347             nw::gfx::Model* changeModel = nw::ut::DynamicCast<nw::gfx::Model*>(node);
348             NW_NULL_ASSERT(changeModel);
349 
350             changeModel->Transform().SetTranslate(0.0f, s_TorusTranslate, 0.0f);
351             s_TorusTranslate += 1.5f;
352             changeModel->SetUserParameter(MATERIAL_CHANGE);
353 
354             // バッファオプションを指定してモデルを生成します。
355             nw::gfx::SceneNode* bufferNode = nw::demo::Utility::CreateSceneNode(
356                 &s_DeviceAllocator,
357                 (*modelResource),
358                 false,
359                 nw::gfx::Model::FLAG_BUFFER_MATERIAL_COLOR
360                 );
361             NW_NULL_ASSERT(bufferNode);
362 
363             nw::gfx::Model* bufferModel = nw::ut::DynamicCast<nw::gfx::Model*>(bufferNode);
364             NW_NULL_ASSERT(bufferModel);
365 
366             bufferModel->Transform().SetTranslate(0.0f, s_TorusTranslate, 0.0f);
367             s_TorusTranslate += 1.5f;
368             s_BufferTorus = bufferModel;
369             bufferModel->SetUserParameter(MATERIAL_DEFAULT);
370             sceneNodeArray.push_back(bufferNode);
371         }
372 
373         sceneNodeArray.push_back(node);
374     }
375 
376     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
377     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
378     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
379          lightResource != lightsEnd; ++lightResource)
380     {
381         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
382             &s_DeviceAllocator,
383             (*lightResource)
384         );
385         NW_NULL_ASSERT(node);
386         sceneNodeArray.push_back(node);
387     }
388 
389     // 親子付け参照関係を解決
390     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
391 
392     // モデルをシーンに追加
393     nw::gfx::SceneHelper::ForeachRootNodes(
394         sceneNodeArray.Begin(),
395         sceneNodeArray.End(),
396         nw::gfx::AttachNode(s_ModelRoot)
397     );
398 
399     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
400     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
401     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
402         settingResource != settingsEnd; ++settingResource)
403     {
404         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
405             .Resource(*settingResource)
406             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
407 
408         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
409             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
410 
411         NW_NULL_ASSERT(sceneEnvironmentSetting);
412         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
413     }
414 }
415 
416 /*!--------------------------------------------------------------------------*
417   @brief        シーンを初期化します。
418  *---------------------------------------------------------------------------*/
419 void
InitializeScenes()420 InitializeScenes()
421 {
422     // ファイルから LUT Set を読み込みます。
423     s_LutResource.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , LUT_RESOURCE_FILE);
424     NW_NULL_ASSERT(s_LutResource.buffer);
425     s_LutResource.resource = nw::gfx::ResGraphicsFile(&(s_LutResource.buffer.front()));
426     s_LutResource.resource.Setup(&s_DeviceAllocator);
427     s_ChangedLut = s_LutResource.resource.GetLutSets(0).GetSamplers("toon_reflectance");
428 
429     s_TextureResource.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator, TEXTURE_RESOURCE_FILE);
430     NW_NULL_ASSERT(s_TextureResource.buffer);
431     s_TextureResource.resource = nw::gfx::ResGraphicsFile(&(s_TextureResource.buffer.front()));
432     s_TextureResource.resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
433     s_TextureResource.resource.Setup(&s_DeviceAllocator);
434     s_ChangedTexture = s_TextureResource.resource.GetTextures(0);
435 
436     BuildRootNodes();
437 
438     BuildCameras();
439 
440     s_TorusTranslate = 0.0f;
441     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
442     {
443         BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
444     }
445 
446     // シーンツリーを巡回して初期化を行います。
447     s_SceneSystem->InitializeScene(s_SceneRoot);
448     s_SceneSystem->UpdateScene();
449 
450     // シーン環境の参照解決を行い設定します。
451     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
452 
453     // カメラを設定します。
454     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
455     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
456     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
457 
458     // レンダーコマンドを作成します。
459     void* startMaterialChangeCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartMaterialChangeRenderCommand));
460     NW_NULL_ASSERT(startMaterialChangeCommandMemory);
461     s_StartMaterialChangeRenderCommand =
462         new(startMaterialChangeCommandMemory) StartMaterialChangeRenderCommand(s_EdgeMaterial);
463 
464     void* endMaterialChangeCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndMaterialChangeRenderCommand));
465     NW_NULL_ASSERT(endMaterialChangeCommandMemory);
466     s_EndMaterialChangeRenderCommand =
467         new(endMaterialChangeCommandMemory) EndMaterialChangeRenderCommand();
468 
469     NW_GL_ASSERT();
470 
471     s_FrameCount = 0;
472 }
473 
474 /*!--------------------------------------------------------------------------*
475   @brief        シーン関連の後始末をします。
476  *---------------------------------------------------------------------------*/
477 void
TerminateScenes()478 TerminateScenes()
479 {
480     s_DeviceAllocator.Free(s_EndMaterialChangeRenderCommand);
481     s_EndMaterialChangeRenderCommand = NULL;
482     s_DeviceAllocator.Free(s_StartMaterialChangeRenderCommand);
483     s_StartMaterialChangeRenderCommand = NULL;
484 
485     s_LutTorus = NULL;
486     s_TextureTorus = NULL;
487     s_EdgeMaterial = NULL;
488     s_BufferTorus = NULL;
489 
490     nw::gfx::SafeDestroyBranch(s_SceneRoot);
491     nw::demo::SafeCleanupResources(s_Resources);
492     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
493 
494     nw::ut::SafeCleanup(s_TextureResource.resource);
495     nw::ut::SafeCleanup(s_LutResource.resource);
496 
497     NW_GL_ASSERT();
498 
499     s_TextureResource.buffer = nw::ut::MoveArray<u8>();
500     s_LutResource.buffer = nw::ut::MoveArray<u8>();
501 
502     s_Resources.clear();
503     s_SceneEnvironmentSettings.clear();
504 
505     s_ModelRoot = NULL;
506 }
507 
508 /*!--------------------------------------------------------------------------*
509   @brief        シーンを更新します。
510                 それぞのモデルのマテリアルの変更を行います。
511  *---------------------------------------------------------------------------*/
512 void
ChangeMaterial()513 ChangeMaterial()
514 {
515     if (s_ChangeFrameCount > s_ChangeFrame)
516     {
517         // torus のマテリアルカラーを変更します。
518         // マテリアルバッファを用いているためにベースとなる torus の色は変更されません。
519         {
520             nw::gfx::res::ResMaterial resTorusMaterial = s_BufferTorus->GetMaterial(0)->GetMaterialColorResMaterial();
521             NW_ASSERT(resTorusMaterial.IsValid());
522             nw::gfx::res::ResMaterialColor resMaterialColor = resTorusMaterial.GetMaterialColor();
523             nw::ut::FloatColor floatColor = resMaterialColor.GetDiffuse();
524             resMaterialColor.SetDiffuse(s_DiffuseColor);
525             s_DiffuseColor = floatColor;
526 
527             // NOTE: マテリアルバッファはハッシュが無効になっていますので、0x0 を設定する必要はありません。
528             // resTorusMaterial.SetMaterialColorHash(0x0);
529         }
530 
531         // texture_torus のテクスチャを差し替えます。
532         {
533             nw::gfx::res::ResMaterial resTorusMaterial = s_TextureTorus->GetMaterial(0)->GetTextureMapperResMaterial();
534             NW_ASSERT(resTorusMaterial.IsValid());
535             nw::gfx::res::ResTextureMapper resTextureMapper = resTorusMaterial.GetTextureMappers(0);
536             nw::gfx::res::ResTexture resTexture = resTextureMapper.GetTexture().Dereference();
537             resTextureMapper.SetTexture(s_ChangedTexture);
538             s_ChangedTexture = resTexture;
539 
540             // テクスチャを変更した場合はテクスチャマッパーのハッシュを0に設定します。
541             resTorusMaterial.SetTextureMappersHash(0x0);
542         }
543 
544         // lut_torus の参照テーブルを差し替えます。
545         {
546             nw::gfx::res::ResMaterial resTorusMaterial = s_LutTorus->GetMaterial(0)->GetFragmentLightingTableResMaterial();
547             NW_ASSERT(resTorusMaterial.IsValid());
548             nw::gfx::res::ResFragmentLightingTable resFragmentLightingLut = resTorusMaterial.GetFragmentShader().GetFragmentLightingTable();
549             nw::gfx::res::ResLightingLookupTable resLightingLut = resFragmentLightingLut.GetReflectanceRSampler();
550             nw::gfx::res::ResLookupTable resLut = resLightingLut.GetSampler().Dereference();
551             resLightingLut.SetSampler(s_ChangedLut);
552             s_ChangedLut = resLut;
553 
554             // 参照テーブルを変更した場合はフラグメントライティングテーブルのハッシュを0に設定します。
555             resTorusMaterial.SetFragmentLightingTableHash(0x0);
556         }
557     }
558 }
559 
560 /*!--------------------------------------------------------------------------*
561   @brief        レンダーキューにモデルの追加を行います。
562                 独自マテリアルでの描画を行うためにコールバックの設定をします。
563  *---------------------------------------------------------------------------*/
564 void
SubmitView()565 SubmitView()
566 {
567     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
568     nw::gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
569     nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
570 
571     nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
572 
573     renderQueue->Reset();
574 
575     s_SceneSystem->GetSceneUpdater()->SubmitView(
576         renderQueue,
577         sceneContext,
578         *s_BaseCamera,
579         0,
580         1,
581         &s_MaterialDefaultModel,
582         s_RenderSystem->GetRenderSortMode());
583 
584     if (s_ChangeMaterial)
585     {
586         // マテリアルの変更を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
587         s_RenderSystem->EnqueueRenderCommand(
588             s_StartMaterialChangeRenderCommand, nw::gfx::res::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 1);
589     }
590 
591     s_SceneSystem->GetSceneUpdater()->SubmitView(
592         renderQueue,
593         sceneContext,
594         *s_BaseCamera,
595         2,
596         2,
597         &s_MaterialChangeModel,
598         s_RenderSystem->GetRenderSortMode());
599 
600     if (s_ChangeMaterial)
601     {
602         // マテリアルの変更の後処理行うコマンドをレイヤー2の後に実行するコールバックに追加します。
603         s_RenderSystem->EnqueueRenderCommand(
604             s_EndMaterialChangeRenderCommand, nw::gfx::res::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 2);
605     }
606 
607     // レンダーキューをソートします。
608     // RenderElementCompare() やレンダーキーファクトリーをカスタマイズすることで
609     // 描画順を変更することができます。
610     // 詳しくは最適化TIPSを参照してください。
611     std::sort(
612         renderQueue->Begin(),
613         renderQueue->End(),
614         nw::gfx::RenderElementCompare());
615 }
616 
617 /*!--------------------------------------------------------------------------*
618   @brief        シーンを更新します。
619  *---------------------------------------------------------------------------*/
620 void
UpdateScene()621 UpdateScene()
622 {
623     s_SceneSystem->GetCameraController()->Update();
624 
625     s_SceneSystem->UpdateScene();
626 
627     s_BaseCamera->UpdateCameraMatrix();
628 
629     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
630 
631     ++s_FrameCount;
632 }
633 
634 /*!--------------------------------------------------------------------------*
635   @brief        負荷表示やテスト機能の処理をおこないます。
636  *---------------------------------------------------------------------------*/
637 void
ReportDemo()638 ReportDemo()
639 {
640     NW_PROFILE("ReportDemo");
641 
642     // 負荷表示からはこれらの負荷は除きます。
643     s_RenderSystem->SuspendLoadMeter();
644 
645     nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
646 
647     s_GraphicsDrawing.BeginDrawingShape();
648 
649     nw::demo::DebugUtility::DrawLoadMeter(
650         s_RenderSystem,
651         &s_GraphicsDrawing
652     );
653 
654     s_GraphicsDrawing.EndDrawingShape();
655 
656     s_GraphicsDrawing.BeginDrawingString();
657 
658     nw::demo::DebugUtility::DrawLoadMeterText(
659         s_RenderSystem,
660         &s_GraphicsDrawing
661     );
662 
663     s_GraphicsDrawing.EndDrawingString();
664 
665     s_RenderSystem->ResumeLoadMeter();
666 }
667 
668 /*!--------------------------------------------------------------------------*
669   @brief        シーンをデモンストレーションします。
670  *---------------------------------------------------------------------------*/
671 void
DemoScene()672 DemoScene()
673 {
674     NW_ASSERT(!s_RenderTargets.empty());
675 
676     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
677 
678     InitializeScenes();
679 
680     nw::demo::DebugUtility::PostInitializeScenes();
681 
682     bool isContinuing = true;
683 
684     while ( isContinuing )
685     {
686         nw::demo::DebugUtility::AdvanceAutoTestFrame();
687 
688         nw::demo::PadFactory::GetPad()->Update();
689 
690         UpdateScene();
691 
692         // マテリアルの変更を行います。
693         ChangeMaterial();
694 
695         renderContext->SetActiveCamera(s_BaseCameraIndex);
696 
697         // レンダーキューへのモデルの追加を行います。
698         // 独自マテリアルでの描画を行うためにカスタマイズします。
699         SubmitView();
700 
701         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
702         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
703 
704         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
705         ReportDemo();
706         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
707 
708         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
709 
710         renderContext->ResetState();
711 
712         if (nw::demo::Utility::IsTerminating())
713         {
714             isContinuing = false;
715         }
716 
717         if (s_ChangeFrameCount > s_ChangeFrame)
718         {
719             s_ChangeMaterial = !s_ChangeMaterial;
720             s_ChangeFrameCount = 0;
721         }
722 
723         ++s_ChangeFrameCount;
724     }
725 
726     nw::demo::DebugUtility::PreTerminateScenes();
727 
728     TerminateScenes();
729 }
730 
731 } // namespace
732 
733 /*!--------------------------------------------------------------------------*
734   @brief        メイン関数です。
735  *---------------------------------------------------------------------------*/
736 void
nnMain()737 nnMain()
738 {
739     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
740 
741     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
742 
743     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
744     {
745         InitializeGraphics();
746 
747         DemoScene();
748 
749         TerminateGraphics();
750     }
751 
752     nw::demo::PadFactory::Finalize();
753 
754     nw::demo::FinalizeGraphicsSystem();
755 }
756