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: 28483 $
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* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
282
283 const wchar_t* MODEL_RESOURCE_FILES[] =
284 {
285 NW_DEMO_FILE_PATH(L"MaleShadow.bcmdl"),
286 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
287 NW_DEMO_FILE_PATH(L"SpotLight.bcenv"),
288 NW_DEMO_FILE_PATH(L"AmbientLight.bcenv"),
289 };
290
291 const wchar_t* SKELETAL_ANIM_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"WalkAimAt.bcskla");
292
293 const wchar_t* SHADOW_MATERIAL_FILE_NAME = NW_DEMO_FILE_PATH(L"ShadowModel.bcmdl");
294
295 //----------------------------------------
296 // 描画関係
297 const int RENDER_TARGET_COUNT = 2;
298 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
299
300 RenderTargetArray s_RenderTargets;
301 nw::demo::SceneSystem* s_SceneSystem = NULL;
302 nw::demo::RenderSystem* s_RenderSystem = NULL;
303
304 nw::demo::GraphicsDrawing s_GraphicsDrawing;
305
306 //----------------------------------------
307 // リソース関係
308 nw::demo::ResourceArray s_Resources;
309
310 //----------------------------------------
311 // シーン関係
312 nw::gfx::SceneNode* s_SceneRoot = NULL;
313 nw::gfx::SceneNode* s_ModelRoot = NULL;
314 nw::gfx::TransformNode* s_LightRoot = NULL;
315 s32 s_FrameCount = 0;
316 nw::gfx::Camera* s_BaseCamera = NULL;
317 nw::gfx::Camera* s_LeftCamera = NULL;
318 nw::gfx::Camera* s_RightCamera = NULL;
319 nw::gfx::FragmentLight* s_SpotLight = NULL;
320
321 const f32 s_fNearPlane = 0.1f;
322 const f32 s_fFarPlane = 1000.0f;
323
324 //----------------------------------------
325 // シーン環境関係
326 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
327
328 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
329 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
330
331 const s32 s_BaseCameraIndex = 0;
332 const s32 s_ShadowCameraIndex = 1;
333
334 //----------------------------------------
335 // アニメーション関係
336 nw::gfx::SkeletalModel* s_AnimModel = NULL;
337 const int MAX_ANIM_OBJECTS = 8;
338 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
339
340 /*!--------------------------------------------------------------------------*
341 @brief グラフィックス関連の初期化を行います。
342 *---------------------------------------------------------------------------*/
343 void
InitializeGraphics()344 InitializeGraphics()
345 {
346 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
347
348 // renderDescriptionへステレオの設定を行います。
349 nw::demo::RenderSystem::Description renderDescription;
350
351 renderDescription.reusableCommandBufferSize = 0x100000;
352 renderDescription.reusableCommandRequestCount = 512;
353 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
354
355 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
356
357 s_GraphicsDrawing.SetScreenSize(
358 renderDescription.lowerScreenDescription.width,
359 renderDescription.lowerScreenDescription.height
360 );
361
362 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
363
364 s_RenderTargets.push_back(
365 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
366 );
367
368 // シャドウ描画用のテクスチャを確保します。
369 // VRAM に配置して OffScreenBuffer として利用するので、
370 // LocationFlag(NN_GX_MEM_VRAMA), DynamicAllocation(false) とする。
371 s_ShadowTexture =
372 nw::gfx::ResImageTexture::DynamicBuilder()
373 .Width(s_ShadowTextureSize)
374 .Height(s_ShadowTextureSize)
375 .MipmapSize(1)
376 .LocationFlag(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP)
377 .Format(nw::gfx::ResPixelBasedTexture::FORMAT_HW_RGBA8)
378 .ExecutingMemoryFill(true)
379 .DynamicAllocation(false)
380 .Create(&s_DeviceAllocator);
381 s_ShadowTexture.Setup(&s_DeviceAllocator, nw::gfx::ResGraphicsFile(NULL));
382
383 // オフスクリーンバッファを作成します。
384 nw::gfx::IRenderTarget* offScreenTarget =
385 nw::gfx::IRenderTarget::CreateOffScreenBuffer(&s_DeviceAllocator, s_ShadowTexture);
386
387 s_RenderTargets.push_back(offScreenTarget);
388
389 NW_ASSERT(!s_RenderTargets.empty());
390 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets[0]);
391
392 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
393 nw::demo::SceneSystem::Description sceneDescription;
394 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
395
396 // デモ用の最遠景モデルをレンダリングシステムに設定します。
397 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
398 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
399
400 NW_GL_ASSERT();
401 }
402
403 /*!--------------------------------------------------------------------------*
404 @brief グラフィックス関連の後始末をします。
405 *---------------------------------------------------------------------------*/
406 void
TerminateGraphics()407 TerminateGraphics()
408 {
409 s_ShadowTexture.Cleanup();
410 if (s_ShadowTexture.IsValid())
411 {
412 s_ShadowTexture.DynamicDestroy();
413 }
414
415 nw::gfx::SafeDestroy(s_LeftCamera);
416
417 nw::gfx::SafeDestroy(s_RightCamera);
418
419 nw::gfx::SafeDestroy(s_SceneSystem);
420
421 nw::gfx::SafeDestroyAll(s_RenderTargets);
422
423 s_GraphicsDrawing.Finalize();
424
425 nw::gfx::SafeDestroy(s_RenderSystem);
426
427 NW_GL_ASSERT();
428 }
429
430 /*!--------------------------------------------------------------------------*
431 @brief ファイルからトランスフォームアニメーション評価を生成します。
432
433 @param[in] maxBones 最大メンバ数です。
434 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
435 @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
436
437 @return トランスフォームアニメーション評価です。
438 *---------------------------------------------------------------------------*/
439 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,const wchar_t * filePath)440 CreateTransformAnimEvaluator(
441 const int maxMembers,
442 const bool translateAnimEnabled,
443 const wchar_t* filePath
444 )
445 {
446 //----------------------------------------
447 // アニメーションリソースを生成します。
448 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
449 if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
450 {
451 return NULL;
452 }
453 nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0);
454
455 if (!resAnim.IsValid())
456 {
457 return NULL;
458 }
459
460 //----------------------------------------
461 // トランスフォームアニメーション評価を生成します。
462 //
463 // アニメーションを1つのモデルにのみ適用する場合や、
464 // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
465 nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
466 .AnimData(resAnim)
467 .MaxMembers(maxMembers)
468 .AllocCache(false)
469 .Create(&s_DeviceAllocator);
470
471 // 移動アニメーションの無効化フラグを設定します。
472 evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
473
474 return evaluator;
475 }
476
477 /*!--------------------------------------------------------------------------*
478 @brief スケルタルアニメーションを初期化します。
479
480 @param[in] model スケルタルモデルです。
481 *---------------------------------------------------------------------------*/
482 void
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)483 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
484 {
485 nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
486 if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。
487 {
488 return;
489 }
490
491 nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
492 nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
493 const int maxBones = resSkeleton.GetBonesCount();
494 const bool translateAnimEnabled =
495 nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
496
497 //----------------------------------------
498 // アニメーション評価を生成します。
499 nw::gfx::TransformAnimEvaluator* evaluator = CreateTransformAnimEvaluator(
500 maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILE);
501 if (evaluator == NULL)
502 {
503 return;
504 }
505
506 // アニメーションをバインドします。
507 bool bindResult = evaluator->Bind(animGroup);
508
509 //----------------------------------------
510 // アニメーションをモデルに登録します。
511 model->SetSkeletalAnimObject(evaluator);
512 s_AnimObjects.PushBack(evaluator);
513 }
514
515 /*!--------------------------------------------------------------------------*
516 @brief アニメーションの後始末をします。
517 *---------------------------------------------------------------------------*/
518 void
TerminateAnim(void)519 TerminateAnim(void)
520 {
521 for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
522 {
523 nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
524 }
525 s_AnimObjects.clear();
526 }
527
528 /*!--------------------------------------------------------------------------*
529 @brief ルートノード関連の構築をします。
530 *---------------------------------------------------------------------------*/
531 void
BuildRootNodes()532 BuildRootNodes()
533 {
534 NW_ASSERT(s_SceneRoot == NULL);
535 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
536 .IsFixedSizeMemory(false)
537 .Create(&s_DeviceAllocator);
538 NW_NULL_ASSERT(s_SceneRoot);
539
540 NW_ASSERT(s_ModelRoot == NULL);
541 s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
542 .IsFixedSizeMemory(false)
543 .Create(&s_DeviceAllocator);
544 s_SceneRoot->AttachChild(s_ModelRoot);
545 NW_NULL_ASSERT(s_ModelRoot);
546
547 NW_ASSERT(s_LightRoot == NULL);
548 s_LightRoot = nw::gfx::TransformNode::DynamicBuilder()
549 .IsFixedSizeMemory(false)
550 .Create(&s_DeviceAllocator);
551 s_SceneRoot->AttachChild(s_LightRoot);
552 NW_NULL_ASSERT(s_LightRoot);
553 }
554
555 /*!--------------------------------------------------------------------------*
556 @brief カメラ関連の構築をします。
557 *---------------------------------------------------------------------------*/
558 void
BuildCameras()559 BuildCameras()
560 {
561 nw::demo::Utility::CreateStereoCameras(
562 &s_BaseCamera,
563 &s_LeftCamera,
564 &s_RightCamera,
565 &s_DeviceAllocator,
566 nw::math::VEC3(20.0f, 15.0f, 20.0f),
567 nw::math::VEC3(0.0f, 10.0f, 0.0f),
568 s_fNearPlane,
569 s_fFarPlane
570 );
571 s_SceneRoot->AttachChild(s_BaseCamera);
572 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
573
574 // シャドウ用のカメラを作成します。
575 switch (s_CameraKind)
576 {
577 case PERSPECTIVE_CAMERA:
578 {
579 s_ShadowCamera =
580 nw::demo::Utility::CreateCamera(
581 &s_DeviceAllocator,
582 nw::math::VEC3(20.0f, 15.0f, 20.0f),
583 nw::math::VEC3(0.0f, 10.0f, 0.0f),
584 s_ShadowNear,
585 s_ShadowFar,
586 NW_MATH_DEG_TO_RAD(45.0f),
587 nw::math::PIVOT_NONE);
588 }
589 break;
590 case FRUSTUM_CAMERA:
591 {
592 s_ShadowCamera =
593 nw::demo::Utility::CreateFrustumCamera(
594 &s_DeviceAllocator,
595 nw::math::VEC3(20.0f, 15.0f, 20.0f),
596 nw::math::VEC3(0.0f, 10.0f, 0.0f),
597 s_ShadowNear,
598 s_ShadowFar,
599 nw::math::VEC2(0.0f, 0.0f),
600 1.0f,
601 nw::math::PIVOT_NONE);
602 }
603 break;
604 case ORTHO_CAMERA:
605 {
606 s_ShadowCamera =
607 nw::demo::Utility::CreateOrthoCamera(
608 &s_DeviceAllocator,
609 nw::math::VEC3(20.0f, 15.0f, 20.0f),
610 nw::math::VEC3(0.0f, 10.0f, 0.0f),
611 s_ShadowNear,
612 s_ShadowFar,
613 nw::math::VEC2(0.0f, 0.0f),
614 s_OrthoCameraHeight,
615 nw::math::PIVOT_NONE);
616 }
617 break;
618 default:
619 {
620 NW_FATAL_ERROR("Unsupported camera type.");
621 }
622 break;
623 }
624
625 NW_NULL_ASSERT(s_ShadowCamera);
626
627 s_SceneRoot->AttachChild(s_ShadowCamera);
628 }
629
630 /*!--------------------------------------------------------------------------*
631 @brief シャドウ用のテクスチャコンバイナ関連の構築をします。
632 *---------------------------------------------------------------------------*/
633 void
SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)634 SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)
635 {
636 nw::gfx::ResTextureCoordinator resTexCoord = resMaterial.GetTextureCoordinators(0);
637 resTexCoord.SetReferenceCamera(1);
638 nw::gfx::ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(0);
639 // ダミーのテクスチャをシャドウ用のテクスチャに差し替えます。
640 nw::gfx::ResTexture dummyTexture = resTextureMapper.GetTexture().Dereference();
641 dummyTexture.Cleanup();
642 resTextureMapper.SetTexture(s_ShadowTexture);
643 }
644
645 /*!--------------------------------------------------------------------------*
646 @brief リソース関連の構築をします。
647 *---------------------------------------------------------------------------*/
648 void
BuildResources(nw::demo::ResourceSet * resourceSet)649 BuildResources(nw::demo::ResourceSet* resourceSet)
650 {
651 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
652 resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
653 resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
654
655 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
656 if (result.IsFailure())
657 {
658 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
659 }
660
661 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
662
663 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
664 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
665 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
666 modelResource != modelsEnd; ++modelResource)
667 {
668 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
669 &s_DeviceAllocator,
670 (*modelResource)
671 );
672
673 // plane の Texture0 にオフスクリーンバッファをテクスチャとしてセットする
674 if (::std::strcmp((*modelResource).GetName(), "Plane") == 0)
675 {
676 nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(node);
677 NW_ASSERT(model->GetMaterialCount() != 0);
678
679 nw::gfx::Material* material = model->GetMaterial(0);
680 nw::gfx::ResMaterial resMaterial = material->GetOriginal();
681 NW_ASSERT(resMaterial.IsValid());
682 SetupShadowMaterial(resMaterial);
683 }
684 else if (::std::strcmp((*modelResource).GetName(), "Male") == 0)
685 {
686 nw::gfx::SkeletalModel* skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
687 s_AnimModel = skeletalModel;
688
689 // 影を生成するモデルにフラグを設定します。
690 skeletalModel->SetUserParameter(SHADOW_CASTER);
691 }
692
693 sceneNodeArray.push_back(node);
694 }
695
696 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
697 nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
698 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
699 lightResource != lightsEnd; ++lightResource)
700 {
701 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
702 &s_DeviceAllocator,
703 (*lightResource)
704 );
705
706 if (::std::strcmp((*lightResource).GetName(), "SpotLight") == 0)
707 {
708 s_SpotLight = nw::ut::DynamicCast<nw::gfx::FragmentLight*>(node);
709 s_LightRoot->AttachChild(s_SpotLight);
710 }
711
712 sceneNodeArray.push_back(node);
713 }
714
715 // 親子付け参照関係を解決
716 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
717
718 // モデルをシーンに追加
719 nw::gfx::SceneHelper::ForeachRootNodes(
720 sceneNodeArray.Begin(),
721 sceneNodeArray.End(),
722 nw::gfx::AttachNode(s_ModelRoot)
723 );
724
725 nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
726 nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
727 for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
728 settingResource != settingsEnd; ++settingResource)
729 {
730 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
731 .Resource(*settingResource)
732 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
733
734 nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
735 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
736
737 NW_NULL_ASSERT(sceneEnvironmentSetting);
738 s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
739 }
740 }
741
742 /*!--------------------------------------------------------------------------*
743 @brief シーンを初期化します。
744 *---------------------------------------------------------------------------*/
745 void
InitializeScenes()746 InitializeScenes()
747 {
748 BuildRootNodes();
749
750 BuildCameras();
751
752 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
753 {
754 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
755 }
756
757 if (s_AnimModel != NULL)
758 {
759 InitializeSkeletalAnim(s_AnimModel);
760 }
761
762 // シーンツリーを巡回して初期化を行います。
763 s_SceneSystem->InitializeScene(s_SceneRoot);
764 s_SceneSystem->UpdateScene();
765
766 // シーン環境の参照解決を行い設定します。
767 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
768
769 // カメラを設定します。
770 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
771 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
772 sceneEnvironment.SetCamera(s_ShadowCameraIndex, s_ShadowCamera);
773 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
774
775 // シャドウ用のマテリアルとシェーダーを含むモデルを読み込みます。
776 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, SHADOW_MATERIAL_FILE_NAME, &s_DeviceAllocator);
777 nw::gfx::ResModel resShadowModel = resourceSet->resource.GetModels("ShadowModel");
778 nw::gfx::Result result = resShadowModel.Setup(&s_DeviceAllocator, resourceSet->resource);
779 NW_ASSERT(result.IsSuccess());
780 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
781 &s_DeviceAllocator,
782 resShadowModel
783 );
784 s_ShadowDummyModel = nw::ut::DynamicCast<nw::gfx::Model*>(node);
785 NW_NULL_ASSERT(s_ShadowDummyModel);
786
787 NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
788
789 // 影の強度(濃さ)を設定します。
790 nw::gfx::ResMaterialColor materialColor = s_ShadowDummyModel->GetMaterial(0)->GetOriginal().GetMaterialColor();
791 materialColor.SetDiffuse(s_ShadowIntensity, s_ShadowIntensity, s_ShadowIntensity);
792
793 nw::demo::CommandListSwapper* commandListSwapper = s_RenderSystem->GetCommandListSwapper();
794 NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
795 nw::gfx::Material* shadowMaterial = s_ShadowDummyModel->GetMaterial(0);
796
797 // レンダーコマンドを作成します。
798 void* startShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartShadowRenderCommand));
799 NW_NULL_ASSERT(startShadowCommandMemory);
800 s_StartShadowRenderCommand = new(startShadowCommandMemory) StartShadowRenderCommand(
801 commandListSwapper,
802 s_RenderTargets[1],
803 s_ShadowCameraIndex,
804 shadowMaterial);
805
806 void* endShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndShadowRenderCommand));
807 NW_NULL_ASSERT(endShadowCommandMemory);
808 s_EndShadowRenderCommand = new(endShadowCommandMemory) EndShadowRenderCommand(commandListSwapper, s_StartShadowRenderCommand);
809
810 void* startCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartRenderCommand));
811 NW_NULL_ASSERT(startCommandMemory);
812 s_StartRenderCommand = new(startCommandMemory) StartRenderCommand(s_RenderSystem, s_RenderTargets[0], s_BaseCameraIndex);
813
814 void* endCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndRenderCommand));
815 NW_NULL_ASSERT(endCommandMemory);
816 s_EndRenderCommand = new(endCommandMemory) EndRenderCommand(s_RenderSystem, s_LeftCamera, s_RightCamera, s_StartRenderCommand);
817
818 NW_GL_ASSERT();
819
820 s_FrameCount = 0;
821 }
822
823 /*!--------------------------------------------------------------------------*
824 @brief シーン関連の後始末をします。
825 *---------------------------------------------------------------------------*/
826 void
TerminateScenes()827 TerminateScenes()
828 {
829 s_DeviceAllocator.Free(s_EndRenderCommand);
830 s_DeviceAllocator.Free(s_StartRenderCommand);
831 s_DeviceAllocator.Free(s_EndShadowRenderCommand);
832 s_DeviceAllocator.Free(s_StartShadowRenderCommand);
833
834 nw::ut::SafeDestroy(s_ShadowDummyModel);
835 nw::gfx::SafeDestroyBranch(s_SceneRoot);
836 nw::demo::SafeCleanupResources(s_Resources);
837 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
838 TerminateAnim();
839
840 NW_GL_ASSERT();
841
842 s_Resources.clear();
843 s_SceneEnvironmentSettings.clear();
844 s_ModelRoot = NULL;
845 s_LightRoot = NULL;
846 }
847
848 /*!--------------------------------------------------------------------------*
849 @brief シーンを更新します。
850 *---------------------------------------------------------------------------*/
851 void
UpdateScene()852 UpdateScene()
853 {
854 float radian = static_cast<float>((s_FrameCount) % (314 * 2)) * 0.01f;
855
856 // ライトルートがY軸中心に回転します。
857 nw::gfx::TransformNode* lightNode =
858 nw::ut::DynamicCast<nw::gfx::TransformNode*>(s_LightRoot);
859 NW_NULL_ASSERT(lightNode);
860
861 lightNode->Transform().SetRotateXYZ(0.0f, radian, 0.0f);
862
863 s_SceneSystem->GetCameraController()->Update();
864
865 s_SceneSystem->UpdateScene();
866
867 s_BaseCamera->UpdateCameraMatrix();
868
869 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
870
871 // シャドウの描画をライト方向から行うために、カメラの位置と方向をライトに追従させます。
872 nw::math::VEC3 translate;
873 translate.x = s_SpotLight->WorldMatrix().m[0][3];
874 translate.y = s_SpotLight->WorldMatrix().m[1][3];
875 translate.z = s_SpotLight->WorldMatrix().m[2][3];
876
877 s_ShadowCamera->WorldMatrix().m[0][3] = translate.x;
878 s_ShadowCamera->WorldMatrix().m[1][3] = translate.y;
879 s_ShadowCamera->WorldMatrix().m[2][3] = translate.z;
880
881 const nw::math::VEC3& direction = s_SpotLight->Direction();
882 s_ShadowCamera->SetTargetPosition(translate + direction);
883
884 s_ShadowCamera->UpdateCameraMatrix();
885
886 ++s_FrameCount;
887 }
888
889 /*!--------------------------------------------------------------------------*
890 @brief レンダーキューにレンダーエレメントを追加します。
891 *---------------------------------------------------------------------------*/
892 void
SubmitView()893 SubmitView()
894 {
895 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
896 nw::gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
897 nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
898
899 nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
900
901 renderQueue->Reset();
902
903 // 描画対象とレンダーコマンドをレンダーキューに追加します。
904 // 分かりやすくするために処理される順に Submit or Enqueue を行います。
905
906 // シャドウ用の設定を行うコマンドをレイヤー0の後に実行するコールバックに追加します。
907 s_RenderSystem->EnqueueRenderCommand(
908 s_StartShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 0);
909
910 // シャドウキャスターとして指定されたモデルのみを レイヤー1としてレンダーキューに追加します。
911 s_SceneSystem->GetSceneUpdater()->SubmitView(
912 renderQueue,
913 sceneContext,
914 *s_ShadowCamera,
915 1,
916 1,
917 &s_ShadowCasterModel,
918 s_RenderSystem->GetRenderSortMode());
919
920 // シャドウの後処理を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
921 s_RenderSystem->EnqueueRenderCommand(
922 s_EndShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 1);
923
924 // ステレオ描画の前処理の設定を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
925 s_RenderSystem->EnqueueRenderCommand(
926 s_StartRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 1, 1);
927
928 // シーンコンテキストの全てのモデルをレイヤー2でレンダーキューに追加します。
929 s_SceneSystem->GetSceneUpdater()->SubmitView(
930 renderQueue,
931 sceneContext,
932 *s_BaseCamera,
933 2,
934 s_RenderSystem->GetRenderSortMode());
935
936 // ステレオ描画の後処理の設定を行うコマンドをレイヤー2の後に実行するコールバックに追加します。
937 s_RenderSystem->EnqueueRenderCommand(
938 s_EndRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 2);
939
940 std::sort(
941 renderQueue->Begin(),
942 renderQueue->End(),
943 nw::gfx::RenderElementCompare());
944 }
945
946 //----------------------------------------
947 struct RenderSceneInternalFunctor
948 : public std::unary_function<nw::gfx::RenderElement&, void>
949 {
950 nw::gfx::RenderContext* m_RenderContext;
951 nw::gfx::MeshRenderer* m_MeshRenderer;
952
RenderSceneInternalFunctor__anond8ebf6880111::RenderSceneInternalFunctor953 RenderSceneInternalFunctor(nw::gfx::RenderContext* renderContext, nw::gfx::MeshRenderer* meshRenderer)
954 : m_RenderContext(renderContext), m_MeshRenderer(meshRenderer)
955 {
956 NW_NULL_ASSERT(renderContext);
957 NW_NULL_ASSERT(meshRenderer);
958 }
959
operator ()__anond8ebf6880111::RenderSceneInternalFunctor960 void operator()(nw::gfx::RenderElement& element)
961 {
962 if (element.IsCommand())
963 {
964 nw::gfx::RenderCommand* command = element.GetCommand();
965 NW_NULL_ASSERT(command);
966 command->Invoke(this->m_RenderContext);
967 }
968 else
969 {
970 nw::gfx::ResMesh mesh = element.GetMesh();
971 nw::gfx::Model* model = element.GetModel();
972 model->PreRenderSignal()(model, mesh, this->m_RenderContext);
973 this->m_MeshRenderer->RenderMesh(mesh, model);
974 model->PostRenderSignal()(model, mesh, this->m_RenderContext);
975 }
976 NW_GL_ASSERT();
977 }
978 };
979
980 /*!--------------------------------------------------------------------------*
981 @brief レンダーキューに基づいて描画を行います。
982 *---------------------------------------------------------------------------*/
983 void
RenderScene()984 RenderScene()
985 {
986 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
987 nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
988 nw::gfx::MeshRenderer* meshRenderer = s_RenderSystem->GetMeshRenderer();
989
990 std::for_each(
991 renderQueue->Begin(),
992 renderQueue->End(),
993 RenderSceneInternalFunctor(renderContext, meshRenderer));
994
995 NW_GL_ASSERT();
996 }
997
998 /*!--------------------------------------------------------------------------*
999 @brief 負荷表示やテスト機能の処理をおこないます。
1000 *---------------------------------------------------------------------------*/
1001 void
ReportDemo()1002 ReportDemo()
1003 {
1004 NW_PROFILE("ReportDemo");
1005
1006 // 負荷表示からはこれらの負荷は除きます。
1007 s_RenderSystem->SuspendLoadMeter();
1008
1009 s_RenderSystem->AddLoadMeterCommandSize(
1010 s_EndShadowRenderCommand->GetCommandSize() - s_StartShadowRenderCommand->GetCommandSize());
1011
1012 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
1013
1014 s_GraphicsDrawing.BeginDrawingShape();
1015
1016 nw::demo::DebugUtility::DrawLoadMeter(
1017 s_RenderSystem,
1018 &s_GraphicsDrawing
1019 );
1020
1021 s_GraphicsDrawing.EndDrawingShape();
1022
1023 s_GraphicsDrawing.BeginDrawingString();
1024
1025 nw::demo::DebugUtility::DrawLoadMeterText(
1026 s_RenderSystem,
1027 &s_GraphicsDrawing
1028 );
1029
1030 s_GraphicsDrawing.EndDrawingString();
1031
1032 s_RenderSystem->ResumeLoadMeter();
1033 }
1034
1035 /*!--------------------------------------------------------------------------*
1036 @brief シーンをデモンストレーションします。
1037 *---------------------------------------------------------------------------*/
1038 void
DemoScene()1039 DemoScene()
1040 {
1041 NW_ASSERT(!s_RenderTargets.empty());
1042
1043 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
1044
1045 InitializeScenes();
1046
1047 nw::demo::DebugUtility::PostInitializeScenes();
1048
1049 bool isContinuing = true;
1050
1051 while ( isContinuing )
1052 {
1053 nw::demo::DebugUtility::AdvanceAutoTestFrame();
1054
1055 nw::demo::PadFactory::GetPad()->Update();
1056
1057 UpdateScene();
1058
1059 SubmitView();
1060
1061 RenderScene();
1062
1063 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
1064 ReportDemo();
1065 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
1066
1067 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
1068
1069 renderContext->ResetState();
1070
1071 if (nw::demo::Utility::IsTerminating())
1072 {
1073 isContinuing = false;
1074 }
1075 }
1076
1077 nw::demo::DebugUtility::PreTerminateScenes();
1078
1079 TerminateScenes();
1080 }
1081
1082 } // namespace
1083
1084 /*!--------------------------------------------------------------------------*
1085 @brief メイン関数です。
1086 *---------------------------------------------------------------------------*/
1087 void
nnMain()1088 nnMain()
1089 {
1090 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
1091
1092 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
1093
1094 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
1095 {
1096
1097 InitializeGraphics();
1098
1099 DemoScene();
1100
1101 TerminateGraphics();
1102
1103 }
1104
1105 nw::demo::PadFactory::Finalize();
1106
1107 nw::demo::FinalizeGraphicsSystem();
1108 }
1109