1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_MaterialActivator.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: 26943 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/gfx_MaterialActivator.h>
19 #include <nw/gfx/gfx_MaterialState.h>
20 #include <nw/gfx/gfx_Model.h>
21 #include <nn/gx.h>
22
23 // このマクロを定義するとバッファを有効にします。
24 #define BUFFER_ENABLED
25
26 namespace nw
27 {
28 namespace gfx
29 {
30
31 NW_UT_RUNTIME_TYPEINFO_DEFINITION(MaterialActivator, IMaterialActivator);
32
33 //----------------------------------------
34 IMaterialActivator*
Create(os::IAllocator * allocator)35 MaterialActivator::Create(os::IAllocator* allocator)
36 {
37 void* memory = allocator->Alloc(sizeof(MaterialActivator));
38
39 if (memory == NULL)
40 {
41 return NULL;
42 }
43 else
44 {
45 return new(memory) MaterialActivator(allocator);
46 }
47 }
48
49 //----------------------------------------
50 void
Activate(RenderContext * renderContext,const Material * material)51 MaterialActivator::Activate(RenderContext* renderContext, const Material* material)
52 {
53 NW_NULL_ASSERT(renderContext);
54 const ShaderProgram* shaderProgram = renderContext->GetShaderProgram();
55 NW_NULL_ASSERT(shaderProgram);
56
57 ResMaterial original = material->GetOriginal();
58 const Model* owner = material->GetOwnerModel();
59 NW_NULL_ASSERT(owner);
60
61 const SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
62 bool areFragmentLightsDirty = sceneEnvironment.IsFragmentLightsDirty() || sceneEnvironment.IsAmbientLightDirty();
63 bool areVertexLightsDirty = sceneEnvironment.IsVertexLightsDirty() || sceneEnvironment.IsHemiSphereLightDirty();
64
65 bit32 bufferOption = owner->GetBufferOption();
66
67 RenderContext::MaterialHash materialHash = renderContext->GetMaterialHash();
68
69 const ResMaterial resShaderParameterMaterial = material->GetShaderParameterResMaterial();
70 u32 shaderParametersHash = resShaderParameterMaterial.GetShaderParametersHash();
71 bool isShaderParametersEnabled =
72 (shaderParametersHash != materialHash.shaderParameter) ||
73 (shaderParametersHash == 0x0) ||
74 renderContext->IsShaderProgramDirty();
75 if (isShaderParametersEnabled)
76 {
77 internal::MaterialState::ActivateShaderParameter(shaderProgram, resShaderParameterMaterial);
78 materialHash.shaderParameter = shaderParametersHash;
79 }
80
81 const ResMaterial resShadingParameterResMaterial = material->GetShadingParameterResMaterial();
82
83 // FragmentLightEnabled は必ず設定します。
84 internal::MaterialState::ActivateFragmentLightParameters(sceneEnvironment, shaderProgram, resShadingParameterResMaterial);
85
86 u32 shadingParametersHash = resShadingParameterResMaterial.GetShadingParameterHash();
87 bool isShadingParametersEnabled =
88 (shadingParametersHash != materialHash.shadingParameter) || shadingParametersHash == 0x0 || areVertexLightsDirty;
89 if (isShadingParametersEnabled)
90 {
91 internal::MaterialState::ActivateShadingParameters(sceneEnvironment, shaderProgram, resShadingParameterResMaterial);
92 materialHash.shadingParameter = shadingParametersHash;
93 }
94
95 const ResMaterial resRasterizationMaterial = material->GetRasterizationResMaterial();
96 u32 rasterizationHash = resRasterizationMaterial.GetRasterizationHash();
97 bool isRasterizationEnabled = (rasterizationHash != materialHash.rasterization) || rasterizationHash == 0x0;
98 if (isRasterizationEnabled)
99 {
100 internal::MaterialState::ActivateRasterization(resRasterizationMaterial.GetRasterization());
101 materialHash.rasterization = rasterizationHash;
102 }
103
104 const ResMaterial resTextureCoordinatorsMaterial = material->GetTextureCoordinatorResMaterial();
105 u32 textureCoordinatorHash = resTextureCoordinatorsMaterial.GetTextureCoordinatorsHash();
106 bool isTextureCoordinatorEnabled = (textureCoordinatorHash != materialHash.textureCoordinator) || textureCoordinatorHash == 0x0;
107 if (isTextureCoordinatorEnabled)
108 {
109 internal::MaterialState::ActivateTextureCoordinators(renderContext, shaderProgram, resTextureCoordinatorsMaterial);
110 materialHash.textureCoordinator = textureCoordinatorHash;
111 }
112
113 const ResMaterial resTextureMappersMaterial = material->GetTextureMapperResMaterial();
114 u32 textureMappersHash = resTextureMappersMaterial.GetTextureMappersHash();
115 bool isTextureMappersEnabled = (textureMappersHash != materialHash.textureMapper) || textureMappersHash == 0x0;
116 if (isTextureMappersEnabled)
117 {
118 internal::MaterialState::ActivateTextureMappers(resTextureMappersMaterial);
119 materialHash.textureMapper = textureMappersHash;
120 }
121
122 #if 0 // プロシージャルテクスチャは未対応
123 const ResMaterial resProceduralTextureMapperMaterial = material->GetProceduralTextureMapperResMaterial();
124 internal::MaterialState::ActivateProceduralTextureMapper(renderContext, shaderProgram, resProceduralTextureMapperMaterial);
125 #endif
126
127 bool reflectionEnabled = false;
128 bool lightEnabled = ut::CheckFlag(resShaderParameterMaterial.GetFlags(), ResMaterialData::FLAG_FRAGMENTLIGHT_ENABLED);
129 if (lightEnabled)
130 {
131 const ResMaterial resFragmentLightingResMaterial = material->GetFragmentLightingResMaterial();
132 const ResFragmentLighting resFragmentLighting = resFragmentLightingResMaterial.GetFragmentShader().GetFragmentLighting();
133 reflectionEnabled = ut::CheckFlag(resFragmentLighting.GetFlags(), ResFragmentLightingData::FLAG_REFLECTION_ENABLED);
134 u32 fragmentLightingHash = resFragmentLightingResMaterial.GetFragmentLightingHash();
135 bool isFragmentLightingEnabled = (fragmentLightingHash != materialHash.fragmentLighting) ||
136 fragmentLightingHash == 0x0 ||
137 areFragmentLightsDirty;
138 if (isFragmentLightingEnabled)
139 {
140 internal::MaterialState::ActivateFragmentLighting(sceneEnvironment, resFragmentLighting);
141 materialHash.fragmentLighting = fragmentLightingHash;
142 }
143
144 const ResMaterial resFramgnetLightingTableResMaterial = material->GetFragmentLightingTableResMaterial();
145 u32 fragmentLightingTableHash = resFramgnetLightingTableResMaterial.GetFragmentLightingTableHash();
146 bool isFragmentLightingTableEnabled = (fragmentLightingTableHash != materialHash.fragmentLightingTable) || fragmentLightingTableHash == 0x0;
147 if (isFragmentLightingTableEnabled)
148 {
149 const ResFragmentLightingTable resFragmentLightingTable = resFramgnetLightingTableResMaterial.GetFragmentShader().GetFragmentLightingTable();
150 internal::MaterialState::ActivateFragmentLightingTable(resFragmentLighting, resFragmentLightingTable);
151 materialHash.fragmentLightingTable = fragmentLightingTableHash;
152 }
153 }
154
155 const ResMaterial resMaterialColorResMaterial = material->GetMaterialColorResMaterial();
156 const ResMaterialColor resMaterialColor = resMaterialColorResMaterial.GetMaterialColor();
157 u32 materialColorHash = resMaterialColorResMaterial.GetMaterialColorHash();
158 bool isMaterialColorEnabled = (materialColorHash != materialHash.materialColor) || materialColorHash == 0x0 || areFragmentLightsDirty;
159
160 Material* cacheMaterial = renderContext->GetMaterialCache();
161 if (!isMaterialColorEnabled && cacheMaterial != NULL)
162 {
163 // マテリアルカラーは reflectionEnabled が変化したときに再設定する必要があるために前回に設定したマテリアルを参照します。
164 ResMaterial resCacheMaterial = cacheMaterial->GetFragmentLightingTableResMaterial();
165 bool isPreReflectionEnabled = ut::CheckFlag(resCacheMaterial.GetFragmentShader().GetFragmentLighting().GetFlags(), ResFragmentLightingData::FLAG_REFLECTION_ENABLED);
166 isMaterialColorEnabled = (reflectionEnabled != isPreReflectionEnabled);
167 }
168 if (isMaterialColorEnabled)
169 {
170 internal::MaterialState::ActivateMaterialColor(sceneEnvironment, shaderProgram, resMaterialColor, reflectionEnabled);
171 materialHash.materialColor = materialColorHash;
172 }
173
174 const ResMaterial resTextureCombinerResMaterial = material->GetTextureCombinerResMaterial();
175 u32 textureCombinersHash = resTextureCombinerResMaterial.GetTextureCombinersHash();
176 bool isTextureCombinersEnabled = (textureCombinersHash != materialHash.textureCombiner) || textureCombinersHash == 0x0;
177 if (isTextureCombinersEnabled || isMaterialColorEnabled)
178 {
179 const ResFragmentShader resTextureCombinerFragmentShader = resTextureCombinerResMaterial.GetFragmentShader();
180 internal::MaterialState::ActivateTextureCombiners(resTextureCombinerFragmentShader, resMaterialColor);
181 materialHash.textureCombiner = textureCombinersHash;
182 }
183
184 const ResMaterial resAlphaTestResMaterial = material->GetAlphaTestResMaterial();
185 u32 alphaTestHash = resAlphaTestResMaterial.GetAlphaTestHash();
186 bool isAlphaTestEnabled = (alphaTestHash != materialHash.alphaTest) || alphaTestHash == 0x0;
187 if (isAlphaTestEnabled)
188 {
189 const ResAlphaTest resAlphaTest = resAlphaTestResMaterial.GetFragmentShader().GetAlphaTest();
190 internal::MaterialState::ActivateAlphaTest(resAlphaTest);
191 materialHash.alphaTest = alphaTestHash;
192 }
193
194 const ResMaterial resFragmentOperationResMaterial = material->GetFragmentOperationResMaterial();
195 u32 fragmentOperationHash = resFragmentOperationResMaterial.GetFragmentOperationHash();
196 bool isFragmentOperationEnabled = (fragmentOperationHash != materialHash.fragmentOperation) || fragmentOperationHash == 0x0;
197 if (isFragmentOperationEnabled)
198 {
199 const ResFragmentOperation resFragmentOperation = resFragmentOperationResMaterial.GetFragmentOperation();
200 internal::MaterialState::ActivateFragmentOperation(resFragmentOperation);
201 materialHash.fragmentOperation = fragmentOperationHash;
202 }
203
204 renderContext->SetMaterialHash(materialHash);
205 }
206
207 //----------------------------------------
MaterialActivator(os::IAllocator * allocator)208 MaterialActivator::MaterialActivator(os::IAllocator* allocator)
209 : IMaterialActivator(allocator)
210 {
211 }
212
213 //----------------------------------------
~MaterialActivator()214 MaterialActivator::~MaterialActivator()
215 {
216 }
217
218 } // namespace gfx
219 } // namespace nw
220