/src/ogre/Components/RTShaderSystem/src/OgreShaderFFPLighting.cpp
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | | of this software and associated documentation files (the "Software"), to deal |
10 | | in the Software without restriction, including without limitation the rights |
11 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
12 | | copies of the Software, and to permit persons to whom the Software is |
13 | | furnished to do so, subject to the following conditions: |
14 | | |
15 | | The above copyright notice and this permission notice shall be included in |
16 | | all copies or substantial portions of the Software. |
17 | | |
18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
21 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
23 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
24 | | THE SOFTWARE. |
25 | | ----------------------------------------------------------------------------- |
26 | | */ |
27 | | #include "OgreShaderPrecompiledHeaders.h" |
28 | | #if defined(RTSHADER_SYSTEM_BUILD_CORE_SHADERS) || defined(RTSHADER_SYSTEM_BUILD_EXT_SHADERS) |
29 | | namespace Ogre { |
30 | | namespace RTShader { |
31 | | |
32 | | /************************************************************************/ |
33 | | /* */ |
34 | | /************************************************************************/ |
35 | | const String SRS_PER_VERTEX_LIGHTING = "FFP_Lighting"; |
36 | | |
37 | | //----------------------------------------------------------------------- |
38 | | FFPLighting::FFPLighting() |
39 | 0 | { |
40 | 0 | mTrackVertexColourType = TVC_NONE; |
41 | 0 | mSpecularEnable = false; |
42 | 0 | mNormalisedEnable = false; |
43 | 0 | mTwoSidedLighting = false; |
44 | 0 | mLightCount = 0; |
45 | 0 | mLtcLUT1SamplerIndex = -1; |
46 | 0 | } |
47 | | |
48 | | //----------------------------------------------------------------------- |
49 | | const String& FFPLighting::getType() const |
50 | 0 | { |
51 | 0 | return SRS_PER_VERTEX_LIGHTING; |
52 | 0 | } |
53 | | |
54 | | |
55 | | //----------------------------------------------------------------------- |
56 | | int FFPLighting::getExecutionOrder() const |
57 | 0 | { |
58 | 0 | return FFP_LIGHTING; |
59 | 0 | } |
60 | | |
61 | | //----------------------------------------------------------------------- |
62 | | bool FFPLighting::resolveParameters(ProgramSet* programSet) |
63 | 0 | { |
64 | 0 | Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM); |
65 | 0 | Function* vsMain = vsProgram->getEntryPointFunction(); |
66 | | |
67 | | // Resolve world view IT matrix. |
68 | 0 | mWorldViewITMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_NORMAL_MATRIX); |
69 | 0 | mViewNormal = vsMain->resolveLocalParameter(Parameter::SPC_NORMAL_VIEW_SPACE); |
70 | | |
71 | | // Get surface ambient colour if need to. |
72 | 0 | if ((mTrackVertexColourType & TVC_AMBIENT) == 0) |
73 | 0 | { |
74 | 0 | mDerivedAmbientLightColour = vsProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR); |
75 | 0 | } |
76 | 0 | else |
77 | 0 | { |
78 | 0 | mLightAmbientColour = vsProgram->resolveParameter(GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); |
79 | 0 | } |
80 | | |
81 | | // Get surface emissive colour if need to. |
82 | 0 | if ((mTrackVertexColourType & TVC_EMISSIVE) == 0) |
83 | 0 | { |
84 | 0 | mSurfaceEmissiveColour = vsProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); |
85 | 0 | } |
86 | | |
87 | | // Get derived scene colour. |
88 | 0 | mDerivedSceneColour = vsProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_SCENE_COLOUR); |
89 | | |
90 | | // Resolve input vertex shader normal. |
91 | 0 | mVSInNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE); |
92 | | |
93 | 0 | if (mTrackVertexColourType != 0) |
94 | 0 | { |
95 | 0 | mInDiffuse = vsMain->resolveInputParameter(Parameter::SPC_COLOR_DIFFUSE); |
96 | 0 | } |
97 | | |
98 | | |
99 | | // Resolve output vertex shader diffuse colour. |
100 | 0 | mOutDiffuse = vsMain->resolveOutputParameter(Parameter::SPC_COLOR_DIFFUSE); |
101 | | |
102 | | // Resolve per light parameters. |
103 | 0 | mPositions = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE_ARRAY, mLightCount); |
104 | 0 | mAttenuatParams = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_ATTENUATION_ARRAY, mLightCount); |
105 | 0 | mDirections = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE_ARRAY, mLightCount); |
106 | 0 | mSpotParams = vsProgram->resolveParameter(GpuProgramParameters::ACT_SPOTLIGHT_PARAMS_ARRAY, mLightCount); |
107 | | |
108 | | // Resolve diffuse colour. |
109 | 0 | if ((mTrackVertexColourType & TVC_DIFFUSE) == 0) |
110 | 0 | { |
111 | 0 | mDiffuseColours = vsProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR_ARRAY, mLightCount); |
112 | 0 | } |
113 | 0 | else |
114 | 0 | { |
115 | 0 | mDiffuseColours = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR_POWER_SCALED_ARRAY, mLightCount); |
116 | 0 | } |
117 | |
|
118 | 0 | if (mSpecularEnable) |
119 | 0 | { |
120 | | // Get surface shininess. |
121 | 0 | mSurfaceShininess = vsProgram->resolveParameter(GpuProgramParameters::ACT_SURFACE_SHININESS); |
122 | | |
123 | | // Resolve specular colour. |
124 | 0 | if ((mTrackVertexColourType & TVC_SPECULAR) == 0) |
125 | 0 | { |
126 | 0 | mSpecularColours = vsProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_LIGHT_SPECULAR_COLOUR_ARRAY, mLightCount); |
127 | 0 | } |
128 | 0 | else |
129 | 0 | { |
130 | 0 | mSpecularColours = vsProgram->resolveParameter(GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR_POWER_SCALED_ARRAY, mLightCount); |
131 | 0 | } |
132 | |
|
133 | 0 | if (mOutSpecular.get() == NULL) |
134 | 0 | { |
135 | 0 | mOutSpecular = vsMain->resolveOutputParameter(Parameter::SPC_COLOR_SPECULAR); |
136 | 0 | } |
137 | 0 | } |
138 | | |
139 | | //if(needViewPos) |
140 | 0 | { |
141 | 0 | mWorldViewMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLDVIEW_MATRIX); |
142 | 0 | mVSInPosition = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE); |
143 | 0 | mViewPos = vsMain->resolveLocalParameter(Parameter::SPC_POSITION_VIEW_SPACE); |
144 | 0 | } |
145 | |
|
146 | 0 | return true; |
147 | 0 | } |
148 | | |
149 | | //----------------------------------------------------------------------- |
150 | | bool FFPLighting::resolveDependencies(ProgramSet* programSet) |
151 | 0 | { |
152 | 0 | Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM); |
153 | |
|
154 | 0 | vsProgram->addDependency(FFP_LIB_TRANSFORM); |
155 | 0 | vsProgram->addDependency(SGX_LIB_PERPIXELLIGHTING); |
156 | |
|
157 | 0 | addDefines(vsProgram); |
158 | |
|
159 | 0 | if(mSpecularEnable) |
160 | 0 | programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM)->addPreprocessorDefines("USE_SPECULAR"); |
161 | |
|
162 | 0 | return true; |
163 | 0 | } |
164 | | |
165 | | void FFPLighting::addDefines(Program* program) |
166 | 0 | { |
167 | 0 | if(mNormalisedEnable) |
168 | 0 | program->addPreprocessorDefines("NORMALISED"); |
169 | |
|
170 | 0 | if(mSpecularEnable) |
171 | 0 | program->addPreprocessorDefines("USE_SPECULAR"); |
172 | |
|
173 | 0 | if(mTrackVertexColourType & TVC_DIFFUSE) |
174 | 0 | program->addPreprocessorDefines("TVC_DIFFUSE"); |
175 | |
|
176 | 0 | if(mTrackVertexColourType & TVC_SPECULAR) |
177 | 0 | program->addPreprocessorDefines("TVC_SPECULAR"); |
178 | |
|
179 | 0 | program->addPreprocessorDefines("LIGHT_COUNT=" + StringConverter::toString(mLightCount)); |
180 | 0 | } |
181 | | |
182 | | //----------------------------------------------------------------------- |
183 | | bool FFPLighting::addFunctionInvocations(ProgramSet* programSet) |
184 | 0 | { |
185 | 0 | Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM); |
186 | 0 | Function* vsMain = vsProgram->getEntryPointFunction(); |
187 | 0 | auto stage = vsMain->getStage(FFP_VS_LIGHTING); |
188 | | |
189 | | // Add the global illumination functions. |
190 | 0 | addGlobalIlluminationInvocation(stage); |
191 | | |
192 | | // Add per light functions. |
193 | 0 | for (int i = 0; i < mLightCount; i++) |
194 | 0 | { |
195 | 0 | addIlluminationInvocation(i, stage); |
196 | 0 | } |
197 | |
|
198 | 0 | auto psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM); |
199 | 0 | auto psMain = psProgram->getMain(); |
200 | 0 | if (auto shadowFactor = psMain->getLocalParameter("lShadowFactor")) |
201 | 0 | { |
202 | 0 | auto ambient = psProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_SCENE_COLOUR); |
203 | 0 | auto psOutDiffuse = psMain->resolveOutputParameter(Parameter::SPC_COLOR_DIFFUSE); |
204 | |
|
205 | 0 | auto fstage = psMain->getStage(FFP_PS_COLOUR_BEGIN); |
206 | |
|
207 | 0 | std::vector<Operand> args = {In(ambient), In(shadowFactor),InOut(psOutDiffuse)}; |
208 | |
|
209 | 0 | if (mSpecularEnable) |
210 | 0 | { |
211 | 0 | auto psSpecular = psMain->getInputParameter(Parameter::SPC_COLOR_SPECULAR); |
212 | 0 | if (!psSpecular) |
213 | 0 | psSpecular = psMain->getLocalParameter(Parameter::SPC_COLOR_SPECULAR); |
214 | 0 | args.push_back(InOut(psSpecular)); |
215 | 0 | } |
216 | |
|
217 | 0 | fstage.callFunction("SGX_ApplyShadowFactor_Modulative", args); |
218 | 0 | } |
219 | |
|
220 | 0 | return true; |
221 | 0 | } |
222 | | |
223 | | //----------------------------------------------------------------------- |
224 | | void FFPLighting::addGlobalIlluminationInvocation(const FunctionStageRef& stage) |
225 | 0 | { |
226 | | // Transform normal to view space |
227 | 0 | if(mLightCount) |
228 | 0 | stage.callBuiltin("mul", mWorldViewITMatrix, mVSInNormal, mViewNormal); |
229 | |
|
230 | 0 | if(mViewPos) |
231 | 0 | { |
232 | | // Transform position to view space. |
233 | 0 | stage.callFunction(FFP_FUNC_TRANSFORM, mWorldViewMatrix, mVSInPosition, mViewPos); |
234 | 0 | } |
235 | |
|
236 | 0 | if ((mTrackVertexColourType & TVC_AMBIENT) == 0 && |
237 | 0 | (mTrackVertexColourType & TVC_EMISSIVE) == 0) |
238 | 0 | { |
239 | 0 | stage.assign(mDerivedSceneColour, mOutDiffuse); |
240 | 0 | } |
241 | 0 | else |
242 | 0 | { |
243 | 0 | if (mTrackVertexColourType & TVC_AMBIENT) |
244 | 0 | { |
245 | 0 | stage.mul(mLightAmbientColour, mInDiffuse, mOutDiffuse); |
246 | 0 | } |
247 | 0 | else |
248 | 0 | { |
249 | 0 | stage.assign(mDerivedAmbientLightColour, mOutDiffuse); |
250 | 0 | } |
251 | |
|
252 | 0 | if (mTrackVertexColourType & TVC_EMISSIVE) |
253 | 0 | { |
254 | 0 | stage.add(In(mInDiffuse).xyz(), In(mOutDiffuse).xyz(), Out(mOutDiffuse).xyz()); |
255 | 0 | } |
256 | 0 | else |
257 | 0 | { |
258 | 0 | stage.add(mSurfaceEmissiveColour, mOutDiffuse, mOutDiffuse); |
259 | 0 | } |
260 | 0 | } |
261 | 0 | } |
262 | | |
263 | | //----------------------------------------------------------------------- |
264 | | void FFPLighting::addIlluminationInvocation(int i, const FunctionStageRef& stage) |
265 | 0 | { |
266 | 0 | std::vector<Operand> args = {In(mViewNormal), In(mViewPos), In(mPositions), At(i), |
267 | 0 | In(mAttenuatParams), At(i), In(mDirections), At(i), |
268 | 0 | In(mSpotParams), At(i), In(mDiffuseColours), At(i), |
269 | 0 | InOut(mOutDiffuse).xyz()}; |
270 | |
|
271 | 0 | if (mTrackVertexColourType & (TVC_DIFFUSE | TVC_SPECULAR)) |
272 | 0 | { |
273 | 0 | args.push_back(In(mInDiffuse)); |
274 | 0 | } |
275 | |
|
276 | 0 | if (mSpecularEnable) |
277 | 0 | { |
278 | 0 | args.insert(args.end(), {In(mSpecularColours), At(i), In(mSurfaceShininess), InOut(mOutSpecular).xyz()}); |
279 | 0 | } |
280 | |
|
281 | 0 | if (mShadowFactor) |
282 | 0 | { |
283 | 0 | if(i < int(mShadowFactor->getSize())) |
284 | 0 | args.insert(args.end(), {In(mShadowFactor), At(i)}); |
285 | 0 | else |
286 | 0 | args.push_back(In(1)); |
287 | 0 | } |
288 | |
|
289 | 0 | if(mLTCLUT1) |
290 | 0 | { |
291 | 0 | args.insert(args.end(), {In(mLTCLUT1), In(mLTCLUT2)}); |
292 | 0 | } |
293 | |
|
294 | 0 | stage.callFunction("evaluateLight", args); |
295 | 0 | } |
296 | | |
297 | | |
298 | | //----------------------------------------------------------------------- |
299 | | void FFPLighting::copyFrom(const SubRenderState& rhs) |
300 | 0 | { |
301 | 0 | const FFPLighting& rhsLighting = static_cast<const FFPLighting&>(rhs); |
302 | |
|
303 | 0 | mLightCount = rhsLighting.mLightCount; |
304 | 0 | mNormalisedEnable = rhsLighting.mNormalisedEnable; |
305 | 0 | mTwoSidedLighting = rhsLighting.mTwoSidedLighting; |
306 | 0 | } |
307 | | |
308 | | uint16 ensureLtcLUTPresent(Pass* dstPass) |
309 | 0 | { |
310 | 0 | auto tus = dstPass->getTextureUnitState("ltc_1.dds"); |
311 | | // return idx of existing texture unit |
312 | 0 | if(tus) |
313 | 0 | return dstPass->getTextureUnitStateIndex(tus); |
314 | | |
315 | 0 | auto ltcSampler = TextureManager::getSingleton().getSampler("Ogre/LtcLUTSampler"); |
316 | 0 | tus = dstPass->createTextureUnitState("ltc_1.dds"); |
317 | 0 | tus->setNumMipmaps(0); |
318 | 0 | tus->setName("ltc_1.dds"); |
319 | 0 | tus->setSampler(ltcSampler); |
320 | 0 | tus = dstPass->createTextureUnitState("ltc_2.dds"); |
321 | 0 | tus->setNumMipmaps(0); |
322 | 0 | tus->setSampler(ltcSampler); |
323 | |
|
324 | 0 | return dstPass->getNumTextureUnitStates() - 2; // idx of first LUT |
325 | 0 | } |
326 | | |
327 | | //----------------------------------------------------------------------- |
328 | | bool FFPLighting::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass) |
329 | 0 | { |
330 | | //! [disable] |
331 | 0 | if (!srcPass->getLightingEnabled()) |
332 | 0 | return false; |
333 | | //! [disable] |
334 | | |
335 | 0 | mLightCount = renderState->getLightCount(); |
336 | | |
337 | 0 | setTrackVertexColourType(srcPass->getVertexColourTracking()); |
338 | |
|
339 | 0 | mSpecularEnable = srcPass->getShininess() > 0.0 && |
340 | 0 | (srcPass->getSpecular() != ColourValue::Black || (srcPass->getVertexColourTracking() & TVC_SPECULAR) != 0); |
341 | | |
342 | | // Case this pass should run once per light(s) -> override the light policy. |
343 | 0 | if (srcPass->getIteratePerLight()) |
344 | 0 | { |
345 | 0 | mLightCount = srcPass->getLightCountPerIteration(); |
346 | 0 | } |
347 | |
|
348 | 0 | if(srcPass->getMaxSimultaneousLights() == 0) |
349 | 0 | { |
350 | 0 | mLightCount = 0; |
351 | 0 | } |
352 | |
|
353 | 0 | if (renderState->haveAreaLights()) |
354 | 0 | mLtcLUT1SamplerIndex = ensureLtcLUTPresent(dstPass); |
355 | |
|
356 | 0 | return true; |
357 | 0 | } |
358 | | |
359 | | bool FFPLighting::setParameter(const String& name, const String& value) |
360 | 0 | { |
361 | 0 | if(name == "normalise" || name == "normalised") // allow both spelling variations |
362 | 0 | { |
363 | 0 | return StringConverter::parse(value, mNormalisedEnable); |
364 | 0 | } |
365 | | |
366 | 0 | return false; |
367 | 0 | } |
368 | | |
369 | | //----------------------------------------------------------------------- |
370 | | const String& FFPLightingFactory::getType() const |
371 | 0 | { |
372 | 0 | return SRS_PER_VERTEX_LIGHTING; |
373 | 0 | } |
374 | | |
375 | | //----------------------------------------------------------------------- |
376 | | SubRenderState* FFPLightingFactory::createInstance(const ScriptProperty& prop, Pass* pass, |
377 | | SGScriptTranslator* translator) |
378 | 0 | { |
379 | 0 | if (prop.name != "lighting_stage" || prop.values[0] != "ffp") |
380 | 0 | return NULL; |
381 | | |
382 | 0 | SubRenderState* ret = createOrRetrieveInstance(translator); |
383 | |
|
384 | 0 | if(prop.values.size() >= 2) |
385 | 0 | { |
386 | 0 | ret->setParameter(prop.values[1], "true"); // normalise |
387 | 0 | } |
388 | |
|
389 | 0 | return ret; |
390 | 0 | } |
391 | | |
392 | | //----------------------------------------------------------------------- |
393 | | void FFPLightingFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState, |
394 | | Pass* srcPass, Pass* dstPass) |
395 | 0 | { |
396 | 0 | ser->writeAttribute(4, "lighting_stage"); |
397 | 0 | ser->writeValue("ffp"); |
398 | 0 | } |
399 | | |
400 | | //----------------------------------------------------------------------- |
401 | | SubRenderState* FFPLightingFactory::createInstanceImpl() |
402 | 0 | { |
403 | | return OGRE_NEW FFPLighting; |
404 | 0 | } |
405 | | |
406 | | } |
407 | | } |
408 | | |
409 | | #endif |