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