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