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 "ShaderExReflectionMap.h"
28 #include "OgreShaderFFPRenderState.h"
29 #include "OgreShaderProgram.h"
30 #include "OgreShaderParameter.h"
31 #include "OgreShaderProgramSet.h"
32 #include "OgreScriptCompiler.h"
33 
34 
35 
36 /************************************************************************/
37 /*                                                                      */
38 /************************************************************************/
39 String ShaderExReflectionMap::Type                          = "SGX_ReflectionMap";
40 
41 //-----------------------------------------------------------------------
42 #define SGX_LIB_REFLECTIONMAP                   "SampleLib_ReflectionMap"
43 #define SGX_FUNC_APPLY_REFLECTION_MAP           "SGX_ApplyReflectionMap"
44 
45 //-----------------------------------------------------------------------
ShaderExReflectionMap()46 ShaderExReflectionMap::ShaderExReflectionMap()
47 {
48     mMaskMapSamplerIndex                = 0;
49     mReflectionMapSamplerIndex          = 0;
50     mReflectionMapType                  = TEX_TYPE_2D;
51     mReflectionPowerChanged             = true;
52     mReflectionPowerValue               = 0.5;
53 }
54 
55 //-----------------------------------------------------------------------
getType() const56 const String& ShaderExReflectionMap::getType() const
57 {
58     return Type;
59 }
60 
61 
62 //-----------------------------------------------------------------------
getExecutionOrder() const63 int ShaderExReflectionMap::getExecutionOrder() const
64 {
65     // We place this effect after texturing stage and before fog stage.
66     return FFP_TEXTURING + 1;
67 }
68 
69 //-----------------------------------------------------------------------
copyFrom(const SubRenderState & rhs)70 void ShaderExReflectionMap::copyFrom(const SubRenderState& rhs)
71 {
72     const ShaderExReflectionMap& rhsReflectionMap = static_cast<const ShaderExReflectionMap&>(rhs);
73 
74     // Copy all settings that affect this sub render state output code.
75     mMaskMapSamplerIndex = rhsReflectionMap.mMaskMapSamplerIndex;
76     mReflectionMapSamplerIndex = rhsReflectionMap.mReflectionMapSamplerIndex;
77     mReflectionMapType = rhsReflectionMap.mReflectionMapType;
78     mReflectionPowerChanged = rhsReflectionMap.mReflectionPowerChanged;
79     mReflectionPowerValue = rhsReflectionMap.mReflectionPowerValue;
80     mReflectionMapTextureName = rhsReflectionMap.mReflectionMapTextureName;
81     mMaskMapTextureName = rhsReflectionMap.mMaskMapTextureName;
82 }
83 
84 //-----------------------------------------------------------------------
preAddToRenderState(const RenderState * renderState,Pass * srcPass,Pass * dstPass)85 bool ShaderExReflectionMap::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass )
86 {
87     TextureUnitState* textureUnit;
88 
89     // Create the mask texture unit.
90     textureUnit = dstPass->createTextureUnitState();
91     textureUnit->setTextureName(mMaskMapTextureName);
92     mMaskMapSamplerIndex = dstPass->getNumTextureUnitStates() - 1;
93 
94     // Create the reflection texture unit.
95     textureUnit = dstPass->createTextureUnitState();
96 
97     textureUnit->setTextureName(mReflectionMapTextureName, mReflectionMapType);
98     mReflectionMapSamplerIndex = dstPass->getNumTextureUnitStates() - 1;
99 
100     return true;
101 }
102 
103 //-----------------------------------------------------------------------
resolveParameters(ProgramSet * programSet)104 bool ShaderExReflectionMap::resolveParameters(ProgramSet* programSet)
105 {
106     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
107     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
108     Function* vsMain = vsProgram->getEntryPointFunction();
109     Function* psMain = psProgram->getEntryPointFunction();
110 
111     // Resolve vs input mask texture coordinates.
112     // NOTE: We use the first texture coordinate hard coded here
113     // You may want to parametrize this as well - just remember to add it to hash and copy methods.
114     mVSInMaskTexcoord = vsMain->resolveInputParameter(Parameter::SPC_TEXTURE_COORDINATE0, GCT_FLOAT2);
115     if (mVSInMaskTexcoord.get() == 0)
116         return false;
117 
118     // Resolve vs output mask texture coordinates.
119     mVSOutMaskTexcoord = vsMain->resolveOutputParameter(mVSInMaskTexcoord->getContent(), GCT_FLOAT2);
120     if (mVSOutMaskTexcoord.get() == 0)
121         return false;
122 
123     // Resolve ps input mask texture coordinates.
124     mPSInMaskTexcoord = psMain->resolveInputParameter(mVSOutMaskTexcoord);
125 
126     // Resolve vs output reflection texture coordinates.
127     mVSOutReflectionTexcoord = vsMain->resolveOutputParameter(
128         Parameter::SPC_UNKNOWN, mReflectionMapType == TEX_TYPE_2D ? GCT_FLOAT2 : GCT_FLOAT3);
129     if (mVSOutReflectionTexcoord.get() == 0)
130         return false;
131 
132     // Resolve ps input reflection texture coordinates.
133     mPSInReflectionTexcoord= psMain->resolveInputParameter(mVSOutReflectionTexcoord);
134 
135 
136     // Resolve world matrix.
137     mWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_MATRIX);
138     if (mWorldMatrix.get() == NULL)
139         return false;
140 
141     // Resolve world inverse transpose matrix.
142     mWorldITMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLD_MATRIX);
143     if (mWorldITMatrix.get() == NULL)
144         return false;
145 
146 
147     // Resolve view matrix.
148     mViewMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_VIEW_MATRIX);
149     if (mViewMatrix.get() == NULL)
150         return false;
151 
152     // Resolve vertex position.
153     mVSInputPos = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);
154     if (mVSInputPos.get() == NULL)
155         return false;
156 
157     // Resolve vertex normal.
158     mVSInputNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
159     if (mVSInputNormal.get() == NULL)
160         return false;
161 
162     // Resolve mask texture sampler parameter.
163     mMaskMapSampler = psProgram->resolveParameter(GCT_SAMPLER2D, mMaskMapSamplerIndex, (uint16)GPV_GLOBAL, "mask_sampler");
164     if (mMaskMapSampler.get() == NULL)
165         return false;
166 
167     // Resolve reflection texture sampler parameter.
168     mReflectionMapSampler = psProgram->resolveParameter(mReflectionMapType == TEX_TYPE_2D ? GCT_SAMPLER2D : GCT_SAMPLERCUBE,
169         mReflectionMapSamplerIndex, (uint16)GPV_GLOBAL, "reflection_texture");
170     if (mReflectionMapSampler.get() == NULL)
171         return false;
172 
173     // Resolve reflection power parameter.
174     mReflectionPower = psProgram->resolveParameter(GCT_FLOAT1, -1, (uint16)GPV_GLOBAL, "reflection_power");
175     if (mReflectionPower.get() == NULL)
176         return false;
177 
178     // Resolve ps output diffuse colour.
179     mPSOutDiffuse = psMain->resolveOutputParameter(Parameter::SPC_COLOR_DIFFUSE);
180     if (mPSOutDiffuse.get() == NULL)
181         return false;
182 
183     return true;
184 }
185 
186 //-----------------------------------------------------------------------
resolveDependencies(ProgramSet * programSet)187 bool ShaderExReflectionMap::resolveDependencies(ProgramSet* programSet)
188 {
189     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
190     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
191 
192     vsProgram->addDependency(FFP_LIB_COMMON);
193     vsProgram->addDependency(FFP_LIB_TEXTURING);
194 
195     psProgram->addDependency(FFP_LIB_COMMON);
196     psProgram->addDependency(FFP_LIB_TEXTURING);
197     psProgram->addDependency(SGX_LIB_REFLECTIONMAP);
198 
199     return true;
200 }
201 
202 
203 //-----------------------------------------------------------------------
addFunctionInvocations(ProgramSet * programSet)204 bool ShaderExReflectionMap::addFunctionInvocations(ProgramSet* programSet)
205 {
206     Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
207     Function* vsMain = vsProgram->getEntryPointFunction();
208     Program* psProgram = programSet->getCpuProgram(GPT_FRAGMENT_PROGRAM);
209     Function* psMain = psProgram->getEntryPointFunction();
210 
211 
212     // Add vertex shader invocations.
213     if (false == addVSInvocations(vsMain->getStage(FFP_VS_TEXTURING + 1)))
214         return false;
215 
216 
217     // Add pixel shader invocations.
218     if (false == addPSInvocations(psMain->getStage(FFP_PS_TEXTURING + 1)))
219         return false;
220 
221     return true;
222 }
223 
224 //-----------------------------------------------------------------------
addVSInvocations(const FunctionStageRef & stage)225 bool ShaderExReflectionMap::addVSInvocations( const FunctionStageRef& stage )
226 {
227     // Output mask texture coordinates.
228     stage.assign(mVSInMaskTexcoord, mVSOutMaskTexcoord);
229 
230 
231     // Output reflection texture coordinates.
232     if (mReflectionMapType == TEX_TYPE_2D)
233     {
234         stage.callFunction(FFP_FUNC_GENERATE_TEXCOORD_ENV_SPHERE,
235                            {In(mWorldITMatrix), In(mViewMatrix), In(mVSInputNormal), Out(mVSOutReflectionTexcoord)});
236     }
237     else
238     {
239         stage.callFunction(
240             FFP_FUNC_GENERATE_TEXCOORD_ENV_REFLECT,
241             {In(mWorldMatrix), In(mWorldITMatrix), In(mViewMatrix), In(mVSInputNormal), In(mVSInputPos), Out(mVSOutReflectionTexcoord)});
242     }
243 
244 
245 
246     return true;
247 }
248 
249 //-----------------------------------------------------------------------
addPSInvocations(const FunctionStageRef & stage)250 bool ShaderExReflectionMap::addPSInvocations( const FunctionStageRef& stage )
251 {
252     stage.callFunction(SGX_FUNC_APPLY_REFLECTION_MAP,
253                        {In(mMaskMapSampler), In(mPSInMaskTexcoord), In(mReflectionMapSampler),
254                         In(mPSInReflectionTexcoord), In(mPSOutDiffuse).xyz(), In(mReflectionPower),
255                         Out(mPSOutDiffuse).xyz()});
256     return true;
257 }
258 
259 //-----------------------------------------------------------------------
setReflectionMapType(TextureType type)260 void ShaderExReflectionMap::setReflectionMapType( TextureType type )
261 {
262     if (type != TEX_TYPE_2D && type != TEX_TYPE_CUBE_MAP)
263     {
264         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
265             "Invalid texture type set - only 2D or Cube supported",
266             "ShaderExReflectionMap::setReflectionMapType");
267     }
268     mReflectionMapType = type;
269 }
270 
271 //-----------------------------------------------------------------------
setReflectionPower(const Real reflectionPower)272 void ShaderExReflectionMap::setReflectionPower(const Real reflectionPower)
273 {
274     mReflectionPowerValue = reflectionPower;
275     mReflectionPowerChanged = true;
276 }
277 
278 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)279 void ShaderExReflectionMap::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source, const LightList* pLightList)
280 {
281     if (mReflectionPowerChanged)
282     {
283         GpuProgramParametersSharedPtr fsParams = pass->getFragmentProgramParameters();
284 
285         mReflectionPower->setGpuParameter(mReflectionPowerValue);
286 
287         mReflectionPowerChanged = false;
288     }
289 }
290 
291 //-----------------------------------------------------------------------
createInstance(ScriptCompiler * compiler,PropertyAbstractNode * prop,Pass * pass,SGScriptTranslator * translator)292 SubRenderState* ShaderExReflectionMapFactory::createInstance(ScriptCompiler* compiler,
293                                                          PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
294 {
295     if (prop->name == "rtss_ext_reflection_map")
296     {
297         if(prop->values.size() >= 2)
298         {
299             String strValue;
300             AbstractNodeList::const_iterator it = prop->values.begin();
301 
302             // Read reflection map type.
303             if(false == SGScriptTranslator::getString(*it, &strValue))
304             {
305                 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
306                 return NULL;
307             }
308             ++it;
309 
310             SubRenderState* subRenderState = SubRenderStateFactory::createInstance();
311             ShaderExReflectionMap* reflectionMapSubRenderState = static_cast<ShaderExReflectionMap*>(subRenderState);
312 
313 
314             // Reflection map is cubic texture.
315             if (strValue == "cube_map")
316             {
317                 reflectionMapSubRenderState->setReflectionMapType(TEX_TYPE_CUBE_MAP);
318             }
319 
320             // Reflection map is 2d texture.
321             else if (strValue == "2d_map")
322             {
323                 reflectionMapSubRenderState->setReflectionMapType(TEX_TYPE_2D);
324             }
325 
326             // Read mask texture.
327             if (false == SGScriptTranslator::getString(*it, &strValue))
328             {
329                 compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
330                 return NULL;
331             }
332             reflectionMapSubRenderState->setMaskMapTextureName(strValue);
333             ++it;
334 
335 
336             // Read reflection texture.
337             if (false == SGScriptTranslator::getString(*it, &strValue))
338             {
339                 compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
340                 return NULL;
341             }
342             reflectionMapSubRenderState->setReflectionMapTextureName(strValue);
343             ++it;
344 
345             // Read reflection power value.
346             Real reflectionPower = 0.5;
347             if (false == SGScriptTranslator::getReal(*it, &reflectionPower))
348             {
349                 compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
350                 return NULL;
351             }
352             reflectionMapSubRenderState->setReflectionPower(reflectionPower);
353 
354             return subRenderState;
355 
356         }
357     }
358 
359     return NULL;
360 }
361 
362 //-----------------------------------------------------------------------
writeInstance(MaterialSerializer * ser,SubRenderState * subRenderState,Pass * srcPass,Pass * dstPass)363 void ShaderExReflectionMapFactory::writeInstance(MaterialSerializer* ser,
364                                              SubRenderState* subRenderState,
365                                              Pass* srcPass, Pass* dstPass)
366 {
367     ser->writeAttribute(4, "rtss_ext_reflection_map");
368 
369 
370     ShaderExReflectionMap* reflectionMapSubRenderState = static_cast<ShaderExReflectionMap*>(subRenderState);
371 
372     if (reflectionMapSubRenderState->getReflectionMapType() == TEX_TYPE_CUBE_MAP)
373     {
374         ser->writeValue("cube_map");
375     }
376     else if (reflectionMapSubRenderState->getReflectionMapType() == TEX_TYPE_2D)
377     {
378         ser->writeValue("2d_map");
379     }
380 
381     ser->writeValue(reflectionMapSubRenderState->getMaskMapTextureName());
382     ser->writeValue(reflectionMapSubRenderState->getReflectionMapTextureName());
383     ser->writeValue(StringConverter::toString(reflectionMapSubRenderState->getReflectionPower()));
384 }
385 
386 //-----------------------------------------------------------------------
getType() const387 const String& ShaderExReflectionMapFactory::getType() const
388 {
389     return ShaderExReflectionMap::Type;
390 }
391 
392 
393 //-----------------------------------------------------------------------
createInstanceImpl()394 SubRenderState* ShaderExReflectionMapFactory::createInstanceImpl()
395 {
396     return OGRE_NEW ShaderExReflectionMap;
397 }
398