1 /*---------------------------------------------------------------------------*
2   Project: NintendoWare
3   File   : gfx_RenderElement.h
4 
5   Copyright (C) 2010 Nintendo Co., Ltd. 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: 24209 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_RENDERELEMENT_H_
17 #define NW_GFX_RENDERELEMENT_H_
18 
19 #include <nw/gfx/gfx_GfxObject.h>
20 #include <nw/gfx/gfx_Model.h>
21 #include <nw/gfx/res/gfx_ResModel.h>
22 #include <nw/gfx/res/gfx_ResMesh.h>
23 
24 #include <functional>
25 
26 namespace nw
27 {
28 namespace gfx
29 {
30 
31 class Material;
32 class RenderContext;
33 
34 //---------------------------------------------------------------------------
35 //! @brief レンダーキューの途中に独自処理を割り込ませるためのクラスです。
36 //---------------------------------------------------------------------------
37 class RenderCommand
38 {
39 private:
40     NW_DISALLOW_COPY_AND_ASSIGN(RenderCommand);
41 
42 public:
43 
44     //! @brief コマンドを呼び出します。
45     virtual void Invoke(RenderContext* renderContext) = 0;
46 
47 protected:
48     //! コンストラクタです。
RenderCommand()49     RenderCommand() {}
50     //! デストラクタです。
~RenderCommand()51     virtual ~RenderCommand() {}
52 };
53 
54 //---------------------------------------------------------------------------
55 //! @brief レンダーキューに積まれる描画単位となるクラスです。
56 //!
57 //! @tparam TKey レンダーキーの型です。
58 //---------------------------------------------------------------------------
59 template<typename TKey>
60 class BasicRenderElement
61 {
62 public:
63     //! @brief キーの値となる型です。
64     typedef TKey KeyType;
65 
66     //! @brief 64 ビット版の レンダーキーのビット配置の定義です。
67     enum Bit64RenderKeyFormat
68     {
69         BIT64_LAYER_SHIFT = 56,
70         BIT64_LAYER_BIT_SIZE = 8,
71         BIT64_LAYER_MASK = (1 << BIT64_LAYER_BIT_SIZE) - 1,
72 
73         BIT64_TRANSLUCENCY_KIND_SHIFT = 54,
74         BIT64_TRANSLUCENCY_KIND_BIT_SIZE = 2,
75         BIT64_TRANSLUCENCY_KIND_MASK = (1 << BIT64_TRANSLUCENCY_KIND_BIT_SIZE) - 1,
76 
77         BIT64_COMMAND_FLAG_SHIFT = 53,
78         BIT64_COMMAND_FLAG_MASK = 0x1,
79         BIT64_COMMAND_BIT_SIZE = 32,
80         BIT64_COMMAND_MASK = 0xffffffff,
81 
82         BIT64_DEPTH_BIT_SIZE = 24,
83         BIT64_DEPTH_MASK = (1 << BIT64_DEPTH_BIT_SIZE) - 1,
84         BIT64_DEPTH_MAX_VALUE = BIT64_DEPTH_MASK,
85 
86         BIT64_MATERIAL_ID_BIT_SIZE = 29,
87         BIT64_MATERIAL_ID_MASK = (1 << BIT64_MATERIAL_ID_BIT_SIZE) - 1,
88 
89         // マテリアルID用の定義です。
90         BIT64_MATERIAL_RESOURCE_ID_BIT_SIZE = 22,
91         BIT64_MATERIAL_RESOURCE_ID_MASK = (1 << BIT64_MATERIAL_RESOURCE_ID_BIT_SIZE) - 1,
92 
93         BIT64_MATERIAL_INSTANCE_ID_BIT_SIZE = 3,
94         BIT64_MATERIAL_INSTANCE_ID_MASK = (1 << BIT64_MATERIAL_INSTANCE_ID_BIT_SIZE) - 1,
95 
96         BIT64_MATERIAL_PRIORITY_BIT_SIZE = 4,
97         BIT64_MATERIAL_PRIORITY_MASK = (1 << BIT64_MATERIAL_PRIORITY_BIT_SIZE) - 1,
98 
99         // 簡易マテリアルID用の定義です。深度優先のキーなどに使用します。
100         BIT64_SIMPLE_MATERIAL_ID_BIT_SIZE = 21,
101         BIT64_SIMPLE_MATERIAL_ID_MASK = (1 << BIT64_SIMPLE_MATERIAL_ID_BIT_SIZE) - 1,
102 
103         BIT64_SIMPLE_MATERIAL_PRIORITY_BIT_SIZE = 8,
104         BIT64_SIMPLE_MATERIAL_PRIORITY_MASK = (1 << BIT64_SIMPLE_MATERIAL_PRIORITY_BIT_SIZE) - 1
105     };
106 
107     //! @brief 24 ビット整数の深度値量子化関数オブジェクトです。
108     //!
109     //! 近いものが先に描画されるようになります。
110     //!
111     struct Depth24bitQuantizer : public std::unary_function<float, KeyType>
112     {
operatorDepth24bitQuantizer113         KeyType operator()(float depth)
114         {
115             return static_cast<KeyType>(
116                 depth * static_cast<float>(BIT64_DEPTH_MAX_VALUE))
117                 & BIT64_DEPTH_MASK;
118         }
119     };
120 
121     //! @brief 24 ビット整数の深度値量子化関数オブジェクトです。
122     //!
123     //! 遠いものが先に描画されるようになります。
124     //!
125     struct ReverseDepth24bitQuantizer : public std::unary_function<float, KeyType>
126     {
operatorReverseDepth24bitQuantizer127         KeyType operator()(float depth)
128         {
129             return static_cast<KeyType>(
130                 (1.0f - depth) * static_cast<float>(BIT64_DEPTH_MAX_VALUE))
131                 & BIT64_DEPTH_MASK;
132         }
133     };
134 
135     //! @brief 深度値量子化を行わない関数オブジェクトです。
136     //!
137     //! 0を返すだけです。
138     //!
139     struct ZeroQuantizer : public std::unary_function<float, KeyType>
140     {
operatorZeroQuantizer141         KeyType operator()(float depth)
142         {
143             NW_UNUSED_VARIABLE(depth);
144             return 0;
145         }
146     };
147 
148     //! @brief 64 ビット版のレンダーキーを設定するためのクラスです。
149     template<typename TDepthQuantizer = Depth24bitQuantizer>
150     class Bit64RenderKey
151     {
152     private:
153         NW_DISALLOW_COPY_AND_ASSIGN(Bit64RenderKey);
154 
155     public:
156         //----------------------------------------
157         //! @name 作成
158         //@{
159 
160         //! @brief コンストラクタです。
Bit64RenderKey()161         Bit64RenderKey() : m_Key(0) {}
162 
163         //@}
164 
165         //----------------------------------------
166         //! @name 取得/設定
167         //@{
168 
169         //! @brief  描画要素のソート時に最優先に区分される ID を設定します。
SetLayerId(u8 layerId)170         void SetLayerId(u8 layerId)
171         {
172             m_Key |= static_cast<KeyType>(layerId & BIT64_LAYER_MASK)
173                 << BIT64_LAYER_SHIFT;
174         }
175 
176         //! @brief 詳細マテリアル用の描画優先度を設定します。
SetPriorityForDetailedMaterial(u8 priority,u32 shift)177         void SetPriorityForDetailedMaterial(u8 priority, u32 shift)
178         {
179             m_Key |=
180                 static_cast<KeyType>(priority & BIT64_MATERIAL_PRIORITY_MASK)
181                     << (shift +
182                         BIT64_MATERIAL_RESOURCE_ID_BIT_SIZE +
183                         BIT64_MATERIAL_INSTANCE_ID_BIT_SIZE);
184         }
185 
186         //! @brief 詳細マテリアル ID と描画順の種類を設定します。
SetDetailedMaterialIdAndTranslucencyKind(const Material * material,u32 materialIdShift)187         void SetDetailedMaterialIdAndTranslucencyKind(
188             const Material* material,
189             u32 materialIdShift)
190         {
191             NW_NULL_ASSERT(material);
192 
193             ResMaterial resMaterial = material->GetOriginal();
194             NW_ASSERT(resMaterial.IsValid());
195 
196             // HACK: もっとちゃんとしたマテリアル ID を作るようにする。
197             KeyType id =
198                 ((reinterpret_cast<KeyType>(material->GetOwnerModel()) >> 2) & BIT64_MATERIAL_INSTANCE_ID_MASK) |
199                 (static_cast<KeyType>(resMaterial.GetMaterialId() & BIT64_MATERIAL_RESOURCE_ID_MASK) <<
200                     BIT64_MATERIAL_INSTANCE_ID_BIT_SIZE);
201             m_Key |= (id & BIT64_MATERIAL_ID_MASK) << materialIdShift;
202 
203             ResMaterial shadingParametersResMaterial = material->GetShaderParameterResMaterial();
204             NW_ASSERT(shadingParametersResMaterial.IsValid());
205 
206             ResMaterial::TranslucencyKind translucencyKind =
207                 shadingParametersResMaterial.GetTranslucencyKind();
208 
209             m_Key |= static_cast<KeyType>(translucencyKind & BIT64_TRANSLUCENCY_KIND_MASK)
210                 << BIT64_TRANSLUCENCY_KIND_SHIFT;
211         }
212 
213         //! @brief 簡易マテリアル用の描画優先度を設定します。
SetPriorityForSimpleMaterial(u8 priority,u32 shift)214         void SetPriorityForSimpleMaterial(u8 priority, u32 shift)
215         {
216             m_Key |=
217                 static_cast<KeyType>(priority & BIT64_SIMPLE_MATERIAL_PRIORITY_MASK)
218                     << (shift + BIT64_SIMPLE_MATERIAL_ID_BIT_SIZE);
219         }
220 
221         //! @brief 簡易マテリアル ID と描画順の種類を設定します。
SetSimpleMaterialIdAndTranslucencyKind(const Material * material,u32 materialIdShift)222         void SetSimpleMaterialIdAndTranslucencyKind(
223             const Material* material,
224             u32 materialIdShift)
225         {
226             NW_NULL_ASSERT(material);
227 
228             ResMaterial resMaterial = material->GetOriginal();
229             NW_ASSERT(resMaterial.IsValid());
230 
231             m_Key |= static_cast<KeyType>(resMaterial.GetMaterialId() & BIT64_SIMPLE_MATERIAL_ID_MASK)
232                 << materialIdShift;
233 
234             ResMaterial resBuffer = material->GetBuffer();
235             ResMaterial::TranslucencyKind translucencyKind = (resBuffer.IsValid())
236                 ? resBuffer.GetTranslucencyKind()
237                 : resMaterial.GetTranslucencyKind();
238 
239             m_Key |= (static_cast<KeyType>(translucencyKind)
240                 & BIT64_TRANSLUCENCY_KIND_MASK) << BIT64_TRANSLUCENCY_KIND_SHIFT;
241         }
242 
243         //! @brief 透明性の種類を設定します。
SetTranslucencyKind(ResMaterial::TranslucencyKind translucencyKind)244         void SetTranslucencyKind(ResMaterial::TranslucencyKind translucencyKind)
245         {
246             m_Key |= (static_cast<KeyType>(translucencyKind) & BIT64_TRANSLUCENCY_KIND_MASK)
247                 << BIT64_TRANSLUCENCY_KIND_SHIFT;
248         }
249 
250         //! @brief 深度を設定します。
SetDepth(float depth,u32 shift)251         void SetDepth(float depth, u32 shift)
252         {
253             m_Key |= TDepthQuantizer()(depth) << shift;
254         }
255 
256         //! @brief コマンドを設定します。
SetCommand(RenderCommand * command)257         void SetCommand(RenderCommand* command)
258         {
259             m_Key |= static_cast<KeyType>(1) << BIT64_COMMAND_FLAG_SHIFT;
260             m_Key |= reinterpret_cast<KeyType>(command);
261         }
262 
263         //! @brief キーを取得します。
Key()264         const KeyType Key() const { return m_Key; }
265 
266         //@}
267 
268     private:
269         KeyType m_Key;
270     };
271 
272     //----------------------------------------
273     //! @name 作成/破棄
274     //@{
275 
276     //! @brief キーを設定するコンストラクタです。
BasicRenderElement(const KeyType & key)277     explicit BasicRenderElement(const KeyType& key)
278     : m_Key(key), m_Model(NULL)
279     {
280     }
281 
282     //! @brief メッシュ要素のコンストラクタです。
BasicRenderElement(ResMesh mesh,Model * model)283     BasicRenderElement(ResMesh mesh, Model* model)
284     : m_Key(0), m_Mesh(mesh), m_Model(model)
285     {
286     }
287 
288     //! @brief コピーコンストラクタです。
BasicRenderElement(const BasicRenderElement & element)289     BasicRenderElement(const BasicRenderElement& element)
290     : m_Key(element.m_Key), m_Mesh(element.m_Mesh), m_Model(element.m_Model) {}
291 
292     //! @brief デストラクタです。
~BasicRenderElement()293     ~BasicRenderElement() {}
294 
295     //@}
296 
297     //----------------------------------------
298     //! @name 取得/設定
299     //@{
300 
301     //! @brief 要素の種類がコマンドであれば true を返します。
IsCommand()302     bool IsCommand() const { return this->GetBool(BIT64_COMMAND_FLAG_SHIFT); }
303 
304     //! @brief メッシュを取得します。
GetMesh()305     ResMesh GetMesh() { return m_Mesh; }
306 
307     //! @brief メッシュを取得します。
GetMesh()308     const ResMesh GetMesh() const { return m_Mesh; }
309 
310     //! @brief モデルを取得します。
GetModel()311     Model* GetModel() { return m_Model; }
312 
313     //! @brief モデルを取得します。
GetModel()314     const Model* GetModel() const { return m_Model; }
315 
316     //! @brief コマンドを取得します。
GetCommand()317     RenderCommand* GetCommand()
318     {
319         NW_ASSERT(this->IsCommand());
320         return reinterpret_cast<RenderCommand*>(
321             static_cast<u32>(this->m_Key) & BIT64_COMMAND_MASK);
322     }
323 
324     //! @brief コマンドを取得します。
GetCommand()325     const RenderCommand* GetCommand() const
326     {
327         NW_ASSERT(this->IsCommand());
328         return reinterpret_cast<RenderCommand*>(
329             static_cast<u32>(this->m_Key) & BIT64_COMMAND_MASK);
330     }
331 
332     //! @brief ソート時に比較する値を取得します。
Key()333     KeyType& Key() { return this->m_Key; }
334 
335     //! @brief ソート時に比較する値を取得します。
Key()336     const KeyType& Key() const { return this->m_Key; }
337 
338     //@}
339 
340 private:
GetBool(int shift)341     bool GetBool(int shift) const { return (this->m_Key >> shift) & 0x1; }
342 
343     KeyType m_Key;
344 
345     ResMesh m_Mesh;
346     Model* m_Model;
347 };
348 
349 //---------------------------------------------------------------------------
350 //! @brief 描画ソートを行う際のキーを作成するためのクラスです。
351 //!
352 //! @tparam TKey レンダーキーの型です。
353 //---------------------------------------------------------------------------
354 template<typename TKey>
355 class BasicRenderKeyFactory : public GfxObject
356 {
357 private:
358     NW_DISALLOW_COPY_AND_ASSIGN(BasicRenderKeyFactory);
359 
360 public:
361     //! @brief キーの値となる型です。
362     typedef TKey KeyType;
363 
364     //! @brief 描画単位となるクラスの定義です。
365     typedef BasicRenderElement<KeyType> RenderElementType;
366 
367     //! @brief レンダーキーを作成します。
368     virtual KeyType CreateRenderKey(
369         const RenderElementType& renderElement,
370         float depth,
371         u8 layerId) = 0;
372 
373     //! @brief コマンド用のレンダーキーを作成します。
374     virtual KeyType CreateCommandRenderKey(
375         RenderCommand* command,
376         ResMaterial::TranslucencyKind translucencyKind,
377         u8 priority,
378         u8 layerId) = 0;
379 
380 protected:
381     //! @brief コンストラクタです。
BasicRenderKeyFactory(os::IAllocator * allocator)382     BasicRenderKeyFactory(os::IAllocator* allocator) : GfxObject(allocator) {}
383 
384     //! @brief デストラクタです。
~BasicRenderKeyFactory()385     virtual ~BasicRenderKeyFactory() {}
386 };
387 
388 //---------------------------------------------------------------------------
389 //! @brief マテリアルを優先するレンダーキーファクトリクラスです。
390 //!
391 //! @tparam TKey レンダーキーの型です。
392 //! @tparam TDepthQuantizer 深度値を量子化するための関数オブジェクトの型です。
393 //---------------------------------------------------------------------------
394 template<
395 typename TKey,
396 typename TDepthQuantizer = typename BasicRenderElement<TKey>::Depth24bitQuantizer
397 >
398 class PriorMaterialRenderKeyFactory : public BasicRenderKeyFactory<TKey>
399 {
400 private:
401     NW_DISALLOW_COPY_AND_ASSIGN(PriorMaterialRenderKeyFactory);
402 
403 public:
404     //! @brief キーの値となる型です。
405     typedef TKey KeyType;
406 
407     //! @brief 描画単位となるクラスの定義です。
408     typedef BasicRenderElement<KeyType> RenderElementType;
409 
410     //! @brief キー作成クラスの定義です。
411     typedef typename BasicRenderElement<KeyType>::template Bit64RenderKey<TDepthQuantizer> Bit64RenderKeyType;
412 
413     //----------------------------------------
414     //! @name 作成
415     //@{
416 
417     //! @brief ファクトリを作成します。
418     //!
419     //! @param[in] allocator アロケータです。
420     //!
421     //! @return 作成したファクトリを返します。
422     //!
Create(os::IAllocator * allocator)423     static PriorMaterialRenderKeyFactory* Create(os::IAllocator* allocator)
424     {
425         void* factoryMemory = allocator->Alloc<PriorMaterialRenderKeyFactory>(1);
426         NW_NULL_ASSERT(factoryMemory);
427         return new(factoryMemory) PriorMaterialRenderKeyFactory(allocator);
428     }
429 
430     //@}
431 
432     //! @brief レンダーキーを作成します。
CreateRenderKey(const RenderElementType & renderElement,float depth,u8 layerId)433     virtual KeyType CreateRenderKey(
434         const RenderElementType& renderElement,
435         float depth,
436         u8 layerId)
437     {
438         Bit64RenderKeyType renderKey;
439 
440         renderKey.SetDepth(depth, 0);
441 
442         const ResMesh mesh = renderElement.GetMesh();
443         const Model* model = renderElement.GetModel();
444 
445         if (mesh.IsValid() && model)
446         {
447             const Material* material = model->GetMaterial(mesh.GetMaterialIndex());
448             renderKey.SetDetailedMaterialIdAndTranslucencyKind(
449                 material, RenderElementType::BIT64_DEPTH_BIT_SIZE);
450             renderKey.SetPriorityForDetailedMaterial(
451                 mesh.GetRenderPriority(), RenderElementType::BIT64_DEPTH_BIT_SIZE);
452         }
453 
454         renderKey.SetLayerId(layerId);
455 
456         return renderKey.Key();
457     }
458 
459     //! @brief コマンド用のレンダーキーを作成します。
CreateCommandRenderKey(RenderCommand * command,ResMaterial::TranslucencyKind translucencyKind,u8 priority,u8 layerId)460     virtual KeyType CreateCommandRenderKey(
461         RenderCommand* command,
462         ResMaterial::TranslucencyKind translucencyKind,
463         u8 priority,
464         u8 layerId)
465     {
466         Bit64RenderKeyType renderKey;
467 
468         renderKey.SetLayerId(layerId);
469         renderKey.SetPriorityForSimpleMaterial(
470             priority, RenderElementType::BIT64_DEPTH_BIT_SIZE);
471         renderKey.SetTranslucencyKind(translucencyKind);
472         renderKey.SetCommand(command);
473 
474         return renderKey.Key();
475     }
476 
477 private:
PriorMaterialRenderKeyFactory(os::IAllocator * allocator)478     PriorMaterialRenderKeyFactory(os::IAllocator* allocator)
479     : BasicRenderKeyFactory<KeyType>(allocator)
480     {
481     }
482 };
483 
484 //---------------------------------------------------------------------------
485 //! @brief 深度を優先するレンダーキーファクトリクラスです。
486 //!
487 //! @tparam TKey レンダーキーの型です。
488 //! @tparam TDepthQuantizer 深度値を量子化するための関数オブジェクトの型です。
489 //---------------------------------------------------------------------------
490 template<
491 typename TKey,
492 typename TDepthQuantizer = typename BasicRenderElement<TKey>::Depth24bitQuantizer
493 >
494 class PriorDepthRenderKeyFactory : public BasicRenderKeyFactory<TKey>
495 {
496 private:
497     NW_DISALLOW_COPY_AND_ASSIGN(PriorDepthRenderKeyFactory);
498 
499 public:
500     //! @brief キーの値となる型です。
501     typedef TKey KeyType;
502 
503     //! @brief 描画単位となるクラスの定義です。
504     typedef BasicRenderElement<KeyType> RenderElementType;
505 
506     //! @brief キー作成クラスの定義です。
507     typedef typename BasicRenderElement<KeyType>::template Bit64RenderKey<TDepthQuantizer> Bit64RenderKeyType;
508 
509     //----------------------------------------
510     //! @name 作成
511     //@{
512 
513     //! @brief ファクトリを作成します。
514     //!
515     //! @param[in] allocator アロケータです。
516     //!
517     //! @return 作成したファクトリを返します。
518     //!
Create(os::IAllocator * allocator)519     static PriorDepthRenderKeyFactory* Create(os::IAllocator* allocator)
520     {
521         void* factoryMemory = allocator->Alloc<PriorDepthRenderKeyFactory>(1);
522         NW_NULL_ASSERT(factoryMemory);
523         return new(factoryMemory) PriorDepthRenderKeyFactory(allocator);
524     }
525 
526     //@}
527 
528     //! @brief レンダーキーを作成します。
CreateRenderKey(const RenderElementType & renderElement,float depth,u8 layerId)529     virtual KeyType CreateRenderKey(
530         const RenderElementType& renderElement,
531         float depth,
532         u8 layerId)
533     {
534         Bit64RenderKeyType renderKey;
535 
536         renderKey.SetDepth(depth, RenderElementType::BIT64_SIMPLE_MATERIAL_ID_BIT_SIZE);
537 
538         const ResMesh mesh = renderElement.GetMesh();
539         const Model* model = renderElement.GetModel();
540 
541         if (mesh.IsValid() && model)
542         {
543             const Material* material = model->GetMaterial(mesh.GetMaterialIndex());
544             renderKey.SetSimpleMaterialIdAndTranslucencyKind(material, 0);
545             renderKey.SetPriorityForSimpleMaterial(
546                 mesh.GetRenderPriority(), RenderElementType::BIT64_DEPTH_BIT_SIZE);
547         }
548 
549         renderKey.SetLayerId(layerId);
550 
551         return renderKey.Key();
552     }
553 
554     //! @brief コマンド用のレンダーキーを作成します。
CreateCommandRenderKey(RenderCommand * command,ResMaterial::TranslucencyKind translucencyKind,u8 priority,u8 layerId)555     virtual KeyType CreateCommandRenderKey(
556         RenderCommand* command,
557         ResMaterial::TranslucencyKind translucencyKind,
558         u8 priority,
559         u8 layerId)
560     {
561         Bit64RenderKeyType renderKey;
562 
563         renderKey.SetLayerId(layerId);
564         renderKey.SetPriorityForSimpleMaterial(
565             priority, RenderElementType::BIT64_DEPTH_BIT_SIZE);
566         renderKey.SetTranslucencyKind(translucencyKind);
567         renderKey.SetCommand(command);
568 
569         return renderKey.Key();
570     }
571 
572 private:
PriorDepthRenderKeyFactory(os::IAllocator * allocator)573     PriorDepthRenderKeyFactory(os::IAllocator* allocator)
574     : BasicRenderKeyFactory<KeyType>(allocator)
575     {
576     }
577 };
578 
579 //---------------------------------------------------------------------------
580 //! @brief 深度を最優先するレンダーキーファクトリクラスです。
581 //!
582 //! 描画優先度よりも深度を優先します。
583 //!
584 //! @tparam TKey レンダーキーの型です。
585 //! @tparam TDepthQuantizer 深度値を量子化するための関数オブジェクトの型です。
586 //---------------------------------------------------------------------------
587 template<
588 typename TKey,
589 typename TDepthQuantizer = typename BasicRenderElement<TKey>::Depth24bitQuantizer
590 >
591 class TopPriorDepthRenderKeyFactory : public BasicRenderKeyFactory<TKey>
592 {
593 private:
594     NW_DISALLOW_COPY_AND_ASSIGN(TopPriorDepthRenderKeyFactory);
595 
596 public:
597     //! @brief キーの値となる型です。
598     typedef TKey KeyType;
599 
600     //! @brief 描画単位となるクラスの定義です。
601     typedef BasicRenderElement<KeyType> RenderElementType;
602 
603     //! @brief キー作成クラスの定義です。
604     typedef typename BasicRenderElement<KeyType>::template Bit64RenderKey<TDepthQuantizer> Bit64RenderKeyType;
605 
606     //----------------------------------------
607     //! @name 作成
608     //@{
609 
610     //! @brief ファクトリを作成します。
611     //!
612     //! @param[in] allocator アロケータです。
613     //!
614     //! @return 作成したファクトリを返します。
615     //!
Create(os::IAllocator * allocator)616     static TopPriorDepthRenderKeyFactory* Create(os::IAllocator* allocator)
617     {
618         void* factoryMemory = allocator->Alloc<TopPriorDepthRenderKeyFactory>(1);
619         NW_NULL_ASSERT(factoryMemory);
620         return new(factoryMemory) TopPriorDepthRenderKeyFactory(allocator);
621     }
622 
623     //@}
624 
625     //! @brief レンダーキーを作成します。
CreateRenderKey(const RenderElementType & renderElement,float depth,u8 layerId)626     virtual KeyType CreateRenderKey(
627         const RenderElementType& renderElement,
628         float depth,
629         u8 layerId)
630     {
631         Bit64RenderKeyType renderKey;
632 
633         renderKey.SetDepth(depth,
634             RenderElementType::BIT64_SIMPLE_MATERIAL_ID_BIT_SIZE +
635             RenderElementType::BIT64_SIMPLE_MATERIAL_PRIORITY_BIT_SIZE);
636 
637         const ResMesh mesh = renderElement.GetMesh();
638         const Model* model = renderElement.GetModel();
639 
640         if (mesh.IsValid() && model)
641         {
642             const Material* material = model->GetMaterial(mesh.GetMaterialIndex());
643             renderKey.SetSimpleMaterialIdAndTranslucencyKind(material, 0);
644             renderKey.SetPriorityForSimpleMaterial(mesh.GetRenderPriority(), 0);
645         }
646 
647         renderKey.SetLayerId(layerId);
648 
649         return renderKey.Key();
650     }
651 
652     //! @brief コマンド用のレンダーキーを作成します。
CreateCommandRenderKey(RenderCommand * command,ResMaterial::TranslucencyKind translucencyKind,u8 priority,u8 layerId)653     virtual KeyType CreateCommandRenderKey(
654         RenderCommand* command,
655         ResMaterial::TranslucencyKind translucencyKind,
656         u8 priority,
657         u8 layerId)
658     {
659         Bit64RenderKeyType renderKey;
660 
661         renderKey.SetLayerId(layerId);
662         renderKey.SetPriorityForSimpleMaterial(
663             priority, RenderElementType::BIT64_DEPTH_BIT_SIZE);
664         renderKey.SetTranslucencyKind(translucencyKind);
665         renderKey.SetCommand(command);
666 
667         return renderKey.Key();
668     }
669 
670 private:
TopPriorDepthRenderKeyFactory(os::IAllocator * allocator)671     TopPriorDepthRenderKeyFactory(os::IAllocator* allocator)
672     : BasicRenderKeyFactory<KeyType>(allocator)
673     {
674     }
675 };
676 
677 //----------------------------------------
678 //! @name 描画要素
679 //@{
680 
681 //! @brief 描画ソートを行う際のキーの型です。
682 typedef bit64 RenderKeyType;
683 
684 //! @brief 標準のレンダーエレメントの定義です。
685 typedef BasicRenderElement<RenderKeyType> RenderElement;
686 
687 //! @brief 標準のレンダーキーファクトリーの定義です。
688 typedef BasicRenderKeyFactory<RenderKeyType> RenderKeyFactory;
689 
690 //---------------------------------------------------------------------------
691 //! @brief マテリアル優先のレンダーキーを作成するファクトリを生成します。
692 //!
693 //! @param[in] allocator アロケータです。
694 //!
695 //! @return 生成されたファクトリが返ります。
696 //!
697 //! @sa nw::gfx::BasicRenderQueue::Reset
698 //---------------------------------------------------------------------------
CreatePriorMaterialRenderKeyFactory(os::IAllocator * allocator)699 NW_INLINE RenderKeyFactory* CreatePriorMaterialRenderKeyFactory(
700     os::IAllocator* allocator)
701 {
702     return PriorMaterialRenderKeyFactory<RenderKeyType>::Create(allocator);
703 }
704 
705 //---------------------------------------------------------------------------
706 //! @brief マテリアル優先で奥から描画されるレンダーキーを作成するファクトリを生成します。
707 //!
708 //! @param[in] allocator アロケータです。
709 //!
710 //! @return 生成されたファクトリが返ります。
711 //!
712 //! @sa nw::gfx::BasicRenderQueue::Reset
713 //---------------------------------------------------------------------------
CreatePriorMaterialReverseDepthRenderKeyFactory(os::IAllocator * allocator)714 NW_INLINE RenderKeyFactory* CreatePriorMaterialReverseDepthRenderKeyFactory(
715     os::IAllocator* allocator)
716 {
717     return PriorMaterialRenderKeyFactory<
718         RenderKeyType, RenderElement::ReverseDepth24bitQuantizer>::Create(allocator);
719 }
720 
721 //---------------------------------------------------------------------------
722 //! @brief 深度情報のないマテリアル優先のレンダーキーを作成するファクトリを生成します。
723 //!
724 //! @param[in] allocator アロケータです。
725 //!
726 //! @return 生成されたファクトリが返ります。
727 //!
728 //! @sa nw::gfx::BasicRenderQueue::Reset
729 //---------------------------------------------------------------------------
CreatePriorMaterialAndZeroDepthRenderKeyFactory(os::IAllocator * allocator)730 NW_INLINE RenderKeyFactory* CreatePriorMaterialAndZeroDepthRenderKeyFactory(
731     os::IAllocator* allocator)
732 {
733     return PriorMaterialRenderKeyFactory<
734         RenderKeyType, RenderElement::ZeroQuantizer>::Create(allocator);
735 }
736 
737 //---------------------------------------------------------------------------
738 //! @brief 深度優先のレンダーキーを作成するファクトリを生成します。
739 //!
740 //! @param[in] allocator アロケータです。
741 //!
742 //! @return 生成されたファクトリが返ります。
743 //!
744 //! @sa nw::gfx::BasicRenderQueue::Reset
745 //---------------------------------------------------------------------------
CreatePriorDepthRenderKeyFactory(os::IAllocator * allocator)746 NW_INLINE RenderKeyFactory* CreatePriorDepthRenderKeyFactory(
747     os::IAllocator* allocator)
748 {
749     return PriorDepthRenderKeyFactory<RenderKeyType>::Create(allocator);
750 }
751 
752 //---------------------------------------------------------------------------
753 //! @brief 深度優先で奥から描画されるレンダーキーを作成するファクトリを生成します。
754 //!
755 //! @param[in] allocator アロケータです。
756 //!
757 //! @return 生成されたファクトリが返ります。
758 //!
759 //! @sa nw::gfx::BasicRenderQueue::Reset
760 //---------------------------------------------------------------------------
CreatePriorDepthReverseDepthRenderKeyFactory(os::IAllocator * allocator)761 NW_INLINE RenderKeyFactory* CreatePriorDepthReverseDepthRenderKeyFactory(
762     os::IAllocator* allocator)
763 {
764     return PriorDepthRenderKeyFactory<
765         RenderKeyType, RenderElement::ReverseDepth24bitQuantizer>::Create(allocator);
766 }
767 
768 //---------------------------------------------------------------------------
769 //! @brief 深度最優先のレンダーキーを作成するファクトリを生成します。
770 //!
771 //! @param[in] allocator アロケータです。
772 //!
773 //! @return 生成されたファクトリが返ります。
774 //!
775 //! @sa nw::gfx::BasicRenderQueue::Reset
776 //---------------------------------------------------------------------------
CreateTopPriorDepthRenderKeyFactory(os::IAllocator * allocator)777 NW_INLINE RenderKeyFactory* CreateTopPriorDepthRenderKeyFactory(
778     os::IAllocator* allocator)
779 {
780     return TopPriorDepthRenderKeyFactory<RenderKeyType>::Create(allocator);
781 }
782 
783 //---------------------------------------------------------------------------
784 //! @brief 深度最優先で奥から描画されるレンダーキーを作成するファクトリを生成します。
785 //!
786 //! @param[in] allocator アロケータです。
787 //!
788 //! @return 生成されたファクトリが返ります。
789 //!
790 //! @sa nw::gfx::BasicRenderQueue::Reset
791 //---------------------------------------------------------------------------
CreateTopPriorDepthReverseDepthRenderKeyFactory(os::IAllocator * allocator)792 NW_INLINE RenderKeyFactory* CreateTopPriorDepthReverseDepthRenderKeyFactory(
793     os::IAllocator* allocator)
794 {
795     return TopPriorDepthRenderKeyFactory<
796         RenderKeyType, RenderElement::ReverseDepth24bitQuantizer>::Create(allocator);
797 }
798 //@}
799 
800 } // namespace gfx
801 } // namespace nw
802 
803 #endif // NW_GFX_RENDERELEMENT_H_
804