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