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