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