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