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