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 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "OgreShaderPrecompiledHeaders.h"
29 #ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
30 
31 namespace Ogre {
32 namespace RTShader {
33 
34 /************************************************************************/
35 /*                                                                      */
36 /************************************************************************/
37 String IntegratedPSSM3::Type = "SGX_IntegratedPSSM3";
38 
39 //-----------------------------------------------------------------------
IntegratedPSSM3()40 IntegratedPSSM3::IntegratedPSSM3()
41 {
42 
43 }
44 
45 //-----------------------------------------------------------------------
getType() const46 const String& IntegratedPSSM3::getType() const
47 {
48     return Type;
49 }
50 
51 
52 //-----------------------------------------------------------------------
getExecutionOrder() const53 int IntegratedPSSM3::getExecutionOrder() const
54 {
55     return FFP_TEXTURING + 1;
56 }
57 
58 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)59 void IntegratedPSSM3::updateGpuProgramsParams(Renderable* rend, Pass* pass,
60                                              const AutoParamDataSource* source,
61                                              const LightList* pLightList)
62 {
63     ShadowTextureParamsIterator it = mShadowTextureParamsList.begin();
64     size_t shadowIndex = 0;
65 
66     while(it != mShadowTextureParamsList.end())
67     {
68         it->mWorldViewProjMatrix->setGpuParameter(source->getTextureWorldViewProjMatrix(shadowIndex));
69         it->mInvTextureSize->setGpuParameter(source->getInverseTextureSize(it->mTextureSamplerIndex));
70 
71         ++it;
72         ++shadowIndex;
73     }
74 
75     Vector4 vSplitPoints;
76 
77     vSplitPoints.x = mShadowTextureParamsList[0].mMaxRange;
78     vSplitPoints.y = mShadowTextureParamsList[1].mMaxRange;
79     vSplitPoints.z = 0.0;
80     vSplitPoints.w = 0.0;
81 
82     mPSSplitPoints->setGpuParameter(vSplitPoints);
83 
84 }
85 
86 //-----------------------------------------------------------------------
copyFrom(const SubRenderState & rhs)87 void IntegratedPSSM3::copyFrom(const SubRenderState& rhs)
88 {
89     const IntegratedPSSM3& rhsPssm= static_cast<const IntegratedPSSM3&>(rhs);
90 
91     mShadowTextureParamsList.resize(rhsPssm.mShadowTextureParamsList.size());
92 
93     ShadowTextureParamsConstIterator itSrc = rhsPssm.mShadowTextureParamsList.begin();
94     ShadowTextureParamsIterator itDst = mShadowTextureParamsList.begin();
95 
96     while(itDst != mShadowTextureParamsList.end())
97     {
98         itDst->mMaxRange = itSrc->mMaxRange;
99         ++itSrc;
100         ++itDst;
101     }
102 }
103 
104 //-----------------------------------------------------------------------
preAddToRenderState(const RenderState * renderState,Pass * srcPass,Pass * dstPass)105 bool IntegratedPSSM3::preAddToRenderState(const RenderState* renderState,
106                                          Pass* srcPass, Pass* dstPass)
107 {
108     if (srcPass->getLightingEnabled() == false ||
109         srcPass->getParent()->getParent()->getReceiveShadows() == false)
110         return false;
111 
112     ShadowTextureParamsIterator it = mShadowTextureParamsList.begin();
113 
114     while(it != mShadowTextureParamsList.end())
115     {
116         TextureUnitState* curShadowTexture = dstPass->createTextureUnitState();
117 
118         curShadowTexture->setContentType(TextureUnitState::CONTENT_SHADOW);
119         curShadowTexture->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
120         curShadowTexture->setTextureBorderColour(ColourValue::White);
121         it->mTextureSamplerIndex = dstPass->getNumTextureUnitStates() - 1;
122         ++it;
123     }
124 
125 
126 
127     return true;
128 }
129 
130 //-----------------------------------------------------------------------
setSplitPoints(const SplitPointList & newSplitPoints)131 void IntegratedPSSM3::setSplitPoints(const SplitPointList& newSplitPoints)
132 {
133     if (newSplitPoints.size() != 4)
134     {
135         OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
136                     "IntegratedPSSM3 sub render state requires 4 split points");
137     }
138 
139     mShadowTextureParamsList.resize(newSplitPoints.size() - 1);
140 
141     for (size_t i = 1; i < newSplitPoints.size(); ++i)
142     {
143         mShadowTextureParamsList[i - 1].mMaxRange = newSplitPoints[i];
144     }
145 }
146 
147 //-----------------------------------------------------------------------
resolveParameters(ProgramSet * programSet)148 bool IntegratedPSSM3::resolveParameters(ProgramSet* programSet)
149 {
150     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
151     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
152     Function* vsMain = vsProgram->getEntryPointFunction();
153     Function* psMain = psProgram->getEntryPointFunction();
154 
155     // Get input position parameter.
156     mVSInPos = vsMain->getInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);
157 
158     // Get output position parameter.
159     mVSOutPos = vsMain->getOutputParameter(Parameter::SPC_POSITION_PROJECTIVE_SPACE);
160 
161     // Resolve vertex shader output depth.
162     mVSOutDepth = vsMain->resolveOutputParameter(Parameter::SPC_DEPTH_VIEW_SPACE);
163 
164     // Resolve input depth parameter.
165     mPSInDepth = psMain->resolveInputParameter(mVSOutDepth);
166 
167     // Get in/local diffuse parameter.
168     mPSDiffuse = psMain->getInputParameter(Parameter::SPC_COLOR_DIFFUSE);
169     if (mPSDiffuse.get() == NULL)
170     {
171         mPSDiffuse = psMain->getLocalParameter(Parameter::SPC_COLOR_DIFFUSE);
172     }
173 
174     // Resolve output diffuse parameter.
175     mPSOutDiffuse = psMain->resolveOutputParameter(Parameter::SPC_COLOR_DIFFUSE);
176 
177     // Get in/local specular parameter.
178     mPSSpecualr = psMain->getInputParameter(Parameter::SPC_COLOR_SPECULAR);
179     if (mPSSpecualr.get() == NULL)
180     {
181         mPSSpecualr = psMain->getLocalParameter(Parameter::SPC_COLOR_SPECULAR);
182     }
183 
184     // Resolve computed local shadow colour parameter.
185     mPSLocalShadowFactor = psMain->resolveLocalParameter("lShadowFactor", GCT_FLOAT1);
186 
187     // Resolve computed local shadow colour parameter.
188     mPSSplitPoints = psProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_GLOBAL, "pssm_split_points");
189 
190     // Get derived scene colour.
191     mPSDerivedSceneColour = psProgram->resolveParameter(GpuProgramParameters::ACT_DERIVED_SCENE_COLOUR);
192 
193     ShadowTextureParamsIterator it = mShadowTextureParamsList.begin();
194     int lightIndex = 0;
195 
196     while(it != mShadowTextureParamsList.end())
197     {
198         it->mWorldViewProjMatrix = vsProgram->resolveParameter(GCT_MATRIX_4X4, -1, (uint16)GPV_PER_OBJECT, "world_texture_view_proj");
199 
200         it->mVSOutLightPosition = vsMain->resolveOutputParameter(Parameter::Content(Parameter::SPC_POSITION_LIGHT_SPACE0 + lightIndex));
201         it->mPSInLightPosition = psMain->resolveInputParameter(it->mVSOutLightPosition);
202         it->mTextureSampler = psProgram->resolveParameter(GCT_SAMPLER2D, it->mTextureSamplerIndex, (uint16)GPV_GLOBAL, "shadow_map");
203 
204         it->mInvTextureSize = psProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_GLOBAL, "inv_shadow_texture_size");
205 
206         if (!(it->mInvTextureSize.get()) || !(it->mTextureSampler.get()) || !(it->mPSInLightPosition.get()) ||
207             !(it->mVSOutLightPosition.get()) || !(it->mWorldViewProjMatrix.get()))
208         {
209             OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
210                 "Not all parameters could be constructed for the sub-render state.",
211                 "IntegratedPSSM3::resolveParameters" );
212         }
213 
214         ++lightIndex;
215         ++it;
216     }
217 
218     if (!(mVSInPos.get()) || !(mVSOutPos.get()) || !(mVSOutDepth.get()) || !(mPSInDepth.get()) || !(mPSDiffuse.get()) || !(mPSOutDiffuse.get()) ||
219         !(mPSSpecualr.get()) || !(mPSLocalShadowFactor.get()) || !(mPSSplitPoints.get()) || !(mPSDerivedSceneColour.get()))
220     {
221         OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
222                 "Not all parameters could be constructed for the sub-render state.",
223                 "IntegratedPSSM3::resolveParameters" );
224     }
225 
226     return true;
227 }
228 
229 //-----------------------------------------------------------------------
resolveDependencies(ProgramSet * programSet)230 bool IntegratedPSSM3::resolveDependencies(ProgramSet* programSet)
231 {
232     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
233     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
234 
235     vsProgram->addDependency(FFP_LIB_COMMON);
236 
237     psProgram->addDependency(FFP_LIB_COMMON);
238     psProgram->addDependency(SGX_LIB_INTEGRATEDPSSM);
239 
240     return true;
241 }
242 
243 //-----------------------------------------------------------------------
addFunctionInvocations(ProgramSet * programSet)244 bool IntegratedPSSM3::addFunctionInvocations(ProgramSet* programSet)
245 {
246     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
247     Function* vsMain = vsProgram->getEntryPointFunction();
248     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
249 
250     // Add vertex shader invocations.
251     if (false == addVSInvocation(vsMain, FFP_VS_TEXTURING + 1))
252         return false;
253 
254     // Add pixel shader invocations.
255     if (false == addPSInvocation(psProgram, FFP_PS_COLOUR_BEGIN + 2))
256         return false;
257 
258     return true;
259 }
260 
261 //-----------------------------------------------------------------------
addVSInvocation(Function * vsMain,const int groupOrder)262 bool IntegratedPSSM3::addVSInvocation(Function* vsMain, const int groupOrder)
263 {
264     auto stage = vsMain->getStage(groupOrder);
265 
266     // Output the vertex depth in camera space.
267     stage.assign(In(mVSOutPos).z(), mVSOutDepth);
268 
269     // Compute world space position.
270     ShadowTextureParamsIterator it = mShadowTextureParamsList.begin();
271 
272     while(it != mShadowTextureParamsList.end())
273     {
274         stage.callFunction(FFP_FUNC_TRANSFORM, it->mWorldViewProjMatrix, mVSInPos, it->mVSOutLightPosition);
275         ++it;
276     }
277 
278     return true;
279 }
280 
281 //-----------------------------------------------------------------------
addPSInvocation(Program * psProgram,const int groupOrder)282 bool IntegratedPSSM3::addPSInvocation(Program* psProgram, const int groupOrder)
283 {
284     Function* psMain = psProgram->getEntryPointFunction();
285     auto stage = psMain->getStage(groupOrder);
286 
287     ShadowTextureParams& splitParams0 = mShadowTextureParamsList[0];
288     ShadowTextureParams& splitParams1 = mShadowTextureParamsList[1];
289     ShadowTextureParams& splitParams2 = mShadowTextureParamsList[2];
290 
291     // Compute shadow factor.
292     stage.callFunction(SGX_FUNC_COMPUTE_SHADOW_COLOUR3,
293                        {In(mPSInDepth), In(mPSSplitPoints), In(splitParams0.mPSInLightPosition),
294                         In(splitParams1.mPSInLightPosition), In(splitParams2.mPSInLightPosition),
295                         In(splitParams0.mTextureSampler), In(splitParams1.mTextureSampler),
296                         In(splitParams2.mTextureSampler), In(splitParams0.mInvTextureSize),
297                         In(splitParams1.mInvTextureSize), In(splitParams2.mInvTextureSize), Out(mPSLocalShadowFactor)});
298 
299     // Apply shadow factor on diffuse colour.
300     stage.callFunction(SGX_FUNC_APPLYSHADOWFACTOR_DIFFUSE,
301                        {In(mPSDerivedSceneColour), In(mPSDiffuse), In(mPSLocalShadowFactor), Out(mPSDiffuse)});
302 
303     // Apply shadow factor on specular colour.
304     stage.callFunction(SGX_FUNC_MODULATE_SCALAR, mPSLocalShadowFactor, mPSSpecualr, mPSSpecualr);
305 
306     // Assign the local diffuse to output diffuse.
307     stage.assign(mPSDiffuse, mPSOutDiffuse);
308 
309     return true;
310 }
311 
312 
313 
314 //-----------------------------------------------------------------------
getType() const315 const String& IntegratedPSSM3Factory::getType() const
316 {
317     return IntegratedPSSM3::Type;
318 }
319 
320 //-----------------------------------------------------------------------
createInstance(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)321 SubRenderState* IntegratedPSSM3Factory::createInstance(ScriptCompiler* compiler,
322                                                       PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
323 {
324     if (prop->name == "integrated_pssm4")
325     {
326         if (prop->values.size() != 4)
327         {
328             compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
329         }
330         else
331         {
332             IntegratedPSSM3::SplitPointList splitPointList;
333 
334             AbstractNodeList::const_iterator it = prop->values.begin();
335             AbstractNodeList::const_iterator itEnd = prop->values.end();
336 
337             while(it != itEnd)
338             {
339                 Real curSplitValue;
340 
341                 if (false == SGScriptTranslator::getReal(*it, &curSplitValue))
342                 {
343                     compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
344                     break;
345                 }
346 
347                 splitPointList.push_back(curSplitValue);
348 
349                 ++it;
350             }
351 
352             if (splitPointList.size() == 4)
353             {
354                 SubRenderState* subRenderState = createOrRetrieveInstance(translator);
355                 IntegratedPSSM3* pssmSubRenderState = static_cast<IntegratedPSSM3*>(subRenderState);
356 
357                 pssmSubRenderState->setSplitPoints(splitPointList);
358 
359                 return pssmSubRenderState;
360             }
361         }
362     }
363 
364     return NULL;
365 }
366 
367 //-----------------------------------------------------------------------
createInstanceImpl()368 SubRenderState* IntegratedPSSM3Factory::createInstanceImpl()
369 {
370     return OGRE_NEW IntegratedPSSM3;
371 }
372 
373 }
374 }
375 
376 #endif
377