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