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