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