1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Material.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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: 29206 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/gfx_Material.h>
19 #include <nw/gfx/gfx_Model.h>
20 #include <nw/gfx/res/gfx_ResMaterial.h>
21 #include <nw/gfx/res/gfx_ResShader.h>
22 #include <nw/gfx/gfx_AnimObject.h>
23 
24 namespace
25 {
GetAvailableResMaterial(nw::gfx::Material * material,nw::gfx::Model::BufferOption bufferOption)26 nw::gfx::ResMaterial GetAvailableResMaterial(
27     nw::gfx::Material* material, nw::gfx::Model::BufferOption bufferOption)
28 {
29     return nw::ut::CheckFlag(material->GetOwnerModel()->GetBufferOption(), bufferOption)
30         ? material->GetBuffer()
31         : material->GetOriginal();
32 }
33 }
34 
35 namespace nw
36 {
37 namespace gfx
38 {
39 
40 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Material, SceneObject);
41 
42 //----------------------------------------
Material(os::IAllocator * allocator,ResMaterial resMaterial,s32 bufferCount,Model * owner)43 Material::Material(
44     os::IAllocator* allocator,
45     ResMaterial resMaterial,
46     s32 bufferCount,
47     Model* owner)
48 : SceneObject(
49     allocator,
50     resMaterial),
51     m_Owner(owner),
52     m_BufferCount(bufferCount)
53 {
54     ResBinaryShader resShader = resMaterial.GetShader().Dereference();
55 
56     NW_ASSERT(resShader.IsValid());
57     m_ProgramDescription =
58         resShader.GetDescriptions(resMaterial.GetShaderProgramDescriptionIndex());
59 }
60 
61 //----------------------------------------
62 Material*
Create(ResMaterial resource,s32 bufferCount,Model * parent,os::IAllocator * allocator)63 Material::Create(
64     ResMaterial resource,
65     s32 bufferCount,
66     Model* parent,
67     os::IAllocator* allocator
68 )
69 {
70     NW_NULL_ASSERT(allocator);
71     NW_ASSERT(resource.IsValid());
72 
73     // マテリアルバッファは1つのみ作成可能です。
74     NW_ASSERTMSG(bufferCount <= 1, "Material Buffer Count must be 0 or 1.");
75 
76     void* memory = allocator->Alloc(sizeof(Material));
77     if (memory == NULL)
78     {
79         return NULL;
80     }
81 
82     Material* material = new(memory) Material(
83         allocator,
84         resource,
85         bufferCount,
86         parent);
87 
88     Result result = material->Initialize(allocator);
89     if (result.IsSuccess())
90     {
91         material->m_ShaderParameterResMaterial =
92             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADER_PARAMETER);
93         material->m_ShadingParameterResMaterial =
94             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADING_PARAMETER);
95         material->m_MaterialColorResMaterial =
96             GetAvailableResMaterial(material, Model::FLAG_BUFFER_MATERIAL_COLOR);
97         material->m_RasterizationResMaterial =
98             GetAvailableResMaterial(material, Model::FLAG_BUFFER_RASTERIZATION);
99         material->m_TextureCoordinatorResMaterial =
100             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
101         material->m_TextureMapperResMaterial =
102             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_MAPPER);
103         material->m_FragmentLightingResMaterial =
104             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING);
105         material->m_FragmentLightingTableResMaterial =
106             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE);
107         material->m_TextureCombinerResMaterial =
108             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COMBINER);
109         material->m_AlphaTestResMaterial =
110             GetAvailableResMaterial(material, Model::FLAG_BUFFER_ALPHA_TEST);
111         material->m_FragmentOperationResMaterial =
112             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
113         material->m_SceneEnvironmentResMaterial =
114             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SCENE_ENVIRONMENT);
115         return material;
116     }
117     else
118     {
119         SafeDestroy(material);
120         return NULL;
121     }
122 }
123 
124 //----------------------------------------
125 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResMaterial resMaterial,s32 bufferCount,bit32 bufferOption)126 Material::GetMemorySizeInternal(
127     os::MemorySizeCalculator* pSize,
128     ResMaterial resMaterial,
129     s32 bufferCount,
130     bit32 bufferOption)
131 {
132     os::MemorySizeCalculator& size = *pSize;
133 
134     // Material::Create
135     size += sizeof(Material);
136 
137     // Material::Initialize
138 
139     // Material::CreateBuffers
140     size += sizeof(ResMaterial) * bufferCount;
141     if (bufferCount > 0)
142     {
143         // TODO: 要検証
144         // Material::CopyResMaterial
145         os::MemorySizeCalculator bufferSize(size.GetAlignment());
146 
147         bufferSize += sizeof(ResMaterialData);
148 
149         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
150         {
151             bufferSize += sizeof(ut::Offset) * resMaterial.GetShaderParametersCount();
152 
153             for (int i = 0; i < resMaterial.GetShaderParametersCount(); ++i)
154             {
155                 const int parameterLength = resMaterial.GetShaderParameters(i).GetParameterLength();
156 
157                 bufferSize += sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1);
158             }
159         }
160 
161         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
162         {
163             for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
164             {
165                 ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
166                 if (resTextureMapper.IsValid())
167                 {
168                     resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
169                 }
170             }
171         }
172 
173         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
174         {
175             ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
176             if (resTextureMapper.IsValid())
177             {
178                 resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
179             }
180         }
181 
182         if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
183         {
184             if (resMaterial.GetFragmentShader().IsValid())
185             {
186                 bufferSize += sizeof(ResFragmentShaderData);
187 
188                 if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
189                 {
190                     // Material::CopyResFragmentLightingTable
191                     ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
192 
193                     if (resFragmentShader.GetFragmentLightingTable().IsValid())
194                     {
195                         ResFragmentLightingTable resFragmentLightingTable =
196                             resFragmentShader.GetFragmentLightingTable();
197 
198                         bufferSize += sizeof(ResFragmentLightingTableData);
199                         if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
200                         {
201                             bufferSize += sizeof(ResLightingLookupTableData);
202                             bufferSize += sizeof(ResReferenceLookupTableData);
203                         }
204                         if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
205                         {
206                             bufferSize += sizeof(ResLightingLookupTableData);
207                             bufferSize += sizeof(ResReferenceLookupTableData);
208                         }
209                         if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
210                         {
211                             bufferSize += sizeof(ResLightingLookupTableData);
212                             bufferSize += sizeof(ResReferenceLookupTableData);
213                         }
214                         if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
215                         {
216                             bufferSize += sizeof(ResLightingLookupTableData);
217                             bufferSize += sizeof(ResReferenceLookupTableData);
218                         }
219                         if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
220                         {
221                             bufferSize += sizeof(ResLightingLookupTableData);
222                             bufferSize += sizeof(ResReferenceLookupTableData);
223                         }
224                         if (resFragmentLightingTable.GetFresnelSampler().IsValid())
225                         {
226                             bufferSize += sizeof(ResLightingLookupTableData);
227                             bufferSize += sizeof(ResReferenceLookupTableData);
228                         }
229                     }
230                 }
231             }
232         }
233 
234         bufferSize *= bufferCount;
235         size += bufferSize.GetSizeWithPadding(size.GetAlignment());
236     }
237 }
238 
239 //----------------------------------------
~Material()240 Material::~Material()
241 {
242     std::for_each(
243         m_Buffers.begin(), m_Buffers.end(), ResMaterialDestroyer(&this->GetAllocator()));
244 }
245 
246 //----------------------------------------
247 bool
CanUseBuffer(u32 objectType) const248 Material::CanUseBuffer(u32 objectType) const
249 {
250     if (0 < m_BufferCount)
251     {
252         bit32 option = this->GetOwnerModel()->GetBufferOption();
253         switch (objectType)
254         {
255         case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
256             return ut::CheckFlag(option, Model::FLAG_BUFFER_MATERIAL_COLOR);
257         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
258             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
259         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
260             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
261         case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
262             return ut::CheckFlag(option, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
263         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
264             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
265         default:
266             NW_ASSERT(false);
267         }
268     }
269     return false;
270 }
271 
272 //-----------------------------------------
273 Result
CreateBuffers(os::IAllocator * allocator)274 Material::CreateBuffers(os::IAllocator* allocator)
275 {
276     Result result = INITIALIZE_RESULT_OK;
277 
278     NW_NULL_ASSERT(this->m_Owner);
279     bit32 bufferOption = m_Owner->GetBufferOption();
280 
281     if (m_BufferCount != 0)
282     {
283         void* memory = allocator->Alloc(sizeof(ResMaterial) * m_BufferCount);
284         if (memory == NULL)
285         {
286             result |= Result::MASK_FAIL_BIT;
287         }
288 
289         NW_ENSURE_AND_RETURN(result);
290 
291         m_Buffers = ResMaterialArray(memory, m_BufferCount, allocator);
292 
293         for (int bufferIndex = 0; bufferIndex < m_BufferCount; bufferIndex++)
294         {
295             NW_ENSURE_AND_RETURN(result);
296             ::std::pair<ResMaterial, Result> copyResult = this->CopyResMaterial(allocator, bufferOption);
297 
298             if (copyResult.second.IsSuccess())
299             {
300                 m_Buffers.PushBackFast(copyResult.first);
301             }
302             else
303             {
304                 DestroyResMaterial(allocator, copyResult.first);
305                 result |= Result::MASK_FAIL_BIT;
306             }
307         }
308     }
309 
310     return result;
311 }
312 
313 //-----------------------------------------
314 ::std::pair<ResMaterial, Result>
CopyResMaterial(os::IAllocator * allocator,bit32 bufferOption)315 Material::CopyResMaterial(
316     os::IAllocator* allocator,
317     bit32 bufferOption)
318 {
319     Result result = INITIALIZE_RESULT_OK;
320 
321     ResMaterial resMaterial = this->GetOriginal();
322 
323     void* materialMemory = allocator->Alloc(sizeof(ResMaterialData));
324     if (materialMemory == NULL)
325     {
326         result |= Result::MASK_FAIL_BIT;
327         return ::std::make_pair(ResMaterial(NULL), result);
328     }
329 
330     ResMaterialData* buffer =
331         new(materialMemory) ResMaterialData(this->GetOriginal().ref());
332 
333     ResMaterial copyMaterial = ResMaterial(buffer);
334 
335     // 判定に用いるために NULL でクリアしておく
336     buffer->toName.set_ptr(NULL);
337     buffer->toShader.set_ptr(NULL);
338     buffer->m_ShaderParametersTableCount = 0;
339     buffer->toShaderParametersTable.set_ptr(NULL);
340     buffer->toTextureMappers[0].set_ptr(NULL);
341     buffer->toTextureMappers[1].set_ptr(NULL);
342     buffer->toTextureMappers[2].set_ptr(NULL);
343     buffer->toProceduralTextureMapper.set_ptr(NULL);
344     buffer->toFragmentShader.set_ptr(NULL);
345 
346     // ハッシュ無効化
347     buffer->m_AlphaTestHash = 0x0;
348     buffer->m_FragmentLightingHash = 0x0;
349     buffer->m_FragmentLightingTableHash = 0x0;
350     buffer->m_FragmentLightingTableParametersHash = 0x0;
351     buffer->m_FragmentOperationHash = 0x0;
352     buffer->m_MaterialColorHash = 0x0;
353     buffer->m_RasterizationHash = 0x0;
354     buffer->m_ShaderParametersHash = 0x0;
355     buffer->m_ShadingParameterHash = 0x0;
356     buffer->m_TextureCombinersHash = 0x0;
357     buffer->m_TextureCoordinatorsHash = 0x0;
358     buffer->m_TextureMappersHash = 0x0;
359     buffer->m_TextureSamplersHash = 0x0;
360 
361     // シェーダーパラメータのコピー
362     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
363     {
364         buffer->m_ShaderParametersTableCount = resMaterial.GetShaderParametersCount();
365 
366         ut::Offset* offsets = NULL;
367         if (buffer->m_ShaderParametersTableCount != 0)
368         {
369             offsets = allocator->AllocAndConstruct<ut::Offset>(resMaterial.GetShaderParametersCount());
370 
371             if (offsets == NULL)
372             {
373                 result |= Result::MASK_FAIL_BIT;
374                 return ::std::make_pair(copyMaterial, result);
375             }
376 
377             buffer->toShaderParametersTable.set_ptr(offsets);
378         }
379 
380         // メモリ解放を容易にするために NULL で初期化しておく
381         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
382         {
383             offsets[i].set_ptr(NULL);
384         }
385 
386         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
387         {
388             ResShaderParameter resShaderParameter = resMaterial.GetShaderParameters(i);
389             ResShaderParameterValue resShaderParameterValue = resShaderParameter.GetParameter();
390 
391             const int parameterLength = resShaderParameter.GetParameterLength();
392 
393             // sizeof(ResShaderParameterData)で32ビット分の Value の領域が確保されるので-1をする。
394             void* parameterMemory = allocator->Alloc(sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1));
395             if (parameterMemory == NULL)
396             {
397                 result |= Result::MASK_FAIL_BIT;
398                 return ::std::make_pair(copyMaterial, result);
399             }
400 
401             ResShaderParameterData* shaderParameter = static_cast<ResShaderParameterData*>(parameterMemory);
402             *shaderParameter = ResShaderParameterData(resShaderParameter.ref());
403 
404             for (int j = 0; j < parameterLength; ++j)
405             {
406                 shaderParameter->m_Parameter.m_Value[j] = resShaderParameterValue.ref().m_Value[j];
407             }
408 
409             offsets[i].set_ptr(shaderParameter);
410         }
411     }
412 
413     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
414     {
415         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
416         {
417             ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
418             if (resTextureMapper.IsValid())
419             {
420                 ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
421 
422                 if (!textureMapper.IsValid())
423                 {
424                     result |= Result::MASK_FAIL_BIT;
425                     return ::std::make_pair(copyMaterial, result);
426                 }
427 
428                 buffer->toTextureMappers[i].set_ptr(textureMapper.ptr());
429             }
430         }
431     }
432 
433     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
434     {
435         ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
436         if (resTextureMapper.IsValid())
437         {
438             ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
439 
440             if (!textureMapper.IsValid())
441             {
442                 result |= Result::MASK_FAIL_BIT;
443                 return ::std::make_pair(copyMaterial, result);
444             }
445 
446             buffer->toProceduralTextureMapper.set_ptr(textureMapper.ptr());
447         }
448     }
449 
450     if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
451     {
452         ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
453         if (resFragmentShader.IsValid())
454         {
455             void* shaderMemory = allocator->Alloc(sizeof(ResFragmentShaderData));
456 
457             if (shaderMemory == NULL)
458             {
459                 result |= Result::MASK_FAIL_BIT;
460                 return ::std::make_pair(copyMaterial, result);
461             }
462 
463             ResFragmentShaderData* fragmentShader =
464                 new(shaderMemory) ResFragmentShaderData(resFragmentShader.ref());
465 
466             buffer->toFragmentShader.set_ptr(fragmentShader);
467 
468             // 判定に用いるために NULL でクリアしておく
469             fragmentShader->toFragmentLightingTable.set_ptr(NULL);
470 
471             if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
472             {
473                 ResFragmentLightingTable resFragmentLightingTable =
474                     resFragmentShader.GetFragmentLightingTable();
475                 if (resFragmentLightingTable.IsValid())
476                 {
477                     ::std::pair<ResFragmentLightingTable, Result> copyResult =
478                         this->CopyResFragmentLightingTable(allocator, resFragmentLightingTable);
479 
480                     fragmentShader->toFragmentLightingTable.set_ptr(copyResult.first.ptr());
481 
482                     if (copyResult.second.IsFailure())
483                     {
484                         result |= Result::MASK_FAIL_BIT;
485                         return ::std::make_pair(copyMaterial, result);
486                     }
487                 }
488             }
489         }
490     }
491 
492     return ::std::make_pair(copyMaterial, result);
493 }
494 
495 //-----------------------------------------
496 void
DestroyResMaterial(os::IAllocator * allocator,ResMaterial resMaterial)497 Material::DestroyResMaterial(os::IAllocator* allocator, ResMaterial resMaterial)
498 {
499     NW_NULL_ASSERT( allocator );
500     if (resMaterial.IsValid())
501     {
502         resMaterial.Cleanup();
503 
504         DestroyResFragmentShader(allocator, resMaterial.GetFragmentShader());
505 
506         if (resMaterial.GetProceduralTextureMapper().IsValid())
507         {
508             resMaterial.GetProceduralTextureMapper().DestroyDynamic();
509         }
510 
511         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
512         {
513             if (resMaterial.GetTextureMappers(i).IsValid())
514             {
515                 resMaterial.GetTextureMappers(i).DestroyDynamic();
516             }
517         }
518 
519         // シェーダーパラメータのメモリ解放
520         if (resMaterial.ref().toShaderParametersTable.to_ptr() != NULL)
521         {
522             for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
523             {
524                 DestroyResShaderParameter(allocator, resMaterial.GetShaderParameters(i));
525             }
526             allocator->Free(resMaterial.ref().toShaderParametersTable.to_ptr());
527         }
528 
529         allocator->Free(resMaterial.ptr());
530     }
531 }
532 
533 //-----------------------------------------
534 void
DestroyResFragmentShader(os::IAllocator * allocator,ResFragmentShader resFragmentShader)535 Material::DestroyResFragmentShader(
536     os::IAllocator* allocator,
537     ResFragmentShader resFragmentShader)
538 {
539     if (resFragmentShader.IsValid())
540     {
541         ResFragmentLightingTable resFragmentLightingTable = resFragmentShader.GetFragmentLightingTable();
542 
543         if (resFragmentLightingTable.IsValid())
544         {
545             if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
546             {
547                 allocator->Free(resFragmentLightingTable.GetReflectanceRSampler().GetSampler().ptr());
548                 allocator->Free(resFragmentLightingTable.GetReflectanceRSampler().ptr());
549             }
550 
551             if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
552             {
553                 allocator->Free(resFragmentLightingTable.GetReflectanceGSampler().GetSampler().ptr());
554                 allocator->Free(resFragmentLightingTable.GetReflectanceGSampler().ptr());
555             }
556 
557             if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
558             {
559                 allocator->Free(resFragmentLightingTable.GetReflectanceBSampler().GetSampler().ptr());
560                 allocator->Free(resFragmentLightingTable.GetReflectanceBSampler().ptr());
561             }
562 
563             if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
564             {
565                 allocator->Free(resFragmentLightingTable.GetDistribution0Sampler().GetSampler().ptr());
566                 allocator->Free(resFragmentLightingTable.GetDistribution0Sampler().ptr());
567             }
568 
569             if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
570             {
571                 allocator->Free(resFragmentLightingTable.GetDistribution1Sampler().GetSampler().ptr());
572                 allocator->Free(resFragmentLightingTable.GetDistribution1Sampler().ptr());
573             }
574 
575             if (resFragmentLightingTable.GetFresnelSampler().IsValid())
576             {
577                 allocator->Free(resFragmentLightingTable.GetFresnelSampler().GetSampler().ptr());
578                 allocator->Free(resFragmentLightingTable.GetFresnelSampler().ptr());
579             }
580 
581             allocator->Free(resFragmentLightingTable.ptr());
582         }
583 
584         allocator->Free(resFragmentShader.ptr());
585     }
586 }
587 
588 //-----------------------------------------
589 void
DestroyResShaderParameter(os::IAllocator * allocator,ResShaderParameter resShaderParameter)590 Material::DestroyResShaderParameter(
591     os::IAllocator* allocator,
592     ResShaderParameter resShaderParameter)
593 {
594     if (resShaderParameter.IsValid())
595     {
596         allocator->Free(resShaderParameter.ptr());
597     }
598 }
599 
600 //-----------------------------------------
601 ::std::pair<ResFragmentLightingTable, Result>
CopyResFragmentLightingTable(os::IAllocator * allocator,ResFragmentLightingTable resFragmentLightingTable)602 Material::CopyResFragmentLightingTable(
603     os::IAllocator* allocator,
604     ResFragmentLightingTable resFragmentLightingTable)
605 {
606     Result result = INITIALIZE_RESULT_OK;
607 
608     void* tableMemory = allocator->Alloc(sizeof(ResFragmentLightingTableData));
609     if (tableMemory == NULL)
610     {
611         result |= Result::MASK_FAIL_BIT;
612         return ::std::make_pair(ResFragmentLightingTable(NULL), result);
613     }
614 
615     ResFragmentLightingTableData* fragmentLightingTable =
616         new(tableMemory) ResFragmentLightingTableData(resFragmentLightingTable.ref());
617 
618     fragmentLightingTable->toReflectanceRSampler.set_ptr(NULL);
619     fragmentLightingTable->toReflectanceGSampler.set_ptr(NULL);
620     fragmentLightingTable->toReflectanceBSampler.set_ptr(NULL);
621     fragmentLightingTable->toDistribution0Sampler.set_ptr(NULL);
622     fragmentLightingTable->toDistribution1Sampler.set_ptr(NULL);
623     fragmentLightingTable->toFresnelSampler.set_ptr(NULL);
624 
625     if (resFragmentLightingTable.GetReflectanceRSampler().IsValid() && result.IsSuccess())
626     {
627         ::std::pair<ResLightingLookupTable, Result> copyResult =
628             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceRSampler());
629 
630         fragmentLightingTable->toReflectanceRSampler.set_ptr(copyResult.first.ptr());
631 
632         result |= copyResult.second;
633     }
634 
635     if (resFragmentLightingTable.GetReflectanceGSampler().IsValid() && result.IsSuccess())
636     {
637         ::std::pair<ResLightingLookupTable, Result> copyResult =
638             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceGSampler());
639 
640         fragmentLightingTable->toReflectanceGSampler.set_ptr(copyResult.first.ptr());
641 
642         result |= copyResult.second;
643     }
644 
645     if (resFragmentLightingTable.GetReflectanceBSampler().IsValid() && result.IsSuccess())
646     {
647         ::std::pair<ResLightingLookupTable, Result> copyResult =
648             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceBSampler());
649 
650         fragmentLightingTable->toReflectanceBSampler.set_ptr(copyResult.first.ptr());
651 
652         result |= copyResult.second;
653     }
654 
655     if (resFragmentLightingTable.GetDistribution0Sampler().IsValid() && result.IsSuccess())
656     {
657         ::std::pair<ResLightingLookupTable, Result> copyResult =
658             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution0Sampler());
659 
660         fragmentLightingTable->toDistribution0Sampler.set_ptr(copyResult.first.ptr());
661 
662         result |= copyResult.second;
663     }
664 
665     if (resFragmentLightingTable.GetDistribution1Sampler().IsValid() && result.IsSuccess())
666     {
667         ::std::pair<ResLightingLookupTable, Result> copyResult =
668             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution1Sampler());
669 
670         fragmentLightingTable->toDistribution1Sampler.set_ptr(copyResult.first.ptr());
671 
672         result |= copyResult.second;
673     }
674 
675     if (resFragmentLightingTable.GetFresnelSampler().IsValid() && result.IsSuccess())
676     {
677         ::std::pair<ResLightingLookupTable, Result> copyResult =
678             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetFresnelSampler());
679 
680         fragmentLightingTable->toFresnelSampler.set_ptr(copyResult.first.ptr());
681 
682         result |= copyResult.second;
683     }
684 
685     return ::std::make_pair(ResFragmentLightingTable(fragmentLightingTable), result);
686 }
687 
688 //-----------------------------------------
689 ::std::pair<ResLightingLookupTable, Result>
CopyResLightingLookupTable(os::IAllocator * allocator,ResLightingLookupTable resLightingLookupTable)690 Material::CopyResLightingLookupTable(
691     os::IAllocator* allocator,
692     ResLightingLookupTable resLightingLookupTable)
693 {
694     Result result = INITIALIZE_RESULT_OK;
695 
696     void* tableMemory = allocator->Alloc(sizeof(ResLightingLookupTableData));
697 
698     if (tableMemory == NULL)
699     {
700         result |= Result::MASK_FAIL_BIT;
701         return ::std::make_pair(ResLightingLookupTable(NULL), result);
702     }
703 
704     ResLightingLookupTableData* lightingLookupTable =
705         new(tableMemory) ResLightingLookupTableData(resLightingLookupTable.ref());
706 
707     void* referenceTableMemory = allocator->Alloc(sizeof(ResReferenceLookupTableData));
708 
709     if (referenceTableMemory == NULL)
710     {
711         result |= Result::MASK_FAIL_BIT;
712         allocator->Free(lightingLookupTable);
713         return ::std::make_pair(ResLightingLookupTable(NULL), result);
714     }
715 
716     ResReferenceLookupTable sampler =
717         ut::ResStaticCast<ResReferenceLookupTable>(resLightingLookupTable.GetSampler());
718 
719     // TYPE_INFO などをコピーする。
720     ResReferenceLookupTableData* referenceLookupTable =
721         new (referenceTableMemory) ResReferenceLookupTableData(sampler.ref());
722 
723     referenceLookupTable->toTargetLut.set_ptr(sampler.GetTargetLut().ptr());
724     referenceLookupTable->toPath.set_ptr(sampler.GetPath());
725     referenceLookupTable->toTableName.set_ptr(sampler.GetTableName());
726 
727     ResReferenceLookupTable rLut(referenceLookupTable);
728 
729     lightingLookupTable->m_Input = resLightingLookupTable.GetInput();
730     lightingLookupTable->m_Scale = resLightingLookupTable.GetScale();
731     lightingLookupTable->toSampler.set_ptr(referenceLookupTable);
732 
733     return ::std::make_pair(ResLightingLookupTable(lightingLookupTable), result);
734 }
735 
736 //-----------------------------------------
737 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim,const ResMaterial resMaterial)738 Material::GetAnimTargetObject(const anim::ResAnimGroupMember& anim, const ResMaterial resMaterial)
739 {
740     u32 objectType = anim.GetObjectType();
741     ResMaterial mat = resMaterial;
742 
743     switch (objectType)
744     {
745     case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
746         {
747             anim::ResMaterialColorMember member = ResStaticCast<anim::ResMaterialColorMember>(anim);
748             const char* matName = member.GetMaterialName();
749 
750             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
751             ResMaterialColorData* ptr = mat.GetMaterialColor().ptr();
752             return ptr;
753         }
754 
755     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
756         {
757             anim::ResTextureSamplerMember member = ResStaticCast<anim::ResTextureSamplerMember>(anim);
758             const char* matName = member.GetMaterialName();
759             int mapperIndex = member.GetTextureMapperIndex();
760 
761             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
762 
763             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
764             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
765             // Samplerの変更を反映させるにはMapperのSetSampler()を呼ぶ必要があるので、
766             // Mapperのポインタを返す
767             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
768             return ptr;
769         }
770 
771     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
772         {
773             anim::ResTextureMapperMember member = ResStaticCast<anim::ResTextureMapperMember>(anim);
774             const char* matName = member.GetMaterialName();
775             int mapperIndex = member.GetTextureMapperIndex();
776 
777             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
778             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
779 
780             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
781             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
782             return ptr;
783         }
784 
785     case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
786         {
787             anim::ResBlendOperationMember member = ResStaticCast<anim::ResBlendOperationMember>(anim);
788             const char* matName = member.GetMaterialName();
789 
790             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
791             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
792 
793             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
794             ResBlendOperationData* ptr = mat.GetFragmentOperation().GetBlendOperation().ptr();
795             return ptr;
796         }
797 
798     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
799         {
800             anim::ResTextureCoordinatorMember member = ResStaticCast<anim::ResTextureCoordinatorMember>(anim);
801             const char* matName = member.GetMaterialName();
802             int coordinatorIndex = member.GetTextureCoordinatorIndex();
803 
804             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
805             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
806 
807             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
808             ResTextureCoordinatorData* ptr =mat.GetTextureCoordinators(coordinatorIndex).ptr();
809             return ptr;
810         }
811 
812     default:
813         NW_ASSERT(false);
814         return NULL;
815     }
816 }
817 
818 //-----------------------------------------
819 Result
Initialize(os::IAllocator * allocator)820 Material::Initialize(os::IAllocator* allocator)
821 {
822     Result result = INITIALIZE_RESULT_OK;
823 
824     result |= CreateBuffers(allocator);
825     NW_ENSURE_AND_RETURN(result);
826 
827     return result;
828 }
829 
830 } // namespace gfx
831 } // namespace nw
832