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