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