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