1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ShadowMapDemo.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 29438 $
14  *---------------------------------------------------------------------------*/
15 
16 #define NW_DEBUG_CHECK_MEMORY_LEAK
17 
18 #include <nn/os.h>
19 #include <nn/fs.h>
20 
21 #include <nw/types.h>
22 
23 #include <nw/demo.h>
24 #include <nw/dev.h>
25 #include <nw/gfx.h>
26 #include <nw/ut.h>
27 #include <nw/anim.h>
28 
29 namespace
30 {
31 
32 //----------------------------------------
33 // シャドウ関係
34 // シャドウの状態を表す UserFlag です
35 enum UserFlags
36 {
37     SHADOW_CASTER_SHIFT = 0,
38     SHADOW_RECEIVER_SHIFT = 1,
39 
40     SHADOW_CASTER = 0x1 << SHADOW_CASTER_SHIFT,
41     SHADOW_RECEIVER = 0x1 << SHADOW_RECEIVER_SHIFT
42 };
43 
44 // Shadow の Caster のみを描画要素に加える関数オブジェクトです。
45 class IsShadowCasterModelFunctor : public nw::gfx::ISceneUpdater::IsVisibleModelFunctor
46 {
47 public:
IsVisible(const nw::gfx::Model * model)48     virtual bool IsVisible(const nw::gfx::Model* model)
49     {
50         return nw::ut::CheckFlag(model->GetUserParameter<u32>(), SHADOW_CASTER);
51     }
52 };
53 
54 IsShadowCasterModelFunctor s_ShadowCasterModel;
55 
56 // シャドウの設定を行うレンダーコマンドです。
57 class StartShadowRenderCommand : public nw::gfx::RenderCommand
58 {
59     NW_DISALLOW_COPY_AND_ASSIGN(StartShadowRenderCommand);
60 
61 public:
StartShadowRenderCommand(nw::demo::CommandListSwapper * commandListSwapper,nw::gfx::IRenderTarget * renderTarget,s32 shadowCameraIndex,nw::gfx::Material * shadowMaterial)62     StartShadowRenderCommand(
63         nw::demo::CommandListSwapper* commandListSwapper,
64         nw::gfx::IRenderTarget* renderTarget,
65         s32 shadowCameraIndex,
66         nw::gfx::Material* shadowMaterial)
67         : m_CommandListSwapper(commandListSwapper),
68           m_RenderTarget(renderTarget),
69           m_ShadowCameraIndex(shadowCameraIndex),
70           m_ShadowMaterial(shadowMaterial),
71           m_CommandSize(0),
72           m_ProfilerPoint(0)
73     {}
~StartShadowRenderCommand()74     virtual ~StartShadowRenderCommand() {}
75 
Invoke(nw::gfx::RenderContext * renderContext)76     virtual void Invoke(nw::gfx::RenderContext* renderContext)
77     {
78         m_CommandSize = m_CommandListSwapper->GetCommandBufferSize();
79         m_ProfilerPoint = m_CommandListSwapper->AddGpuProfilingStartPoint(true);
80 
81         // オフスクリーンバッファに切り替えます。
82         renderContext->SetRenderTarget(m_RenderTarget);
83         renderContext->ClearBuffer(GL_COLOR_BUFFER_BIT, nw::ut::FloatColor(1.0f, 1.0f, 1.0f, 1.0f), 1.0f);
84 
85         // シャドウ用のマテリアル、カメラを設定します。
86         renderContext->SetActiveCamera(m_ShadowCameraIndex);
87         renderContext->SetMaterial(m_ShadowMaterial);
88         nw::gfx::Camera* shadowCamera = renderContext->GetActiveCamera();
89         renderContext->SetCameraMatrix(shadowCamera);
90         renderContext->ActivateContext();
91 
92         // 1Pass では RENDERMODE_IGNORE_MATERIAL を用いて以降のマテリアル設定を行いません。
93         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_IGNORE_MATERIAL);
94     }
95 
GetCommandSize() const96     s32 GetCommandSize() const { return this->m_CommandSize; }
GetProfilerPoint() const97     s32 GetProfilerPoint() const { return this->m_ProfilerPoint; }
98 
99 private:
100     nw::demo::CommandListSwapper* m_CommandListSwapper;
101     nw::gfx::IRenderTarget* m_RenderTarget;
102     s32 m_ShadowCameraIndex;
103     nw::gfx::Material* m_ShadowMaterial;
104     s32 m_CommandSize;
105     s32 m_ProfilerPoint;
106 };
107 
108 // シャドウの後処理を行うレンダーコマンドです。
109 class EndShadowRenderCommand : public nw::gfx::RenderCommand
110 {
111     NW_DISALLOW_COPY_AND_ASSIGN(EndShadowRenderCommand);
112 
113 public:
EndShadowRenderCommand(nw::demo::CommandListSwapper * commandListSwapper,StartShadowRenderCommand * startCommand)114     EndShadowRenderCommand(nw::demo::CommandListSwapper* commandListSwapper, StartShadowRenderCommand* startCommand)
115         : m_CommandListSwapper(commandListSwapper),
116           m_StartCommand(startCommand),
117           m_CommandSize(0)
118     {}
~EndShadowRenderCommand()119     virtual ~EndShadowRenderCommand() {}
120 
Invoke(nw::gfx::RenderContext * renderContext)121     virtual void Invoke(nw::gfx::RenderContext* renderContext)
122     {
123         // レンダーモードをデフォルトに戻し、マテリアル設定が通常通り行われるようにします。
124         renderContext->SetRenderMode(nw::gfx::RenderContext::RENDERMODE_DEFAULT);
125 
126         // 描画キャッシュを破棄するために ResetState を行います。
127         renderContext->ResetState();
128 
129         m_CommandSize = m_CommandListSwapper->GetCommandBufferSize();
130         int profilerPoint = m_StartCommand->GetProfilerPoint();
131         m_CommandListSwapper->SetGpuProfilingEndPoint(profilerPoint);
132     }
133 
GetCommandSize() const134     s32 GetCommandSize() const { return this->m_CommandSize; }
135 
136 private:
137     nw::demo::CommandListSwapper* m_CommandListSwapper;
138     StartShadowRenderCommand* m_StartCommand;
139     s32 m_CommandSize;
140 };
141 
142 // 描画開始の設定を行うレンダーコマンドです。
143 class StartRenderCommand : public nw::gfx::RenderCommand
144 {
145     NW_DISALLOW_COPY_AND_ASSIGN(StartRenderCommand);
146 
147 public:
StartRenderCommand(nw::demo::RenderSystem * renderSystem,nw::gfx::IRenderTarget * renderTarget,s32 baseCameraIndex)148     StartRenderCommand(nw::demo::RenderSystem* renderSystem, nw::gfx::IRenderTarget* renderTarget, s32 baseCameraIndex)
149         : m_RenderSystem(renderSystem),
150           m_RenderTarget(renderTarget),
151           m_BaseCameraIndex(baseCameraIndex),
152           m_CommandSize(0)
153     {}
154 
~StartRenderCommand()155     virtual ~StartRenderCommand() {}
156 
Invoke(nw::gfx::RenderContext * renderContext)157     virtual void Invoke(nw::gfx::RenderContext* renderContext)
158     {
159         nw::demo::CommandListSwapper* commandListSwapper = m_RenderSystem->GetCommandListSwapper();
160 
161         // 描画対象をオンスクリーンバッファに切り替えます
162         renderContext->SetRenderTarget(m_RenderTarget);
163         // ライト、環境マップなどの計算用カメラを設定します。
164         renderContext->SetActiveCamera(m_BaseCameraIndex);
165 
166         // ステレオ表示用コマンドの作成を開始します。作成したコマンドは複数回描画するために再利用されます。
167         commandListSwapper->StartCommandSave();
168 
169         m_CommandSize = commandListSwapper->GetCommandBufferSize();
170 
171         m_RenderSystem->ClearBySkyModel(renderContext->GetActiveCamera());
172     }
173 
GetCommandSize() const174     s32 GetCommandSize() const { return this->m_CommandSize; }
175 
176 private:
177     nw::demo::RenderSystem* m_RenderSystem;
178     nw::gfx::IRenderTarget* m_RenderTarget;
179     s32 m_BaseCameraIndex;
180     s32 m_CommandSize;
181 };
182 
183 // 描画終了の設定を行うレンダーコマンドです。
184 class EndRenderCommand : public nw::gfx::RenderCommand
185 {
186     NW_DISALLOW_COPY_AND_ASSIGN(EndRenderCommand);
187 
188 public:
EndRenderCommand(nw::demo::RenderSystem * renderSystem,nw::gfx::Camera * leftCamera,nw::gfx::Camera * rightCamera,StartRenderCommand * startCommand)189     EndRenderCommand(
190         nw::demo::RenderSystem* renderSystem,
191         nw::gfx::Camera* leftCamera,
192         nw::gfx::Camera* rightCamera,
193         StartRenderCommand* startCommand)
194         : m_RenderSystem(renderSystem),
195           m_LeftCamera(leftCamera),
196           m_RightCamera(rightCamera),
197           m_StartCommand(startCommand)
198     {}
~EndRenderCommand()199     virtual ~EndRenderCommand() {}
200 
Invoke(nw::gfx::RenderContext * renderContext)201     virtual void Invoke(nw::gfx::RenderContext* renderContext)
202     {
203         int commandSize = m_RenderSystem->GetCommandListSwapper()->GetCommandBufferSize();
204         m_RenderSystem->AddLoadMeterCommandSize(commandSize - m_StartCommand->GetCommandSize());
205 
206         nw::demo::CommandListSwapper* commandListSwapper = m_RenderSystem->GetCommandListSwapper();
207 
208         // ステレオ表示用コマンドの作成を終了します。
209         commandListSwapper->EndCommandSave();
210 
211         // GPU処理時間計測開始
212         int profilerLeft = commandListSwapper->AddGpuProfilingStartPoint(true);
213 
214         // 保存したコマンドを左目用の描画として再利用します。
215         renderContext->SetCameraMatrix(m_LeftCamera);
216         commandListSwapper->ReuseCommand(false);
217 
218         // GPU処理時間計測終了
219         commandListSwapper->SetGpuProfilingEndPoint(profilerLeft);
220 
221         m_RenderSystem->TransferBuffer(nw::demo::UPPER_SCREEN);
222 
223         // GPU処理時間計測開始
224         int profilerRight = commandListSwapper->AddGpuProfilingStartPoint(true);
225 
226         // 保存したコマンドを右目用の描画として再利用します。
227         renderContext->SetCameraMatrix(m_RightCamera);
228         commandListSwapper->ReuseCommand(false);
229 
230         // GPU処理時間計測終了
231         commandListSwapper->SetGpuProfilingEndPoint(profilerRight);
232 
233         m_RenderSystem->TransferBuffer(nw::demo::EXTENSION_SCREEN);
234     }
235 private:
236     nw::demo::RenderSystem* m_RenderSystem;
237     nw::gfx::Camera* m_LeftCamera;
238     nw::gfx::Camera* m_RightCamera;
239     StartRenderCommand* m_StartCommand;
240 };
241 
242 enum CameraKind
243 {
244     PERSPECTIVE_CAMERA,
245     FRUSTUM_CAMERA,
246     ORTHO_CAMERA
247 };
248 
249 nw::gfx::Camera* s_ShadowCamera = NULL;
250 // シャドウに用いるカメラの種類です。
251 CameraKind s_CameraKind = PERSPECTIVE_CAMERA;
252 // シャドウ用のカメラのパラメータです。
253 const f32 s_OrthoCameraHeight = 32.0f;
254 const f32 s_ShadowNear = 1.0f;
255 const f32 s_ShadowFar = 500.0f;
256 
257 StartShadowRenderCommand* s_StartShadowRenderCommand = NULL;
258 EndShadowRenderCommand* s_EndShadowRenderCommand = NULL;
259 StartRenderCommand* s_StartRenderCommand = NULL;
260 EndRenderCommand* s_EndRenderCommand = NULL;
261 
262 // シャドウのマテリアル、シェーダー設定用モデルです。
263 // このモデルはマテリアルとシェーダーの設定に利用されます。
264 // 実際には描画されません。
265 nw::gfx::Model* s_ShadowDummyModel = NULL;
266 // シャドウ用のテクスチャです。
267 nw::gfx::ResShadowTexture s_ShadowTexture;
268 // シャドウテクスチャのサイズです。
269 const s32 s_ShadowTextureSize = 512;
270 // シャドウに掛ける zBias です。
271 const f32 s_ShadowBias = 1.3f;
272 // 影の強度(濃さ)です。
273 const f32 s_ShadowIntensity = 0.2f;
274 
275 //----------------------------------------
276 // メモリ関係
277 
278 // デバイスメモリを確保するためのアロケータです。
279 nw::demo::DemoAllocator s_DeviceAllocator;
280 
281 //----------------------------------------
282 // ファイル名の定義です。
283 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
284 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
285 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
286 
287 const wchar_t* MODEL_RESOURCE_FILES[] =
288 {
289     NW_DEMO_FILE_PATH(L"MaleShadow.bcmdl"),
290     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
291     NW_DEMO_FILE_PATH(L"SpotLight.bcenv"),
292     NW_DEMO_FILE_PATH(L"AmbientLight.bcenv"),
293 };
294 
295 const wchar_t* SKELETAL_ANIM_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"WalkAimAt.bcskla");
296 
297 const wchar_t* SHADOW_MATERIAL_FILE_NAME = NW_DEMO_FILE_PATH(L"ShadowModel.bcmdl");
298 
299 //----------------------------------------
300 // プロファイル関係
301 const int NW_LOAD_METER_INTERVAL = 60;
302 
303 //----------------------------------------
304 // 描画関係
305 const int RENDER_TARGET_COUNT = 2;
306 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
307 
308 RenderTargetArray s_RenderTargets;
309 nw::demo::SceneSystem*  s_SceneSystem = NULL;
310 nw::demo::RenderSystem* s_RenderSystem = NULL;
311 
312 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
313 
314 //----------------------------------------
315 // リソース関係
316 nw::demo::ResourceArray s_Resources;
317 
318 //----------------------------------------
319 // シーン関係
320 nw::gfx::SceneNode* s_SceneRoot = NULL;
321 nw::gfx::SceneNode* s_ModelRoot = NULL;
322 nw::gfx::TransformNode* s_LightRoot = NULL;
323 s32 s_FrameCount = 0;
324 nw::gfx::Camera* s_BaseCamera = NULL;
325 nw::gfx::Camera* s_LeftCamera = NULL;
326 nw::gfx::Camera* s_RightCamera = NULL;
327 nw::gfx::FragmentLight* s_SpotLight = NULL;
328 
329 const f32 s_fNearPlane = 0.1f;
330 const f32 s_fFarPlane = 1000.0f;
331 
332 //----------------------------------------
333 // シーン環境関係
334 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
335 
336 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
337 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
338 
339 const s32 s_BaseCameraIndex = 0;
340 const s32 s_ShadowCameraIndex = 1;
341 
342 //----------------------------------------
343 // アニメーション関係
344 nw::gfx::SkeletalModel* s_AnimModel = NULL;
345 const int MAX_ANIM_OBJECTS = 8;
346 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
347 
348 /*!--------------------------------------------------------------------------*
349   @brief        グラフィックス関連の初期化を行います。
350  *---------------------------------------------------------------------------*/
351 void
InitializeGraphics()352 InitializeGraphics()
353 {
354     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
355 
356     // renderDescriptionへステレオの設定を行います。
357     nw::demo::RenderSystem::Description renderDescription;
358 
359     renderDescription.reusableCommandBufferSize = 0x100000;
360     renderDescription.reusableCommandRequestCount      = 512;
361     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
362 
363     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
364 
365     s_GraphicsDrawing.SetScreenSize(
366         renderDescription.lowerScreenDescription.width,
367         renderDescription.lowerScreenDescription.height
368     );
369 
370     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
371 
372     NN_ASSERTMSG(result, "Fail to load Font.");
373 
374     s_RenderTargets.push_back(
375         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
376     );
377 
378     bool isPerspectiveShadow = true;
379 
380     // Ortho カメラの場合は r 値による除算を行わないようにします。
381     if (s_CameraKind == ORTHO_CAMERA)
382     {
383         isPerspectiveShadow = false;
384     }
385 
386     // シャドウマップ用のテクスチャを生成します。
387     s_ShadowTexture =
388         nw::gfx::ResShadowTexture::DynamicBuilder()
389         .Width(s_ShadowTextureSize)
390         .Height(s_ShadowTextureSize)
391         .LocationFlag(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP)
392         .ExecutingMemoryFill(true)
393         .PerspectiveShadow(isPerspectiveShadow)
394         .ShadowZBias(s_ShadowBias * s_ShadowNear / (s_ShadowFar - s_ShadowNear))
395         .Create(&s_DeviceAllocator);
396     s_ShadowTexture.Setup(&s_DeviceAllocator, nw::gfx::ResGraphicsFile(NULL));
397 
398     // オフスクリーンバッファを作成します。
399     nw::gfx::IRenderTarget* offScreenTarget =
400         nw::gfx::IRenderTarget::CreateOffScreenBuffer(&s_DeviceAllocator, s_ShadowTexture);
401 
402     s_RenderTargets.push_back(offScreenTarget);
403 
404     NW_ASSERT(!s_RenderTargets.empty());
405     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets[0]);
406 
407     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
408     nw::demo::SceneSystem::Description sceneDescription;
409     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
410 
411     // デモ用の最遠景モデルをレンダリングシステムに設定します。
412     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
413     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
414 
415     NW_GL_ASSERT();
416 }
417 
418 /*!--------------------------------------------------------------------------*
419   @brief        グラフィックス関連の後始末をします。
420  *---------------------------------------------------------------------------*/
421 void
TerminateGraphics()422 TerminateGraphics()
423 {
424     s_ShadowTexture.Cleanup();
425     if (s_ShadowTexture.IsValid())
426     {
427         s_ShadowTexture.DynamicDestroy();
428     }
429 
430     nw::gfx::SafeDestroy(s_LeftCamera);
431 
432     nw::gfx::SafeDestroy(s_RightCamera);
433 
434     nw::gfx::SafeDestroy(s_SceneSystem);
435 
436     nw::gfx::SafeDestroyAll(s_RenderTargets);
437 
438     s_GraphicsDrawing.Finalize();
439 
440     nw::gfx::SafeDestroy(s_RenderSystem);
441 
442     NW_GL_ASSERT();
443 }
444 
445 /*!--------------------------------------------------------------------------*
446   @brief ファイルからトランスフォームアニメーション評価を生成します。
447 
448   @param[in] maxBones 最大メンバ数です。
449   @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
450   @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
451 
452   @return トランスフォームアニメーション評価です。
453  *---------------------------------------------------------------------------*/
454 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,const wchar_t * filePath)455 CreateTransformAnimEvaluator(
456     const int maxMembers,
457     const bool translateAnimEnabled,
458     const wchar_t* filePath
459 )
460 {
461     //----------------------------------------
462     // アニメーションリソースを生成します。
463     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
464     if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
465     {
466         return NULL;
467     }
468     nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0);
469 
470     if (!resAnim.IsValid())
471     {
472         return NULL;
473     }
474 
475     //----------------------------------------
476     // トランスフォームアニメーション評価を生成します。
477     //
478     // アニメーションを1つのモデルにのみ適用する場合や、
479     // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
480     nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
481         .AnimData(resAnim)
482         .MaxMembers(maxMembers)
483         .AllocCache(false)
484         .Create(&s_DeviceAllocator);
485 
486     // 移動アニメーションの無効化フラグを設定します。
487     evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
488 
489     return evaluator;
490 }
491 
492 /*!--------------------------------------------------------------------------*
493   @brief        スケルタルアニメーションを初期化します。
494 
495   @param[in]    model スケルタルモデルです。
496  *---------------------------------------------------------------------------*/
497 void
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)498 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
499 {
500     nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
501     if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。
502     {
503         return;
504     }
505 
506     nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
507     nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
508     const int maxBones = resSkeleton.GetBonesCount();
509     const bool translateAnimEnabled =
510         nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
511 
512     //----------------------------------------
513     // アニメーション評価を生成します。
514     nw::gfx::TransformAnimEvaluator* evaluator = CreateTransformAnimEvaluator(
515         maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILE);
516     if (evaluator == NULL)
517     {
518         return;
519     }
520 
521     // アニメーションをバインドします。
522     bool bindResult = evaluator->Bind(animGroup);
523 
524     //----------------------------------------
525     // アニメーションをモデルに登録します。
526     model->SetSkeletalAnimObject(evaluator);
527     s_AnimObjects.PushBack(evaluator);
528 }
529 
530 /*!--------------------------------------------------------------------------*
531   @brief        アニメーションの後始末をします。
532  *---------------------------------------------------------------------------*/
533 void
TerminateAnim(void)534 TerminateAnim(void)
535 {
536     for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
537     {
538         nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
539     }
540     s_AnimObjects.clear();
541 }
542 
543 /*!--------------------------------------------------------------------------*
544   @brief        ルートノード関連の構築をします。
545  *---------------------------------------------------------------------------*/
546 void
BuildRootNodes()547 BuildRootNodes()
548 {
549     NW_ASSERT(s_SceneRoot == NULL);
550     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
551         .IsFixedSizeMemory(false)
552         .Create(&s_DeviceAllocator);
553     NW_NULL_ASSERT(s_SceneRoot);
554 
555     NW_ASSERT(s_ModelRoot == NULL);
556     s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
557         .IsFixedSizeMemory(false)
558         .Create(&s_DeviceAllocator);
559     s_SceneRoot->AttachChild(s_ModelRoot);
560     NW_NULL_ASSERT(s_ModelRoot);
561 
562     NW_ASSERT(s_LightRoot == NULL);
563     s_LightRoot = nw::gfx::TransformNode::DynamicBuilder()
564         .IsFixedSizeMemory(false)
565         .Create(&s_DeviceAllocator);
566     s_SceneRoot->AttachChild(s_LightRoot);
567     NW_NULL_ASSERT(s_LightRoot);
568 }
569 
570 /*!--------------------------------------------------------------------------*
571   @brief        カメラ関連の構築をします。
572  *---------------------------------------------------------------------------*/
573 void
BuildCameras()574 BuildCameras()
575 {
576     nw::demo::Utility::CreateStereoCameras(
577         &s_BaseCamera,
578         &s_LeftCamera,
579         &s_RightCamera,
580         &s_DeviceAllocator,
581         nw::math::VEC3(20.0f, 15.0f, 20.0f),
582         nw::math::VEC3(0.0f, 10.0f, 0.0f),
583         s_fNearPlane,
584         s_fFarPlane
585     );
586     s_SceneRoot->AttachChild(s_BaseCamera);
587     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
588 
589     // シャドウ用のカメラを作成します。
590     switch (s_CameraKind)
591     {
592         case PERSPECTIVE_CAMERA:
593             {
594                 s_ShadowCamera =
595                     nw::demo::Utility::CreateCamera(
596                         &s_DeviceAllocator,
597                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
598                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
599                         s_ShadowNear,
600                         s_ShadowFar,
601                         NW_MATH_DEG_TO_RAD(45.0f),
602                         nw::math::PIVOT_NONE,
603                         1.0f / s_ShadowFar);
604             }
605             break;
606         case FRUSTUM_CAMERA:
607             {
608                 s_ShadowCamera =
609                     nw::demo::Utility::CreateFrustumCamera(
610                         &s_DeviceAllocator,
611                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
612                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
613                         s_ShadowNear,
614                         s_ShadowFar,
615                         nw::math::VEC2(0.0f, 0.0f),
616                         1.0f,
617                         nw::math::PIVOT_NONE,
618                         1.0f / s_ShadowFar);
619             }
620             break;
621         case ORTHO_CAMERA:
622             {
623                 s_ShadowCamera =
624                     nw::demo::Utility::CreateOrthoCamera(
625                         &s_DeviceAllocator,
626                         nw::math::VEC3(20.0f, 15.0f, 20.0f),
627                         nw::math::VEC3(0.0f, 10.0f, 0.0f),
628                         s_ShadowNear,
629                         s_ShadowFar,
630                         nw::math::VEC2(0.0f, 0.0f),
631                         s_OrthoCameraHeight,
632                         nw::math::PIVOT_NONE);
633             }
634             break;
635         default:
636             {
637                 NW_FATAL_ERROR("Unsupported camera type.");
638             }
639             break;
640     }
641 
642     NW_NULL_ASSERT(s_ShadowCamera);
643 
644     s_SceneRoot->AttachChild(s_ShadowCamera);
645 }
646 
647 /*!--------------------------------------------------------------------------*
648   @brief        シャドウ用のテクスチャコンバイナ関連の構築をします。
649  *---------------------------------------------------------------------------*/
650 void
SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)651 SetupShadowMaterial(nw::gfx::ResMaterial resMaterial)
652 {
653     NW_ASSERT(resMaterial.GetTextureCoordinatorsCount() != 0);
654 
655     resMaterial.SetTextureCoordinatorsHash(0x0);
656     resMaterial.SetTextureMappersHash(0x0);
657     resMaterial.SetTextureCombinersHash(0x0);
658     resMaterial.SetMaterialColorHash(0x0);
659 
660     nw::gfx::ResTextureCoordinator resTexCoord = resMaterial.GetTextureCoordinators(0);
661 
662     // シャドウマップ用のカメラのインデクスとシャドウマップ用のテクスチャマトリクス計算法を設定します。
663     resTexCoord.SetReferenceCamera(1);
664     resTexCoord.SetMappingMethod(nw::gfx::ResTextureCoordinator::MAPPINGMETHOD_SHADOW);
665 
666     NW_ASSERT(resMaterial.GetTextureMappersCount() != 0);
667     nw::gfx::ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(0);
668 
669     // ダミーテクスチャとシャドウ用テクスチャを差し替えます。
670     nw::gfx::ResTexture dummyTexture = resTextureMapper.GetTexture().Dereference();
671     dummyTexture.Cleanup();
672     resTextureMapper.SetTexture(s_ShadowTexture);
673 
674     nw::gfx::ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
675 
676     // シャドウを表示するためのコンバイナ設定を行います。
677     nw::gfx::ResTextureCombiner combiner0 = resFragmentShader.GetTextureCombiners(0);
678     combiner0.SetSourceRgb(0, nw::gfx::ResTextureCombiner::SOURCE_TEXTURE0);
679     combiner0.SetSourceRgb(1, nw::gfx::ResTextureCombiner::SOURCE_CONSTANT);
680     combiner0.SetOperandRgb(0, nw::gfx::ResTextureCombiner::OPERANDRGB_ONE_MINUS_SRC_COLOR);
681     combiner0.SetOperandRgb(1, nw::gfx::ResTextureCombiner::OPERANDRGB_SRC_COLOR);
682     combiner0.SetCombineRgb(nw::gfx::ResTextureCombiner::COMBINE_MODULATE);
683 
684     nw::gfx::ResTextureCombiner combiner1 = resFragmentShader.GetTextureCombiners(1);
685     combiner1.SetSourceRgb(0, nw::gfx::ResTextureCombiner::SOURCE_TEXTURE1);
686     combiner1.SetSourceRgb(1, nw::gfx::ResTextureCombiner::SOURCE_PREVIOUS);
687     combiner1.SetOperandRgb(0, nw::gfx::ResTextureCombiner::OPERANDRGB_SRC_COLOR);
688     combiner1.SetOperandRgb(1, nw::gfx::ResTextureCombiner::OPERANDRGB_ONE_MINUS_SRC_COLOR);
689     combiner1.SetCombineRgb(nw::gfx::ResTextureCombiner::COMBINE_MODULATE);
690 
691     nw::gfx::ResTextureCombiner combiner2 = resFragmentShader.GetTextureCombiners(2);
692     combiner2.SetSourceRgb(0, nw::gfx::ResTextureCombiner::SOURCE_FRAGMENT_PRIMARY_COLOR);
693     combiner2.SetSourceRgb(1, nw::gfx::ResTextureCombiner::SOURCE_PREVIOUS);
694     combiner2.SetSourceRgb(2, nw::gfx::ResTextureCombiner::SOURCE_FRAGMENT_SECONDARY_COLOR);
695     combiner2.SetOperandRgb(0, nw::gfx::ResTextureCombiner::OPERANDRGB_SRC_COLOR);
696     combiner2.SetOperandRgb(1, nw::gfx::ResTextureCombiner::OPERANDRGB_SRC_COLOR);
697     combiner2.SetOperandRgb(2, nw::gfx::ResTextureCombiner::OPERANDRGB_SRC_COLOR);
698     combiner2.SetCombineRgb(nw::gfx::ResTextureCombiner::COMBINE_MULT_ADD);
699 
700     // 影の色を設定します。
701     nw::gfx::ResMaterialColor color = resMaterial.GetMaterialColor();
702     color.SetConstant0(1.0f - s_ShadowIntensity, 1.0f - s_ShadowIntensity, 1.0f - s_ShadowIntensity);
703 }
704 
705 /*!--------------------------------------------------------------------------*
706   @brief        リソース関連の構築をします。
707  *---------------------------------------------------------------------------*/
708 void
BuildResources(nw::demo::ResourceSet * resourceSet)709 BuildResources(nw::demo::ResourceSet* resourceSet)
710 {
711     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
712     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
713     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
714 
715     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
716     if (result.IsFailure())
717     {
718         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
719     }
720 
721     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
722 
723     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
724     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
725     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
726          modelResource != modelsEnd; ++modelResource)
727     {
728         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
729             &s_DeviceAllocator,
730             (*modelResource)
731         );
732 
733         // plane の Texture0 にオフスクリーンバッファをテクスチャとしてセットする
734         if (::std::strcmp((*modelResource).GetName(), "Plane") == 0)
735         {
736             nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(node);
737             NW_ASSERT(model->GetMaterialCount() != 0);
738 
739             nw::gfx::Material* material = model->GetMaterial(0);
740             nw::gfx::ResMaterial resMaterial = material->GetOriginal();
741             NW_ASSERT(resMaterial.IsValid());
742             SetupShadowMaterial(resMaterial);
743         }
744         else if (::std::strcmp((*modelResource).GetName(), "Male") == 0)
745         {
746             nw::gfx::SkeletalModel* skeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
747             s_AnimModel = skeletalModel;
748 
749             nw::gfx::Material* material = skeletalModel->GetMaterial(0);
750             NW_ASSERT(skeletalModel->GetMaterialCount() != 0);
751 
752             nw::gfx::ResMaterial resMaterial = material->GetOriginal();
753             NW_ASSERT(resMaterial.IsValid());
754             SetupShadowMaterial(resMaterial);
755 
756             // 影を生成するモデルにフラグを設定します。
757             skeletalModel->SetUserParameter(SHADOW_CASTER);
758         }
759 
760         sceneNodeArray.push_back(node);
761     }
762 
763     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
764     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
765     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
766          lightResource != lightsEnd; ++lightResource)
767     {
768         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
769             &s_DeviceAllocator,
770             (*lightResource)
771         );
772 
773         if (::std::strcmp((*lightResource).GetName(), "SpotLight") == 0)
774         {
775             s_SpotLight = nw::ut::DynamicCast<nw::gfx::FragmentLight*>(node);
776             s_LightRoot->AttachChild(s_SpotLight);
777         }
778 
779         sceneNodeArray.push_back(node);
780     }
781 
782     // 親子付け参照関係を解決
783     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
784 
785     // モデルをシーンに追加
786     nw::gfx::SceneHelper::ForeachRootNodes(
787         sceneNodeArray.Begin(),
788         sceneNodeArray.End(),
789         nw::gfx::AttachNode(s_ModelRoot)
790     );
791 
792     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
793     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
794     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
795         settingResource != settingsEnd; ++settingResource)
796     {
797         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
798             .Resource(*settingResource)
799             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
800 
801         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
802             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
803 
804         NW_NULL_ASSERT(sceneEnvironmentSetting);
805         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
806     }
807 }
808 
809 /*!--------------------------------------------------------------------------*
810   @brief        シーンを初期化します。
811  *---------------------------------------------------------------------------*/
812 void
InitializeScenes()813 InitializeScenes()
814 {
815     BuildRootNodes();
816 
817     BuildCameras();
818 
819     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
820     {
821         BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
822     }
823 
824     if (s_AnimModel != NULL)
825     {
826         InitializeSkeletalAnim(s_AnimModel);
827     }
828 
829     // シーンツリーを巡回して初期化を行います。
830     s_SceneSystem->InitializeScene(s_SceneRoot);
831     s_SceneSystem->UpdateScene();
832 
833     // シーン環境の参照解決を行い設定します。
834     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
835 
836     // カメラを設定します。
837     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
838     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
839     sceneEnvironment.SetCamera(s_ShadowCameraIndex, s_ShadowCamera);
840     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
841 
842     // シャドウ用のマテリアルとシェーダーを含むモデルを読み込みます。
843     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, SHADOW_MATERIAL_FILE_NAME, &s_DeviceAllocator);
844     nw::gfx::ResModel resShadowModel = resourceSet->resource.GetModels("ShadowModel");
845     nw::gfx::Result result = resShadowModel.Setup(&s_DeviceAllocator, resourceSet->resource);
846     NW_ASSERT(result.IsSuccess());
847     nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
848         &s_DeviceAllocator,
849         resShadowModel
850     );
851     s_ShadowDummyModel = nw::ut::DynamicCast<nw::gfx::Model*>(node);
852     NW_NULL_ASSERT(s_ShadowDummyModel);
853 
854     NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
855 
856     // シャドウ用のマテリアルにシャドウモードを設定します。
857     // シャドウマップにシャドウ強度とデプス情報を書き込むために必要となります。
858     nw::gfx::ResFragmentOperation fragmentOperation = s_ShadowDummyModel->GetMaterial(0)->GetOriginal().GetFragmentOperation();
859     fragmentOperation.SetFragmentOperationMode(nw::gfx::ResFragmentOperation::FRAGMENT_OPERATION_MODE_SHADOW);
860 
861     // シャドウオブジェクトの色を設定します。
862     // シャドウマップでは必ず黒(0.0f, 0.0f, 0.0f ,0.0f) に設定する必要があります。
863     // 影の色の設定ははコンバイナでコンスタントカラーによって行っています。
864     nw::gfx::ResMaterialColor materialColor = s_ShadowDummyModel->GetMaterial(0)->GetOriginal().GetMaterialColor();
865     materialColor.SetDiffuse(0.0f, 0.0f, 0.0f, 0.0f);
866 
867     nw::demo::CommandListSwapper* commandListSwapper = s_RenderSystem->GetCommandListSwapper();
868     NW_ASSERT(s_ShadowDummyModel->GetMaterialCount() != 0);
869     nw::gfx::Material* shadowMaterial = s_ShadowDummyModel->GetMaterial(0);
870 
871     // レンダーコマンドを作成します。
872     void* startShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartShadowRenderCommand));
873     NW_NULL_ASSERT(startShadowCommandMemory);
874     s_StartShadowRenderCommand = new(startShadowCommandMemory) StartShadowRenderCommand(
875         commandListSwapper,
876         s_RenderTargets[1],
877         s_ShadowCameraIndex,
878         shadowMaterial);
879 
880     void* endShadowCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndShadowRenderCommand));
881     NW_NULL_ASSERT(endShadowCommandMemory);
882     s_EndShadowRenderCommand = new(endShadowCommandMemory) EndShadowRenderCommand(commandListSwapper, s_StartShadowRenderCommand);
883 
884     void* startCommandMemory = s_DeviceAllocator.Alloc(sizeof(StartRenderCommand));
885     NW_NULL_ASSERT(startCommandMemory);
886     s_StartRenderCommand = new(startCommandMemory) StartRenderCommand(s_RenderSystem, s_RenderTargets[0], s_BaseCameraIndex);
887 
888     void* endCommandMemory = s_DeviceAllocator.Alloc(sizeof(EndRenderCommand));
889     NW_NULL_ASSERT(endCommandMemory);
890     s_EndRenderCommand = new(endCommandMemory) EndRenderCommand(s_RenderSystem, s_LeftCamera, s_RightCamera, s_StartRenderCommand);
891 
892     NW_GL_ASSERT();
893 
894     s_FrameCount = 0;
895 }
896 
897 /*!--------------------------------------------------------------------------*
898   @brief        シーン関連の後始末をします。
899  *---------------------------------------------------------------------------*/
900 void
TerminateScenes()901 TerminateScenes()
902 {
903     s_DeviceAllocator.Free(s_EndRenderCommand);
904     s_DeviceAllocator.Free(s_StartRenderCommand);
905     s_DeviceAllocator.Free(s_EndShadowRenderCommand);
906     s_DeviceAllocator.Free(s_StartShadowRenderCommand);
907 
908     nw::ut::SafeDestroy(s_ShadowDummyModel);
909     nw::gfx::SafeDestroyBranch(s_SceneRoot);
910     nw::demo::SafeCleanupResources(s_Resources);
911     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
912     TerminateAnim();
913 
914     NW_GL_ASSERT();
915 
916     s_Resources.clear();
917     s_SceneEnvironmentSettings.clear();
918     s_ModelRoot = NULL;
919     s_LightRoot = NULL;
920 }
921 
922 /*!--------------------------------------------------------------------------*
923   @brief        シーンを更新します。
924  *---------------------------------------------------------------------------*/
925 void
UpdateScene()926 UpdateScene()
927 {
928     float radian = static_cast<float>((s_FrameCount) % (314 * 2)) * 0.01f;
929 
930     // ライトルートがY軸中心に回転します。
931     nw::gfx::TransformNode* lightNode =
932         nw::ut::DynamicCast<nw::gfx::TransformNode*>(s_LightRoot);
933     NW_NULL_ASSERT(lightNode);
934 
935     lightNode->Transform().SetRotateXYZ(0.0f, radian, 0.0f);
936 
937     s_SceneSystem->GetCameraController()->Update();
938 
939     s_SceneSystem->UpdateScene();
940 
941     s_BaseCamera->UpdateCameraMatrix();
942 
943     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
944 
945     // シャドウの描画をライト方向から行うために、カメラの位置と方向をライトに追従させます。
946     nw::math::VEC3 translate;
947     translate.x = s_SpotLight->WorldMatrix().m[0][3];
948     translate.y = s_SpotLight->WorldMatrix().m[1][3];
949     translate.z = s_SpotLight->WorldMatrix().m[2][3];
950 
951     s_ShadowCamera->WorldMatrix().m[0][3] = translate.x;
952     s_ShadowCamera->WorldMatrix().m[1][3] = translate.y;
953     s_ShadowCamera->WorldMatrix().m[2][3] = translate.z;
954 
955     const nw::math::VEC3& direction = s_SpotLight->Direction();
956     s_ShadowCamera->SetTargetPosition(translate + direction);
957 
958     s_ShadowCamera->UpdateCameraMatrix();
959 
960     ++s_FrameCount;
961 }
962 
963 /*!--------------------------------------------------------------------------*
964   @brief        レンダーキューにレンダーエレメントを追加します。
965  *---------------------------------------------------------------------------*/
966 void
SubmitView()967 SubmitView()
968 {
969     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
970     nw::gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
971     nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
972 
973     nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
974 
975     renderQueue->Reset();
976 
977     // 描画対象とレンダーコマンドをレンダーキューに追加します。
978     // 分かりやすくするために処理される順に Submit or Enqueue を行います。
979 
980     // シャドウ用の設定を行うコマンドをレイヤー0の後に実行するコールバックに追加します。
981     s_RenderSystem->EnqueueRenderCommand(
982         s_StartShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 0);
983 
984     // シャドウキャスターとして指定されたモデルのみを レイヤー1としてレンダーキューに追加します。
985     s_SceneSystem->GetSceneUpdater()->SubmitView(
986         renderQueue,
987         sceneContext,
988         *s_ShadowCamera,
989         1,
990         1,
991         &s_ShadowCasterModel,
992         s_RenderSystem->GetRenderSortMode());
993 
994     // シャドウの後処理を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
995     s_RenderSystem->EnqueueRenderCommand(
996         s_EndShadowRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 1);
997 
998     // ステレオ描画の前処理の設定を行うコマンドをレイヤー1の後に実行するコールバックに追加します。
999     s_RenderSystem->EnqueueRenderCommand(
1000         s_StartRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 1, 1);
1001 
1002     // シーンコンテキストの全てのモデルをレイヤー2でレンダーキューに追加します。
1003     s_SceneSystem->GetSceneUpdater()->SubmitView(
1004         renderQueue,
1005         sceneContext,
1006         *s_BaseCamera,
1007         2,
1008         s_RenderSystem->GetRenderSortMode());
1009 
1010     // ステレオ描画の後処理の設定を行うコマンドをレイヤー2の後に実行するコールバックに追加します。
1011     s_RenderSystem->EnqueueRenderCommand(
1012         s_EndRenderCommand, nw::gfx::ResMaterial::TRANSLUCENCY_KIND_OPAQUE, 0, 2);
1013 
1014     std::sort(
1015         renderQueue->Begin(),
1016         renderQueue->End(),
1017         nw::gfx::RenderElementCompare());
1018 }
1019 
1020 //----------------------------------------
1021 struct RenderSceneInternalFunctor
1022 : public std::unary_function<nw::gfx::RenderElement&, void>
1023 {
1024     nw::gfx::RenderContext* m_RenderContext;
1025     nw::gfx::MeshRenderer* m_MeshRenderer;
1026 
RenderSceneInternalFunctor__anon3ce08f1b0111::RenderSceneInternalFunctor1027     RenderSceneInternalFunctor(nw::gfx::RenderContext* renderContext, nw::gfx::MeshRenderer* meshRenderer)
1028     : m_RenderContext(renderContext), m_MeshRenderer(meshRenderer)
1029     {
1030         NW_NULL_ASSERT(renderContext);
1031         NW_NULL_ASSERT(meshRenderer);
1032     }
1033 
operator ()__anon3ce08f1b0111::RenderSceneInternalFunctor1034     void operator()(nw::gfx::RenderElement& element)
1035     {
1036         if (element.IsCommand())
1037         {
1038             nw::gfx::RenderCommand* command = element.GetCommand();
1039             NW_NULL_ASSERT(command);
1040             command->Invoke(this->m_RenderContext);
1041         }
1042         else
1043         {
1044             nw::gfx::ResMesh mesh = element.GetMesh();
1045             nw::gfx::Model* model = element.GetModel();
1046             model->PreRenderSignal()(model, mesh, this->m_RenderContext);
1047             this->m_MeshRenderer->RenderMesh(mesh, model);
1048             model->PostRenderSignal()(model, mesh, this->m_RenderContext);
1049         }
1050         NW_GL_ASSERT();
1051     }
1052 };
1053 
1054 /*!--------------------------------------------------------------------------*
1055   @brief        レンダーキューに基づいて描画を行います。
1056  *---------------------------------------------------------------------------*/
1057 void
RenderScene()1058 RenderScene()
1059 {
1060     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
1061     nw::gfx::RenderQueue* renderQueue = s_RenderSystem->GetRenderQueue();
1062     nw::gfx::MeshRenderer* meshRenderer = s_RenderSystem->GetMeshRenderer();
1063 
1064     std::for_each(
1065         renderQueue->Begin(),
1066         renderQueue->End(),
1067         RenderSceneInternalFunctor(renderContext, meshRenderer));
1068 
1069     NW_GL_ASSERT();
1070 }
1071 
1072 /*!--------------------------------------------------------------------------*
1073   @brief        負荷表示やテスト機能の処理をおこないます。
1074  *---------------------------------------------------------------------------*/
1075 void
ReportDemo()1076 ReportDemo()
1077 {
1078     NW_PROFILE("ReportDemo");
1079 
1080     // 負荷表示からはこれらの負荷は除きます。
1081     s_RenderSystem->SuspendLoadMeter();
1082 
1083     s_RenderSystem->AddLoadMeterCommandSize(
1084         s_EndShadowRenderCommand->GetCommandSize() - s_StartShadowRenderCommand->GetCommandSize());
1085 
1086     s_GraphicsDrawing.BeginDrawingString();
1087 
1088     nw::demo::DebugUtility::DrawLoadMeter(
1089         s_RenderSystem,
1090         &s_GraphicsDrawing,
1091         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
1092     );
1093 
1094     s_GraphicsDrawing.FlushDrawing();
1095 
1096     s_RenderSystem->ResumeLoadMeter();
1097 }
1098 
1099 /*!--------------------------------------------------------------------------*
1100   @brief        シーンをデモンストレーションします。
1101  *---------------------------------------------------------------------------*/
1102 void
DemoScene()1103 DemoScene()
1104 {
1105     NW_ASSERT(!s_RenderTargets.empty());
1106 
1107     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
1108 
1109     InitializeScenes();
1110 
1111     bool isContinuing = true;
1112 
1113     while ( isContinuing )
1114     {
1115         nw::demo::DebugUtility::AdvanceAutoTestFrame();
1116 
1117         nw::demo::PadFactory::GetPad()->Update();
1118 
1119         UpdateScene();
1120 
1121         SubmitView();
1122 
1123         RenderScene();
1124 
1125         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
1126         ReportDemo();
1127         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
1128 
1129         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
1130 
1131         renderContext->ResetState();
1132 
1133         if (nw::demo::Utility::IsTerminating())
1134         {
1135             isContinuing = false;
1136         }
1137     }
1138 
1139     TerminateScenes();
1140 }
1141 
1142 } // namespace
1143 
1144 /*!--------------------------------------------------------------------------*
1145   @brief        メイン関数です。
1146  *---------------------------------------------------------------------------*/
1147 void
nnMain()1148 nnMain()
1149 {
1150     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
1151 
1152     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
1153 
1154     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
1155     {
1156 
1157         InitializeGraphics();
1158 
1159         DemoScene();
1160 
1161         TerminateGraphics();
1162 
1163     }
1164 
1165     nw::demo::PadFactory::Finalize();
1166 
1167     nw::demo::FinalizeGraphicsSystem();
1168 }
1169