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