1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ProjectionShadowDemo.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: 29438 $
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     SHADOW_CASTER_SHIFT = 0,
38     SHADOW_RECEIVER_SHIFT = 1,
39 
40     SHADOW_CASTER = 0x1 << SHADOW_CASTER_SHIFT,
41     SHADOW_RECEIVER = 0x1 << SHADOW_RECEIVER_SHIFT
42 };
43 
44 // Shadow の Caster のみを描画要素に加える関数オブジェクトです。
45 class IsShadowCasterModelFunctor : 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>(), SHADOW_CASTER);
51     }
52 };
53 
54 IsShadowCasterModelFunctor s_ShadowCasterModel;
55 
56 // シャドウの設定を行うレンダーコマンドです。
57 class StartShadowRenderCommand : public nw::gfx::RenderCommand
58 {
59     NW_DISALLOW_COPY_AND_ASSIGN(StartShadowRenderCommand);
60 
61 public:
StartShadowRenderCommand(nw::demo::CommandListSwapper * commandListSwapper,nw::gfx::IRenderTarget * renderTarget,s32 shadowCameraIndex,nw::gfx::Material * shadowMaterial)62     StartShadowRenderCommand(
63         nw::demo::CommandListSwapper* commandListSwapper,
64         nw::gfx::IRenderTarget* renderTarget,
65         s32 shadowCameraIndex,
66         nw::gfx::Material* shadowMaterial)
67         : m_CommandListSwapper(commandListSwapper),
68           m_RenderTarget(renderTarget),
69           m_ShadowCameraIndex(shadowCameraIndex),
70           m_ShadowMaterial(shadowMaterial),
71           m_CommandSize(0),
72           m_ProfilerPoint(0)
73     {}
~StartShadowRenderCommand()74     virtual ~StartShadowRenderCommand() {}
75 
Invoke(nw::gfx::RenderContext * renderContext)76     virtual void Invoke(nw::gfx::RenderContext* renderContext)
77     {
78         m_CommandSize = m_CommandListSwapper->GetCommandBufferSize();
79         m_ProfilerPoint = m_CommandListSwapper->AddGpuProfilingStartPoint(true);
80 
81         // オフスクリーンバッファに切り替えます。
82         renderContext->SetRenderTarget(m_RenderTarget);
83         renderContext->ClearBuffer(GL_COLOR_BUFFER_BIT, nw::ut::FloatColor(1.0f, 1.0f, 1.0f, 1.0f), 1.0f);
84 
85         // シャドウ用のマテリアル、カメラを設定します。
86         renderContext->SetActiveCamera(m_ShadowCameraIndex);
87         renderContext->SetMaterial(m_ShadowMaterial);
88         nw::gfx::Camera* shadowCamera = renderContext->GetActiveCamera();
89         renderContext->SetCameraMatrix(shadowCamera);
90         renderContext->ActivateContext();
91 
92         // 1Pass では RENDERMODE_IGNORE_MATERIAL を用いて以降のマテリアル設定を行いません。
93         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_IGNORE_MATERIAL);
94     }
95 
GetCommandSize() const96     s32 GetCommandSize() const { return this->m_CommandSize; }
GetProfilerPoint() const97     s32 GetProfilerPoint() const { return this->m_ProfilerPoint; }
98 
99 private:
100     nw::demo::CommandListSwapper* m_CommandListSwapper;
101     nw::gfx::IRenderTarget* m_RenderTarget;
102     s32 m_ShadowCameraIndex;
103     nw::gfx::Material* m_ShadowMaterial;
104     s32 m_CommandSize;
105     s32 m_ProfilerPoint;
106 };
107 
108 // シャドウの後処理を行うレンダーコマンドです。
109 class EndShadowRenderCommand : public nw::gfx::RenderCommand
110 {
111     NW_DISALLOW_COPY_AND_ASSIGN(EndShadowRenderCommand);
112 
113 public:
EndShadowRenderCommand(nw::demo::CommandListSwapper * commandListSwapper,StartShadowRenderCommand * startCommand)114     EndShadowRenderCommand(nw::demo::CommandListSwapper* commandListSwapper, StartShadowRenderCommand* startCommand)
115         : m_CommandListSwapper(commandListSwapper),
116           m_StartCommand(startCommand),
117           m_CommandSize(0)
118     {}
~EndShadowRenderCommand()119     virtual ~EndShadowRenderCommand() {}
120 
Invoke(nw::gfx::RenderContext * renderContext)121     virtual void Invoke(nw::gfx::RenderContext* renderContext)
122     {
123         // レンダーモードをデフォルトに戻し、マテリアル設定が通常通り行われるようにします。
124         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_DEFAULT);
125 
126         // 描画キャッシュを破棄するために ResetState を行います。
127         renderContext->ResetState();
128 
129         m_CommandSize = m_CommandListSwapper->GetCommandBufferSize();
130         int profilerPoint = m_StartCommand->GetProfilerPoint();
131         m_CommandListSwapper->SetGpuProfilingEndPoint(profilerPoint);
132     }
133 
GetCommandSize() const134     s32 GetCommandSize() const { return this->m_CommandSize; }
135 
136 private:
137     nw::demo::CommandListSwapper* m_CommandListSwapper;
138     StartShadowRenderCommand* m_StartCommand;
139     s32 m_CommandSize;
140 };
141 
142 // 描画開始の設定を行うレンダーコマンドです。
143 class StartRenderCommand : public nw::gfx::RenderCommand
144 {
145     NW_DISALLOW_COPY_AND_ASSIGN(StartRenderCommand);
146 
147 public:
StartRenderCommand(nw::demo::RenderSystem * renderSystem,nw::gfx::IRenderTarget * renderTarget,s32 baseCameraIndex)148     StartRenderCommand(nw::demo::RenderSystem* renderSystem, nw::gfx::IRenderTarget* renderTarget, s32 baseCameraIndex)
149         : m_RenderSystem(renderSystem),
150           m_RenderTarget(renderTarget),
151           m_BaseCameraIndex(baseCameraIndex),
152           m_CommandSize(0)
153     {}
154 
~StartRenderCommand()155     virtual ~StartRenderCommand() {}
156 
Invoke(nw::gfx::RenderContext * renderContext)157     virtual void Invoke(nw::gfx::RenderContext* renderContext)
158     {
159         nw::demo::CommandListSwapper* commandListSwapper = m_RenderSystem->GetCommandListSwapper();
160 
161         // 描画対象をオンスクリーンバッファに切り替えます
162         renderContext->SetRenderTarget(m_RenderTarget);
163         // ライト、環境マップなどの計算用カメラを設定します。
164         renderContext->SetActiveCamera(m_BaseCameraIndex);
165 
166         // ステレオ表示用コマンドの作成を開始します。作成したコマンドは複数回描画するために再利用されます。
167         commandListSwapper->StartCommandSave();
168 
169         m_CommandSize = commandListSwapper->GetCommandBufferSize();
170 
171         m_RenderSystem->ClearBySkyModel(renderContext->GetActiveCamera());
172     }
173 
GetCommandSize() const174     s32 GetCommandSize() const { return this->m_CommandSize; }
175 
176 private:
177     nw::demo::RenderSystem* m_RenderSystem;
178     nw::gfx::IRenderTarget* m_RenderTarget;
179     s32 m_BaseCameraIndex;
180     s32 m_CommandSize;
181 };
182 
183 // 描画終了の設定を行うレンダーコマンドです。
184 class EndRenderCommand : public nw::gfx::RenderCommand
185 {
186     NW_DISALLOW_COPY_AND_ASSIGN(EndRenderCommand);
187 
188 public:
EndRenderCommand(nw::demo::RenderSystem * renderSystem,nw::gfx::Camera * leftCamera,nw::gfx::Camera * rightCamera,StartRenderCommand * startCommand)189     EndRenderCommand(
190         nw::demo::RenderSystem* renderSystem,
191         nw::gfx::Camera* leftCamera,
192         nw::gfx::Camera* rightCamera,
193         StartRenderCommand* startCommand)
194         : m_RenderSystem(renderSystem),
195           m_LeftCamera(leftCamera),
196           m_RightCamera(rightCamera),
197           m_StartCommand(startCommand)
198     {}
~EndRenderCommand()199     virtual ~EndRenderCommand() {}
200 
Invoke(nw::gfx::RenderContext * renderContext)201     virtual void Invoke(nw::gfx::RenderContext* renderContext)
202     {
203         int commandSize = m_RenderSystem->GetCommandListSwapper()->GetCommandBufferSize();
204         m_RenderSystem->AddLoadMeterCommandSize(commandSize - m_StartCommand->GetCommandSize());
205 
206         nw::demo::CommandListSwapper* commandListSwapper = m_RenderSystem->GetCommandListSwapper();
207 
208         // ステレオ表示用コマンドの作成を終了します。
209         commandListSwapper->EndCommandSave();
210 
211         // GPU処理時間計測開始
212         int profilerLeft = commandListSwapper->AddGpuProfilingStartPoint(true);
213 
214         // 保存したコマンドを左目用の描画として再利用します。
215         renderContext->SetCameraMatrix(m_LeftCamera);
216         commandListSwapper->ReuseCommand(false);
217 
218         // GPU処理時間計測終了
219         commandListSwapper->SetGpuProfilingEndPoint(profilerLeft);
220 
221         m_RenderSystem->TransferBuffer(nw::demo::UPPER_SCREEN);
222 
223         // GPU処理時間計測開始
224         int profilerRight = commandListSwapper->AddGpuProfilingStartPoint(true);
225 
226         // 保存したコマンドを右目用の描画として再利用します。
227         renderContext->SetCameraMatrix(m_RightCamera);
228         commandListSwapper->ReuseCommand(false);
229 
230         // GPU処理時間計測終了
231         commandListSwapper->SetGpuProfilingEndPoint(profilerRight);
232 
233         m_RenderSystem->TransferBuffer(nw::demo::EXTENSION_SCREEN);
234     }
235 private:
236     nw::demo::RenderSystem* m_RenderSystem;
237     nw::gfx::Camera* m_LeftCamera;
238     nw::gfx::Camera* m_RightCamera;
239     StartRenderCommand* m_StartCommand;
240 };
241 
242 enum CameraKind
243 {
244     PERSPECTIVE_CAMERA,
245     FRUSTUM_CAMERA,
246     ORTHO_CAMERA
247 };
248 
249 nw::gfx::Camera* s_ShadowCamera = NULL;
250 // シャドウに用いるカメラの種類です。
251 CameraKind s_CameraKind = PERSPECTIVE_CAMERA;
252 // シャドウ用のカメラのパラメータです。
253 const f32 s_OrthoCameraHeight = 32.0f;
254 const f32 s_ShadowNear = 1.0f;
255 const f32 s_ShadowFar = 500.0f;
256 
257 StartShadowRenderCommand* s_StartShadowRenderCommand = NULL;
258 EndShadowRenderCommand* s_EndShadowRenderCommand = NULL;
259 StartRenderCommand* s_StartRenderCommand = NULL;
260 EndRenderCommand* s_EndRenderCommand = NULL;
261 
262 // シャドウのマテリアル、シェーダー設定用モデルです。
263 // このモデルはマテリアルとシェーダーの設定に利用されます。
264 // 実際には描画されません。
265 nw::gfx::Model* s_ShadowDummyModel = NULL;
266 // シャドウ用のテクスチャです。
267 nw::gfx::ResImageTexture s_ShadowTexture;
268 // シャドウテクスチャのサイズです。
269 const s32 s_ShadowTextureSize = 512;
270 // 影の強度(濃さ)です。
271 const f32 s_ShadowIntensity = 0.2f;
272 
273 //----------------------------------------
274 // メモリ関係
275 
276 // デバイスメモリを確保するためのアロケータです。
277 nw::demo::DemoAllocator s_DeviceAllocator;
278 
279 //----------------------------------------
280 // ファイル名の定義です。
281 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
282 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
283 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
284 
285 const wchar_t* MODEL_RESOURCE_FILES[] =
286 {
287     NW_DEMO_FILE_PATH(L"MaleShadow.bcmdl"),
288     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
289     NW_DEMO_FILE_PATH(L"SpotLight.bcenv"),
290     NW_DEMO_FILE_PATH(L"AmbientLight.bcenv"),
291 };
292 
293 const wchar_t* SKELETAL_ANIM_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"WalkAimAt.bcskla");
294 
295 const wchar_t* SHADOW_MATERIAL_FILE_NAME = NW_DEMO_FILE_PATH(L"ShadowModel.bcmdl");
296 
297 //----------------------------------------
298 // プロファイル関係
299 const int NW_LOAD_METER_INTERVAL = 60;
300 
301 //----------------------------------------
302 // 描画関係
303 const int RENDER_TARGET_COUNT = 2;
304 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
305 
306 RenderTargetArray s_RenderTargets;
307 nw::demo::SceneSystem*  s_SceneSystem = NULL;
308 nw::demo::RenderSystem* s_RenderSystem = NULL;
309 
310 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
311 
312 //----------------------------------------
313 // リソース関係
314 nw::demo::ResourceArray s_Resources;
315 
316 //----------------------------------------
317 // シーン関係
318 nw::gfx::SceneNode* s_SceneRoot = NULL;
319 nw::gfx::SceneNode* s_ModelRoot = NULL;
320 nw::gfx::TransformNode* s_LightRoot = NULL;
321 s32 s_FrameCount = 0;
322 nw::gfx::Camera* s_BaseCamera = NULL;
323 nw::gfx::Camera* s_LeftCamera = NULL;
324 nw::gfx::Camera* s_RightCamera = NULL;
325 nw::gfx::FragmentLight* s_SpotLight = NULL;
326 
327 const f32 s_fNearPlane = 0.1f;
328 const f32 s_fFarPlane = 1000.0f;
329 
330 //----------------------------------------
331 // シーン環境関係
332 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
333 
334 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
335 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
336 
337 const s32 s_BaseCameraIndex = 0;
338 const s32 s_ShadowCameraIndex = 1;
339 
340 //----------------------------------------
341 // アニメーション関係
342 nw::gfx::SkeletalModel* s_AnimModel = NULL;
343 const int MAX_ANIM_OBJECTS = 8;
344 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
345 
346 /*!--------------------------------------------------------------------------*
347   @brief        グラフィックス関連の初期化を行います。
348  *---------------------------------------------------------------------------*/
349 void
InitializeGraphics()350 InitializeGraphics()
351 {
352     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
353 
354     // renderDescriptionへステレオの設定を行います。
355     nw::demo::RenderSystem::Description renderDescription;
356 
357     renderDescription.reusableCommandBufferSize = 0x100000;
358     renderDescription.reusableCommandRequestCount      = 512;
359     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
360 
361     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
362 
363     s_GraphicsDrawing.SetScreenSize(
364         renderDescription.lowerScreenDescription.width,
365         renderDescription.lowerScreenDescription.height
366     );
367 
368     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
369 
370     NN_ASSERTMSG(result, "Fail to load Font.");
371 
372     s_RenderTargets.push_back(
373         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
374     );
375 
376     s_ShadowTexture =
377         nw::gfx::ResImageTexture::DynamicBuilder()
378         .Width(s_ShadowTextureSize)
379         .Height(s_ShadowTextureSize)
380         .MipmapSize(1)
381         .LocationFlag(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP)
382         .Format(nw::gfx::ResPixelBasedTexture::FORMAT_HW_RGBA8)
383         .ExecutingMemoryFill(true)
384         .Create(&s_DeviceAllocator);
385     s_ShadowTexture.Setup(&s_DeviceAllocator, nw::gfx::ResGraphicsFile(NULL));
386 
387     // オフスクリーンバッファを作成します。
388     nw::gfx::IRenderTarget* offScreenTarget =
389         nw::gfx::IRenderTarget::CreateOffScreenBuffer(&s_DeviceAllocator, s_ShadowTexture);
390 
391     s_RenderTargets.push_back(offScreenTarget);
392 
393     NW_ASSERT(!s_RenderTargets.empty());
394     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets[0]);
395 
396     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
397     nw::demo::SceneSystem::Description sceneDescription;
398     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
399 
400     // デモ用の最遠景モデルをレンダリングシステムに設定します。
401     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
402     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
403 
404     NW_GL_ASSERT();
405 }
406 
407 /*!--------------------------------------------------------------------------*
408   @brief        グラフィックス関連の後始末をします。
409  *---------------------------------------------------------------------------*/
410 void
TerminateGraphics()411 TerminateGraphics()
412 {
413     s_ShadowTexture.Cleanup();
414     if (s_ShadowTexture.IsValid())
415     {
416         s_ShadowTexture.DynamicDestroy();
417     }
418 
419     nw::gfx::SafeDestroy(s_LeftCamera);
420 
421     nw::gfx::SafeDestroy(s_RightCamera);
422 
423     nw::gfx::SafeDestroy(s_SceneSystem);
424 
425     nw::gfx::SafeDestroyAll(s_RenderTargets);
426 
427     s_GraphicsDrawing.Finalize();
428 
429     nw::gfx::SafeDestroy(s_RenderSystem);
430 
431     NW_GL_ASSERT();
432 }
433 
434 /*!--------------------------------------------------------------------------*
435   @brief ファイルからトランスフォームアニメーション評価を生成します。
436 
437   @param[in] maxBones 最大メンバ数です。
438   @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
439   @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
440 
441   @return トランスフォームアニメーション評価です。
442  *---------------------------------------------------------------------------*/
443 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,const wchar_t * filePath)444 CreateTransformAnimEvaluator(
445     const int maxMembers,
446     const bool translateAnimEnabled,
447     const wchar_t* filePath
448 )
449 {
450     //----------------------------------------
451     // アニメーションリソースを生成します。
452     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
453     if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
454     {
455         return NULL;
456     }
457     nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0);
458 
459     if (!resAnim.IsValid())
460     {
461         return NULL;
462     }
463 
464     //----------------------------------------
465     // トランスフォームアニメーション評価を生成します。
466     //
467     // アニメーションを1つのモデルにのみ適用する場合や、
468     // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
469     nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
470         .AnimData(resAnim)
471         .MaxMembers(maxMembers)
472         .AllocCache(false)
473         .Create(&s_DeviceAllocator);
474 
475     // 移動アニメーションの無効化フラグを設定します。
476     evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
477 
478     return evaluator;
479 }
480 
481 /*!--------------------------------------------------------------------------*
482   @brief        スケルタルアニメーションを初期化します。
483 
484   @param[in]    model スケルタルモデルです。
485  *---------------------------------------------------------------------------*/
486 void
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)487 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
488 {
489     nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
490     if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。
491     {
492         return;
493     }
494 
495     nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
496     nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
497     const int maxBones = resSkeleton.GetBonesCount();
498     const bool translateAnimEnabled =
499         nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
500 
501     //----------------------------------------
502     // アニメーション評価を生成します。
503     nw::gfx::TransformAnimEvaluator* evaluator = CreateTransformAnimEvaluator(
504         maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILE);
505     if (evaluator == NULL)
506     {
507         return;
508     }
509 
510     // アニメーションをバインドします。
511     bool bindResult = evaluator->Bind(animGroup);
512 
513     //----------------------------------------
514     // アニメーションをモデルに登録します。
515     model->SetSkeletalAnimObject(evaluator);
516     s_AnimObjects.PushBack(evaluator);
517 }
518 
519 /*!--------------------------------------------------------------------------*
520   @brief        アニメーションの後始末をします。
521  *---------------------------------------------------------------------------*/
522 void
TerminateAnim(void)523 TerminateAnim(void)
524 {
525     for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
526     {
527         nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
528     }
529     s_AnimObjects.clear();
530 }
531 
532 /*!--------------------------------------------------------------------------*
533   @brief        ルートノード関連の構築をします。
534  *---------------------------------------------------------------------------*/
535 void
BuildRootNodes()536 BuildRootNodes()
537 {
538     NW_ASSERT(s_SceneRoot == NULL);
539     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
540         .IsFixedSizeMemory(false)
541         .Create(&s_DeviceAllocator);
542     NW_NULL_ASSERT(s_SceneRoot);
543 
544     NW_ASSERT(s_ModelRoot == NULL);
545     s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
546         .IsFixedSizeMemory(false)
547         .Create(&s_DeviceAllocator);
548     s_SceneRoot->AttachChild(s_ModelRoot);
549     NW_NULL_ASSERT(s_ModelRoot);
550 
551     NW_ASSERT(s_LightRoot == NULL);
552     s_LightRoot = nw::gfx::TransformNode::DynamicBuilder()
553         .IsFixedSizeMemory(false)
554         .Create(&s_DeviceAllocator);
555     s_SceneRoot->AttachChild(s_LightRoot);
556     NW_NULL_ASSERT(s_LightRoot);
557 }
558 
559 /*!--------------------------------------------------------------------------*
560   @brief        カメラ関連の構築をします。
561  *---------------------------------------------------------------------------*/
562 void
BuildCameras()563 BuildCameras()
564 {
565     nw::demo::Utility::CreateStereoCameras(
566         &s_BaseCamera,
567         &s_LeftCamera,
568         &s_RightCamera,
569         &s_DeviceAllocator,
570         nw::math::VEC3(20.0f, 15.0f, 20.0f),
571         nw::math::VEC3(0.0f, 10.0f, 0.0f),
572         s_fNearPlane,
573         s_fFarPlane
574     );
575     s_SceneRoot->AttachChild(s_BaseCamera);
576     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
577 
578     // シャドウ用のカメラを作成します。
579     switch (s_CameraKind)
580     {
581         case PERSPECTIVE_CAMERA:
582             {
583                 s_ShadowCamera =
584                     nw::demo::Utility::CreateCamera(
585                         &s_DeviceAllocator,
586                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
587                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
588                         s_ShadowNear,
589                         s_ShadowFar,
590                         NW_MATH_DEG_TO_RAD(45.0f),
591                         nw::math::PIVOT_NONE);
592             }
593             break;
594         case FRUSTUM_CAMERA:
595             {
596                 s_ShadowCamera =
597                     nw::demo::Utility::CreateFrustumCamera(
598                         &s_DeviceAllocator,
599                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
600                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
601                         s_ShadowNear,
602                         s_ShadowFar,
603                         nw::math::VEC2(0.0f, 0.0f),
604                         1.0f,
605                         nw::math::PIVOT_NONE);
606             }
607             break;
608         case ORTHO_CAMERA:
609             {
610                 s_ShadowCamera =
611                     nw::demo::Utility::CreateOrthoCamera(
612                         &s_DeviceAllocator,
613                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
614                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
615                         s_ShadowNear,
616                         s_ShadowFar,
617                         nw::math::VEC2(0.0f, 0.0f),
618                         s_OrthoCameraHeight,
619                         nw::math::PIVOT_NONE);
620             }
621             break;
622         default:
623             {
624                 NW_FATAL_ERROR("Unsupported camera type.");
625             }
626             break;
627     }
628 
629     NW_NULL_ASSERT(s_ShadowCamera);
630 
631     s_SceneRoot->AttachChild(s_ShadowCamera);
632 }
633 
634 /*!--------------------------------------------------------------------------*
635   @brief        シャドウ用のテクスチャコンバイナ関連の構築をします。
636  *---------------------------------------------------------------------------*/
637 void
SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)638 SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)
639 {
640     nw::gfx::ResTextureCoordinator resTexCoord = resMaterial.GetTextureCoordinators(0);
641     resTexCoord.SetReferenceCamera(1);
642     nw::gfx::ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(0);
643     // ダミーのテクスチャをシャドウ用のテクスチャに差し替えます。
644     nw::gfx::ResTexture dummyTexture = resTextureMapper.GetTexture().Dereference();
645     dummyTexture.Cleanup();
646     resTextureMapper.SetTexture(s_ShadowTexture);
647 }
648 
649 /*!--------------------------------------------------------------------------*
650   @brief        リソース関連の構築をします。
651  *---------------------------------------------------------------------------*/
652 void
BuildResources(nw::demo::ResourceSet * resourceSet)653 BuildResources(nw::demo::ResourceSet* resourceSet)
654 {
655     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
656     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
657     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
658 
659     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
660     if (result.IsFailure())
661     {
662         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
663     }
664 
665     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
666 
667     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
668     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
669     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
670          modelResource != modelsEnd; ++modelResource)
671     {
672         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
673             &s_DeviceAllocator,
674             (*modelResource)
675         );
676 
677         // plane の Texture0 にオフスクリーンバッファをテクスチャとしてセットする
678         if (::std::strcmp((*modelResource).GetName(), "Plane") == 0)
679         {
680             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(node);
681             NW_ASSERT(model->GetMaterialCount() != 0);
682 
683             nw::gfx::Material* material = model->GetMaterial(0);
684             nw::gfx::ResMaterial resMaterial = material->GetOriginal();
685             NW_ASSERT(resMaterial.IsValid());
686             SetupShadowMaterial(resMaterial);
687         }
688         else if (::std::strcmp((*modelResource).GetName(), "Male") == 0)
689         {
690             nw::gfx::SkeletalModel* skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
691             s_AnimModel = skeletalModel;
692 
693             // 影を生成するモデルにフラグを設定します。
694             skeletalModel->SetUserParameter(SHADOW_CASTER);
695         }
696 
697         sceneNodeArray.push_back(node);
698     }
699 
700     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
701     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
702     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
703          lightResource != lightsEnd; ++lightResource)
704     {
705         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
706             &s_DeviceAllocator,
707             (*lightResource)
708         );
709 
710         if (::std::strcmp((*lightResource).GetName(), "SpotLight") == 0)
711         {
712             s_SpotLight = nw::ut::DynamicCast<nw::gfx::FragmentLight*>(node);
713             s_LightRoot->AttachChild(s_SpotLight);
714         }
715 
716         sceneNodeArray.push_back(node);
717     }
718 
719     // 親子付け参照関係を解決
720     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
721 
722     // モデルをシーンに追加
723     nw::gfx::SceneHelper::ForeachRootNodes(
724         sceneNodeArray.Begin(),
725         sceneNodeArray.End(),
726         nw::gfx::AttachNode(s_ModelRoot)
727     );
728 
729     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
730     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
731     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
732         settingResource != settingsEnd; ++settingResource)
733     {
734         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
735             .Resource(*settingResource)
736             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
737 
738         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
739             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
740 
741         NW_NULL_ASSERT(sceneEnvironmentSetting);
742         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
743     }
744 }
745 
746 /*!--------------------------------------------------------------------------*
747   @brief        シーンを初期化します。
748  *---------------------------------------------------------------------------*/
749 void
InitializeScenes()750 InitializeScenes()
751 {
752     BuildRootNodes();
753 
754     BuildCameras();
755 
756     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
757     {
758         BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
759     }
760 
761     if (s_AnimModel != NULL)
762     {
763         InitializeSkeletalAnim(s_AnimModel);
764     }
765 
766     // シーンツリーを巡回して初期化を行います。
767     s_SceneSystem->InitializeScene(s_SceneRoot);
768     s_SceneSystem->UpdateScene();
769 
770     // シーン環境の参照解決を行い設定します。
771     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
772 
773     // カメラを設定します。
774     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
775     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
776     sceneEnvironment.SetCamera(s_ShadowCameraIndex, s_ShadowCamera);
777     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
778 
779     // シャドウ用のマテリアルとシェーダーを含むモデルを読み込みます。
780     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, SHADOW_MATERIAL_FILE_NAME, &s_DeviceAllocator);
781     nw::gfx::ResModel resShadowModel = resourceSet->resource.GetModels("ShadowModel");
782     nw::gfx::Result result = resShadowModel.Setup(&s_DeviceAllocator, resourceSet->resource);
783     NW_ASSERT(result.IsSuccess());
784     nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
785         &s_DeviceAllocator,
786         resShadowModel
787     );
788     s_ShadowDummyModel = nw::ut::DynamicCast<nw::gfx::Model*>(node);
789     NW_NULL_ASSERT(s_ShadowDummyModel);
790 
791     NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
792 
793     // 影の強度(濃さ)を設定します。
794     nw::gfx::ResMaterialColor materialColor = s_ShadowDummyModel->GetMaterial(0)->GetOriginal().GetMaterialColor();
795     materialColor.SetDiffuse(s_ShadowIntensity, s_ShadowIntensity, s_ShadowIntensity);
796 
797     nw::demo::CommandListSwapper* commandListSwapper = s_RenderSystem->GetCommandListSwapper();
798     NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
799     nw::gfx::Material* shadowMaterial = s_ShadowDummyModel->GetMaterial(0);
800 
801     // レンダーコマンドを作成します。
802     void* startShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartShadowRenderCommand));
803     NW_NULL_ASSERT(startShadowCommandMemory);
804     s_StartShadowRenderCommand = new(startShadowCommandMemory) StartShadowRenderCommand(
805         commandListSwapper,
806         s_RenderTargets[1],
807         s_ShadowCameraIndex,
808         shadowMaterial);
809 
810     void* endShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndShadowRenderCommand));
811     NW_NULL_ASSERT(endShadowCommandMemory);
812     s_EndShadowRenderCommand = new(endShadowCommandMemory) EndShadowRenderCommand(commandListSwapper, s_StartShadowRenderCommand);
813 
814     void* startCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartRenderCommand));
815     NW_NULL_ASSERT(startCommandMemory);
816     s_StartRenderCommand = new(startCommandMemory) StartRenderCommand(s_RenderSystem, s_RenderTargets[0], s_BaseCameraIndex);
817 
818     void* endCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndRenderCommand));
819     NW_NULL_ASSERT(endCommandMemory);
820     s_EndRenderCommand = new(endCommandMemory) EndRenderCommand(s_RenderSystem, s_LeftCamera, s_RightCamera, s_StartRenderCommand);
821 
822     NW_GL_ASSERT();
823 
824     s_FrameCount = 0;
825 }
826 
827 /*!--------------------------------------------------------------------------*
828   @brief        シーン関連の後始末をします。
829  *---------------------------------------------------------------------------*/
830 void
TerminateScenes()831 TerminateScenes()
832 {
833     s_DeviceAllocator.Free(s_EndRenderCommand);
834     s_DeviceAllocator.Free(s_StartRenderCommand);
835     s_DeviceAllocator.Free(s_EndShadowRenderCommand);
836     s_DeviceAllocator.Free(s_StartShadowRenderCommand);
837 
838     nw::ut::SafeDestroy(s_ShadowDummyModel);
839     nw::gfx::SafeDestroyBranch(s_SceneRoot);
840     nw::demo::SafeCleanupResources(s_Resources);
841     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
842     TerminateAnim();
843 
844     NW_GL_ASSERT();
845 
846     s_Resources.clear();
847     s_SceneEnvironmentSettings.clear();
848     s_ModelRoot = NULL;
849     s_LightRoot = NULL;
850 }
851 
852 /*!--------------------------------------------------------------------------*
853   @brief        シーンを更新します。
854  *---------------------------------------------------------------------------*/
855 void
UpdateScene()856 UpdateScene()
857 {
858     float radian = static_cast<float>((s_FrameCount) % (314 * 2)) * 0.01f;
859 
860     // ライトルートがY軸中心に回転します。
861     nw::gfx::TransformNode* lightNode =
862         nw::ut::DynamicCast<nw::gfx::TransformNode*>(s_LightRoot);
863     NW_NULL_ASSERT(lightNode);
864 
865     lightNode->Transform().SetRotateXYZ(0.0f, radian, 0.0f);
866 
867     s_SceneSystem->GetCameraController()->Update();
868 
869     s_SceneSystem->UpdateScene();
870 
871     s_BaseCamera->UpdateCameraMatrix();
872 
873     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
874 
875     // シャドウの描画をライト方向から行うために、カメラの位置と方向をライトに追従させます。
876     nw::math::VEC3 translate;
877     translate.x = s_SpotLight->WorldMatrix().m[0][3];
878     translate.y = s_SpotLight->WorldMatrix().m[1][3];
879     translate.z = s_SpotLight->WorldMatrix().m[2][3];
880 
881     s_ShadowCamera->WorldMatrix().m[0][3] = translate.x;
882     s_ShadowCamera->WorldMatrix().m[1][3] = translate.y;
883     s_ShadowCamera->WorldMatrix().m[2][3] = translate.z;
884 
885     const nw::math::VEC3& direction = s_SpotLight->Direction();
886     s_ShadowCamera->SetTargetPosition(translate + direction);
887 
888     s_ShadowCamera->UpdateCameraMatrix();
889 
890     ++s_FrameCount;
891 }
892 
893 /*!--------------------------------------------------------------------------*
894   @brief        レンダーキューにレンダーエレメントを追加します。
895  *---------------------------------------------------------------------------*/
896 void
SubmitView()897 SubmitView()
898 {
899     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
900     nw::gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
901     nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
902 
903     nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
904 
905     renderQueue->Reset();
906 
907     // 描画対象とレンダーコマンドをレンダーキューに追加します。
908     // 分かりやすくするために処理される順に Submit or Enqueue を行います。
909 
910     // シャドウ用の設定を行うコマンドをレイヤー0の後に実行するコールバックに追加します。
911     s_RenderSystem->EnqueueRenderCommand(
912         s_StartShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 0);
913 
914     // シャドウキャスターとして指定されたモデルのみを レイヤー1としてレンダーキューに追加します。
915     s_SceneSystem->GetSceneUpdater()->SubmitView(
916         renderQueue,
917         sceneContext,
918         *s_ShadowCamera,
919         1,
920         1,
921         &s_ShadowCasterModel,
922         s_RenderSystem->GetRenderSortMode());
923 
924     // シャドウの後処理を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
925     s_RenderSystem->EnqueueRenderCommand(
926         s_EndShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 1);
927 
928     // ステレオ描画の前処理の設定を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
929     s_RenderSystem->EnqueueRenderCommand(
930         s_StartRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 1, 1);
931 
932     // シーンコンテキストの全てのモデルをレイヤー2でレンダーキューに追加します。
933     s_SceneSystem->GetSceneUpdater()->SubmitView(
934         renderQueue,
935         sceneContext,
936         *s_BaseCamera,
937         2,
938         s_RenderSystem->GetRenderSortMode());
939 
940     // ステレオ描画の後処理の設定を行うコマンドをレイヤー2の後に実行するコールバックに追加します。
941     s_RenderSystem->EnqueueRenderCommand(
942         s_EndRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 2);
943 
944     std::sort(
945         renderQueue->Begin(),
946         renderQueue->End(),
947         nw::gfx::RenderElementCompare());
948 }
949 
950 //----------------------------------------
951 struct RenderSceneInternalFunctor
952 : public std::unary_function<nw::gfx::RenderElement&, void>
953 {
954     nw::gfx::RenderContext* m_RenderContext;
955     nw::gfx::MeshRenderer* m_MeshRenderer;
956 
RenderSceneInternalFunctor__anoneac4b5990111::RenderSceneInternalFunctor957     RenderSceneInternalFunctor(nw::gfx::RenderContext* renderContext, nw::gfx::MeshRenderer* meshRenderer)
958     : m_RenderContext(renderContext), m_MeshRenderer(meshRenderer)
959     {
960         NW_NULL_ASSERT(renderContext);
961         NW_NULL_ASSERT(meshRenderer);
962     }
963 
operator ()__anoneac4b5990111::RenderSceneInternalFunctor964     void operator()(nw::gfx::RenderElement& element)
965     {
966         if (element.IsCommand())
967         {
968             nw::gfx::RenderCommand* command = element.GetCommand();
969             NW_NULL_ASSERT(command);
970             command->Invoke(this->m_RenderContext);
971         }
972         else
973         {
974             nw::gfx::ResMesh mesh = element.GetMesh();
975             nw::gfx::Model* model = element.GetModel();
976             model->PreRenderSignal()(model, mesh, this->m_RenderContext);
977             this->m_MeshRenderer->RenderMesh(mesh, model);
978             model->PostRenderSignal()(model, mesh, this->m_RenderContext);
979         }
980         NW_GL_ASSERT();
981     }
982 };
983 
984 /*!--------------------------------------------------------------------------*
985   @brief        レンダーキューに基づいて描画を行います。
986  *---------------------------------------------------------------------------*/
987 void
RenderScene()988 RenderScene()
989 {
990     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
991     nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
992     nw::gfx::MeshRenderer* meshRenderer = s_RenderSystem->GetMeshRenderer();
993 
994     std::for_each(
995         renderQueue->Begin(),
996         renderQueue->End(),
997         RenderSceneInternalFunctor(renderContext, meshRenderer));
998 
999     NW_GL_ASSERT();
1000 }
1001 
1002 /*!--------------------------------------------------------------------------*
1003   @brief        負荷表示やテスト機能の処理をおこないます。
1004  *---------------------------------------------------------------------------*/
1005 void
ReportDemo()1006 ReportDemo()
1007 {
1008     NW_PROFILE("ReportDemo");
1009 
1010     // 負荷表示からはこれらの負荷は除きます。
1011     s_RenderSystem->SuspendLoadMeter();
1012 
1013     s_RenderSystem->AddLoadMeterCommandSize(
1014         s_EndShadowRenderCommand->GetCommandSize() - s_StartShadowRenderCommand->GetCommandSize());
1015 
1016     s_GraphicsDrawing.BeginDrawingString();
1017 
1018     nw::demo::DebugUtility::DrawLoadMeter(
1019         s_RenderSystem,
1020         &s_GraphicsDrawing,
1021         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
1022     );
1023 
1024     s_GraphicsDrawing.FlushDrawing();
1025 
1026     s_RenderSystem->ResumeLoadMeter();
1027 }
1028 
1029 /*!--------------------------------------------------------------------------*
1030   @brief        シーンをデモンストレーションします。
1031  *---------------------------------------------------------------------------*/
1032 void
DemoScene()1033 DemoScene()
1034 {
1035     NW_ASSERT(!s_RenderTargets.empty());
1036 
1037     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
1038 
1039     InitializeScenes();
1040 
1041     bool isContinuing = true;
1042 
1043     while ( isContinuing )
1044     {
1045         nw::demo::DebugUtility::AdvanceAutoTestFrame();
1046 
1047         nw::demo::PadFactory::GetPad()->Update();
1048 
1049         UpdateScene();
1050 
1051         SubmitView();
1052 
1053         RenderScene();
1054 
1055         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
1056         ReportDemo();
1057         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
1058 
1059         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
1060 
1061         renderContext->ResetState();
1062 
1063         if (nw::demo::Utility::IsTerminating())
1064         {
1065             isContinuing = false;
1066         }
1067     }
1068 
1069     TerminateScenes();
1070 }
1071 
1072 } // namespace
1073 
1074 /*!--------------------------------------------------------------------------*
1075   @brief        メイン関数です。
1076  *---------------------------------------------------------------------------*/
1077 void
nnMain()1078 nnMain()
1079 {
1080     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
1081 
1082     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
1083 
1084     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
1085     {
1086 
1087         InitializeGraphics();
1088 
1089         DemoScene();
1090 
1091         TerminateGraphics();
1092 
1093     }
1094 
1095     nw::demo::PadFactory::Finalize();
1096 
1097     nw::demo::FinalizeGraphicsSystem();
1098 }
1099