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