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