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