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