1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Material.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_MATERIAL_H_
19 #define NW_GFX_MATERIAL_H_
20 
21 #include <nw/gfx/gfx_SceneObject.h>
22 #include <nw/ut/ut_RuntimeTypeInfo.h>
23 #include <nw/ut/ut_MoveArray.h>
24 #include <nw/gfx/gfx_ShaderProgram.h>
25 
26 namespace nw
27 {
28 namespace gfx
29 {
30 
31 class Model;
32 class AnimGroup;
33 
34 //---------------------------------------------------------------------------
35 //! @brief        マテリアルを表すクラスです。
36 //!
37 //! マテリアルに対して、アニメーション後に生成時の状態に戻したい場合、Bufferを使用する必要があります。
38 //---------------------------------------------------------------------------
39 class Material : public SceneObject
40 {
41 private:
42     NW_DISALLOW_COPY_AND_ASSIGN(Material);
43 
44 public:
45     NW_UT_RUNTIME_TYPEINFO;
46 
47     //----------------------------------------
48     //! @name 作成
49     //@{
50 
51     //! @brief        リソースからマテリアルを生成します。
52     //!
53     //! @param[in]    resource リソースです。
54     //! @param[in]    bufferCount 生成するマテリアルバッファの数です。
55     //! @param[in]    parent マテリアルの親となるモデルクラスです。
56     //! @param[in]    allocator アロケータです。
57     //!
58     //! @return       生成されたマテリアルです。
59     //!
60     static Material* Create(
61         ResMaterial resource,
62         s32 bufferCount,
63         Model* parent,
64         os::IAllocator* allocator);
65 
66     //! @brief        生成時に必要なメモリサイズを取得します。
67     //!
68     //! @param[in]    resource リソースです。
69     //! @param[in]    bufferCount 生成するマテリアルバッファの数です。
70     //! @param[in]    parent マテリアルの親となるモデルクラスです。
71     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
72     static size_t GetMemorySize(
73         ResMaterial resource,
74         s32 bufferCount,
75         bit32 bufferOption,
76         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
77     {
78         os::MemorySizeCalculator size(alignment);
79 
80         GetMemorySizeInternal(&size, resource, bufferCount, bufferOption);
81 
82         return size.GetSizeWithPadding(alignment);
83     }
84 
85 
86     //! @details :private
87     static void GetMemorySizeInternal(
88         os::MemorySizeCalculator* pSize,
89         ResMaterial resource,
90         s32 bufferCount,
91         bit32 bufferOption);
92 
93     //@}
94 
95     //----------------------------------------
96     //! @name 取得/設定
97     //@{
98 
99     //! @brief オリジナルリソースを取得します。
GetOriginal()100     ResMaterial GetOriginal()
101     {
102         return ResStaticCast<ResMaterial>(this->GetResSceneObject());
103     }
104 
105     //! @brief オリジナルリソースを取得します。
GetOriginal()106     const ResMaterial GetOriginal() const
107     {
108         return ResStaticCast<ResMaterial>(this->GetResSceneObject());
109     }
110 
111     //! @brief 所有者となるモデルを取得します。
112     //!
113     //! @return マテリアルの所有者のモデルです。
114     //!
GetOwnerModel()115     Model* GetOwnerModel()
116     {
117         return this->m_Owner;
118     }
119 
120     //! @brief 所有者となるモデルを取得します。
121     //!
122     //! @return マテリアルの所有者のモデルです。
123     //!
GetOwnerModel()124     const Model* GetOwnerModel() const
125     {
126         return this->m_Owner;
127     }
128 
129     //! @brief リソースを設定します。
130     //!
131     //! @param[in] description シェーダプログラムの詳細設定です。
132     //!
SetDescription(ResShaderProgramDescription description)133     void SetDescription(ResShaderProgramDescription description) { m_ProgramDescription = description; }
134 
135     //! @brief リソースを取得します。
136     //!
137     //! @return シェーダプログラムの詳細設定です。
138     //!
GetDescription()139     const ResShaderProgramDescription GetDescription() const { return m_ProgramDescription; }
140 
141     //@}
142 
143     //----------------------------------------
144     //! @name バッファオプション関連
145     //@{
146 
147     //! @brief バッファの数を取得します。
GetBufferCount()148     int GetBufferCount() const
149     {
150         return this->m_Buffers.size();
151     }
152 
153     //! @brief バッファを取得します。
GetBuffer()154     ResMaterial GetBuffer()
155     {
156         bool hasBuffer = (0 < m_BufferCount);
157 
158         if (hasBuffer)
159         {
160             return this->m_Buffers[0];
161         }
162         else
163         {
164             return ResMaterial(NULL);
165         }
166     }
167 
168     //! バッファを取得します。
GetBuffer()169     const ResMaterial GetBuffer() const
170     {
171         bool hasBuffer = (0 < m_BufferCount);
172 
173         if (hasBuffer)
174         {
175             return this->m_Buffers[0];
176         }
177         else
178         {
179             return ResMaterial(NULL);
180         }
181     }
182 
183     //! 有効なシェーダーパラメータが取得できるマテリアルを取得します。
GetShaderParameterResMaterial()184     ResMaterial& GetShaderParameterResMaterial() { return m_ShaderParameterResMaterial; }
185 
186     //! 有効なシェーダーパラメータが取得できるマテリアルを取得します。
GetShaderParameterResMaterial()187     const ResMaterial& GetShaderParameterResMaterial() const { return m_ShaderParameterResMaterial; }
188 
189     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetShadingParameterResMaterial()190     ResMaterial& GetShadingParameterResMaterial() { return m_ShadingParameterResMaterial; }
191 
192     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetShadingParameterResMaterial()193     const ResMaterial& GetShadingParameterResMaterial() const { return m_ShadingParameterResMaterial; }
194 
195     //! 有効なマテリアルカラーが取得できるマテリアルを取得します。
GetMaterialColorResMaterial()196     ResMaterial& GetMaterialColorResMaterial() { return m_MaterialColorResMaterial; }
197 
198     //! 有効なマテリアルカラーが取得できるマテリアルを取得します。
GetMaterialColorResMaterial()199     const ResMaterial& GetMaterialColorResMaterial() const { return m_MaterialColorResMaterial; }
200 
201     //! 有効なラスタライゼーションが取得できるマテリアルを取得します。
GetRasterizationResMaterial()202     ResMaterial& GetRasterizationResMaterial() { return m_RasterizationResMaterial; }
203 
204     //! 有効なラスタライゼーションが取得できるマテリアルを取得します。
GetRasterizationResMaterial()205     const ResMaterial& GetRasterizationResMaterial() const { return m_RasterizationResMaterial; }
206 
207     //! 有効なテクスチャコーディネータが取得できるマテリアルを取得します。
GetTextureCoordinatorResMaterial()208     ResMaterial& GetTextureCoordinatorResMaterial() { return m_TextureCoordinatorResMaterial; }
209 
210     //! 有効なテクスチャコーディネータが取得できるマテリアルを取得します。
GetTextureCoordinatorResMaterial()211     const ResMaterial& GetTextureCoordinatorResMaterial() const { return m_TextureCoordinatorResMaterial; }
212 
213     //! 有効なテクスチャマッパーが取得できるマテリアルを取得します。
GetTextureMapperResMaterial()214     ResMaterial& GetTextureMapperResMaterial() { return m_TextureMapperResMaterial; }
215 
216     //! 有効なテクスチャマッパーが取得できるマテリアルを取得します。
GetTextureMapperResMaterial()217     const ResMaterial& GetTextureMapperResMaterial() const { return m_TextureMapperResMaterial; }
218 
219     //! 有効なフラグメントライティングが取得できるマテリアルを取得します。
GetFragmentLightingResMaterial()220     ResMaterial& GetFragmentLightingResMaterial() { return m_FragmentLightingResMaterial; }
221 
222     //! 有効なフラグメントライティングが取得できるマテリアルを取得します。
GetFragmentLightingResMaterial()223     const ResMaterial& GetFragmentLightingResMaterial() const { return m_FragmentLightingResMaterial; }
224 
225     //! 有効なフラグメントライティングテーブルが取得できるマテリアルを取得します。
GetFragmentLightingTableResMaterial()226     ResMaterial& GetFragmentLightingTableResMaterial() { return m_FragmentLightingTableResMaterial; }
227 
228     //! 有効なフラグメントライティングテーブルが取得できるマテリアルを取得します。
GetFragmentLightingTableResMaterial()229     const ResMaterial& GetFragmentLightingTableResMaterial() const { return m_FragmentLightingTableResMaterial; }
230 
231     //! 有効なテクスチャコンバイナが取得できるマテリアルを取得します。
GetTextureCombinerResMaterial()232     ResMaterial& GetTextureCombinerResMaterial() { return m_TextureCombinerResMaterial; }
233 
234     //! 有効なテクスチャコンバイナが取得できるマテリアルを取得します。
GetTextureCombinerResMaterial()235     const ResMaterial& GetTextureCombinerResMaterial() const { return m_TextureCombinerResMaterial; }
236 
237     //! 有効なアルファテストが取得できるマテリアルを取得します。
GetAlphaTestResMaterial()238     ResMaterial& GetAlphaTestResMaterial() { return m_AlphaTestResMaterial; }
239 
240     //! 有効なアルファテストが取得できるマテリアルを取得します。
GetAlphaTestResMaterial()241     const ResMaterial& GetAlphaTestResMaterial() const { return m_AlphaTestResMaterial; }
242 
243     //! 有効なフラグメントオペレーションが取得できるマテリアルを取得します。
GetFragmentOperationResMaterial()244     ResMaterial& GetFragmentOperationResMaterial() { return m_FragmentOperationResMaterial; }
245 
246     //! 有効なフラグメントオペレーションが取得できるマテリアルを取得します。
GetFragmentOperationResMaterial()247     const ResMaterial& GetFragmentOperationResMaterial() const { return m_FragmentOperationResMaterial; }
248 
249     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetSceneEnvironmentResMaterial()250     ResMaterial& GetSceneEnvironmentResMaterial() { return m_SceneEnvironmentResMaterial; }
251 
252     //! 有効なシーン環境の設定が取得できるマテリアルを取得します。
GetSceneEnvironmentResMaterial()253     const ResMaterial& GetSceneEnvironmentResMaterial() const { return m_SceneEnvironmentResMaterial; }
254 
255     //@}
256 
257 protected:
258     //----------------------------------------
259     //! @name コンストラクタ/デストラクタ
260     //@{
261 
262     //! コンストラクタです。
263     Material(
264         os::IAllocator* allocator,
265         ResMaterial resMaterial,
266         s32 bufferCount,
267         Model* parent);
268 
269     //! デストラクタです。
270     virtual ~Material();
271 
272     //@}
273 
274     struct ResMaterialDestroyer : public std::unary_function<ResMaterial, void>
275     {
m_AllocatorResMaterialDestroyer276         ResMaterialDestroyer(os::IAllocator* allocator = 0) : m_Allocator(allocator)
277         {}
operatorResMaterialDestroyer278         result_type operator()(argument_type data)
279         {
280             DestroyResMaterial(m_Allocator, data);
281         }
282 
283         os::IAllocator* m_Allocator;
284     };
285 
286 private:
287 
288     //! @brief メンバのメモリ確保と初期化を行います。
289     Result Initialize(os::IAllocator* allocator);
290 
291     //---------------------------------------------------------------------------
292     //! @brief        バッファを作成します。
293     //!
294     //! @param[in]    allocator アロケータです。
295     //---------------------------------------------------------------------------
296     Result CreateBuffers(os::IAllocator* allocator);
297 
298     //---------------------------------------------------------------------------
299     //! @brief        ResMaterialをコピーします。
300     //!
301     //! @param[in]    allocator        アロケータです。
302     //! @param[in]    bufferOption     生成オプションです。
303     //!
304     //! @return コピーしたマテリアルとコピー結果を表すフラグを返します。
305     //---------------------------------------------------------------------------
306     ::std::pair<ResMaterial, Result> CopyResMaterial(
307         os::IAllocator* allocator,
308         bit32 bufferOption);
309 
310     //---------------------------------------------------------------------------
311     //! @brief        ResMaterial のリソースを破棄します。
312     //!
313     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
314     //! @param[in]    resMaterial      解放するリソースです。
315     //---------------------------------------------------------------------------
316     static void DestroyResMaterial(os::IAllocator* allocator, ResMaterial resMaterial);
317 
318     //---------------------------------------------------------------------------
319     //! @brief        ResFragmentShader のリソースを破棄します。
320     //!
321     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
322     //! @param[in]    resFragmentShader 解放するリソースです。
323     //---------------------------------------------------------------------------
324     static void DestroyResFragmentShader(
325         os::IAllocator* allocator,
326         ResFragmentShader resFragmentShader);
327 
328     //---------------------------------------------------------------------------
329     //! @brief        ResShaderParameter のリソースを破棄します。
330     //!
331     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
332     //! @param[in]    resShaderParameter 解放するリソースです。
333     //---------------------------------------------------------------------------
334     static void DestroyResShaderParameter(
335         os::IAllocator* allocator,
336         ResShaderParameter resShaderParameter);
337 
338     //---------------------------------------------------------------------------
339     //! @brief        リソースからフラグメントライティングテーブルをコピーします。
340     //!
341     //! @param[in]    allocator アロケータです。
342     //! @param[in]    resFragmentLightingTable オリジナルのデータです。
343     //---------------------------------------------------------------------------
344     ::std::pair<ResFragmentLightingTable, Result> CopyResFragmentLightingTable(
345         os::IAllocator* allocator,
346         ResFragmentLightingTable resFragmentLightingTable);
347 
348     //---------------------------------------------------------------------------
349     //! @brief        リソースからライティング参照テーブルをコピーします。
350     //!
351     //! @param[in]    allocator アロケータです。
352     //! @param[in]    resLightingLookupTable オリジナルのデータです。
353     //---------------------------------------------------------------------------
354     ::std::pair<ResLightingLookupTable, Result> CopyResLightingLookupTable(
355         os::IAllocator* allocator,
356         ResLightingLookupTable resLightingLookupTable);
357 
358     //! @brief アニメーション対象のリソースを取得します。
359     //!
360     //! @param objectType 対応するタイプです。
361     //! @return バッファがあればバッファを、無ければオリジナルを返します。
362     //!
GetActiveResource(u32 objectType)363     ResMaterial GetActiveResource(u32 objectType)
364     {
365         return (CanUseBuffer(objectType)) ? GetBuffer() : GetOriginal();
366     }
367 
368     //! @brief アニメーションに登録するモデルデータのポインタを取得します。
369     void* GetAnimTargetObject(const anim::ResAnimGroupMember& anim, const ResMaterial resMaterial);
370 
371     // アニメーションのオブジェクトタイプに対応するバッファーが存在するかどうかを取得します。
372     bool CanUseBuffer(u32 objectType) const;
373 
374     typedef ut::MoveArray<ResMaterial> ResMaterialArray;
375 
376     ResMaterialArray m_Buffers;
377     Model* m_Owner;
378     ResShaderProgramDescription m_ProgramDescription;
379     s32 m_BufferCount;
380 
381     ResMaterial m_ShaderParameterResMaterial;
382     ResMaterial m_ShadingParameterResMaterial;
383     ResMaterial m_MaterialColorResMaterial;
384     ResMaterial m_RasterizationResMaterial;
385     ResMaterial m_TextureCoordinatorResMaterial;
386     ResMaterial m_TextureMapperResMaterial;
387     ResMaterial m_FragmentLightingResMaterial;
388     ResMaterial m_FragmentLightingTableResMaterial;
389     ResMaterial m_TextureCombinerResMaterial;
390     ResMaterial m_AlphaTestResMaterial;
391     ResMaterial m_FragmentOperationResMaterial;
392     ResMaterial m_SceneEnvironmentResMaterial;
393 
394     // TODO: CanUseBufferを非公開にするために暫定で対処しています。
395     friend class Model;
396 };
397 
398 //! @brief マテリアルの Array の定義です。
399 typedef ut::MoveArray<Material*> MaterialArray;
400 
401 } // namespace gfx
402 } // namespace nw
403 
404 #endif // NW_GFX_MATERIAL_H_
405