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