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
29 namespace Ogre {
30 namespace RTShader {
31
32
33 //-----------------------------------------------------------------------
RenderState()34 RenderState::RenderState()
35 {
36 mLightCountAutoUpdate = true;
37 mLightCount[0] = 0;
38 mLightCount[1] = 0;
39 mLightCount[2] = 0;
40 }
41
42 //-----------------------------------------------------------------------
~RenderState()43 RenderState::~RenderState()
44 {
45 reset();
46 }
47
48 //-----------------------------------------------------------------------
reset()49 void RenderState::reset()
50 {
51 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
52 {
53 ShaderGenerator::getSingleton().destroySubRenderState(*it);
54 }
55 mSubRenderStateList.clear();
56 }
57
58 //-----------------------------------------------------------------------
setLightCount(const int lightCount[3])59 void RenderState::setLightCount(const int lightCount[3])
60 {
61 mLightCount[0] = lightCount[0];
62 mLightCount[1] = lightCount[1];
63 mLightCount[2] = lightCount[2];
64 }
65
66 //-----------------------------------------------------------------------
getLightCount(int lightCount[3]) const67 void RenderState::getLightCount(int lightCount[3]) const
68 {
69 lightCount[0] = mLightCount[0];
70 lightCount[1] = mLightCount[1];
71 lightCount[2] = mLightCount[2];
72 }
73
74 //-----------------------------------------------------------------------
addTemplateSubRenderState(SubRenderState * subRenderState)75 void RenderState::addTemplateSubRenderState(SubRenderState* subRenderState)
76 {
77 bool addSubRenderState = true;
78
79 // Go over the current sub render state.
80 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
81 {
82 // Case the same instance already exists -> do not add to list.
83 if (*it == subRenderState)
84 {
85 addSubRenderState = false;
86 break;
87 }
88
89 // Case it is different sub render state instance with the same type, use the new sub render state
90 // instead of the previous sub render state. This scenario is usually caused by material inheritance, so we use the derived material sub render state
91 // and destroy the base sub render state.
92 else if ((*it)->getType() == subRenderState->getType())
93 {
94 removeTemplateSubRenderState(*it);
95 break;
96 }
97 }
98
99 // Add only if this sub render state instance is not on the list.
100 if (addSubRenderState)
101 {
102 mSubRenderStateList.push_back(subRenderState);
103 }
104 }
105
106 //-----------------------------------------------------------------------
removeTemplateSubRenderState(SubRenderState * subRenderState)107 void RenderState::removeTemplateSubRenderState(SubRenderState* subRenderState)
108 {
109 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
110 {
111 if ((*it) == subRenderState)
112 {
113 ShaderGenerator::getSingleton().destroySubRenderState(*it);
114 mSubRenderStateList.erase(it);
115 break;
116 }
117 }
118 }
119
120 //-----------------------------------------------------------------------
TargetRenderState()121 TargetRenderState::TargetRenderState()
122 {
123 mProgramSet = NULL;
124 mSubRenderStateSortValid = false;
125 }
126
127 //-----------------------------------------------------------------------
~TargetRenderState()128 TargetRenderState::~TargetRenderState()
129 {
130 destroyProgramSet();
131 }
132
133
134 //-----------------------------------------------------------------------
addSubRenderStateInstance(SubRenderState * subRenderState)135 void TargetRenderState::addSubRenderStateInstance(SubRenderState* subRenderState)
136 {
137 mSubRenderStateList.push_back(subRenderState);
138 mSubRenderStateSortValid = false;
139 }
140
141 //-----------------------------------------------------------------------
removeSubRenderStateInstance(SubRenderState * subRenderState)142 void TargetRenderState::removeSubRenderStateInstance(SubRenderState* subRenderState)
143 {
144 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
145 {
146 if ((*it) == subRenderState)
147 {
148 ShaderGenerator::getSingleton().destroySubRenderState(*it);
149 mSubRenderStateList.erase(it);
150 break;
151 }
152 }
153 }
154
155 //-----------------------------------------------------------------------
createCpuPrograms()156 bool TargetRenderState::createCpuPrograms()
157 {
158 sortSubRenderStates();
159
160 ProgramSet* programSet = createProgramSet();
161 Program* vsProgram = ProgramManager::getSingleton().createCpuProgram(GPT_VERTEX_PROGRAM);
162 Program* psProgram = ProgramManager::getSingleton().createCpuProgram(GPT_FRAGMENT_PROGRAM);
163 RTShader::Function* vsMainFunc = NULL;
164 RTShader::Function* psMainFunc = NULL;
165
166 programSet->setCpuProgram(vsProgram, GPT_VERTEX_PROGRAM);
167 programSet->setCpuProgram(psProgram, GPT_FRAGMENT_PROGRAM);
168
169 // Create entry point functions.
170 vsMainFunc = vsProgram->createFunction("main", "Vertex Program Entry point", Function::FFT_VS_MAIN);
171 vsProgram->setEntryPointFunction(vsMainFunc);
172
173 psMainFunc = psProgram->createFunction("main", "Pixel Program Entry point", Function::FFT_PS_MAIN);
174 psProgram->setEntryPointFunction(psMainFunc);
175
176 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
177 {
178 SubRenderState* srcSubRenderState = *it;
179
180 if (false == srcSubRenderState->createCpuSubPrograms(programSet))
181 {
182 LogManager::getSingleton().stream() << "RTShader::TargetRenderState : Could not generate sub render program of type: " << srcSubRenderState->getType();
183 return false;
184 }
185 }
186
187 return true;
188 }
189
190 //-----------------------------------------------------------------------
createProgramSet()191 ProgramSet* TargetRenderState::createProgramSet()
192 {
193 destroyProgramSet();
194
195 mProgramSet = OGRE_NEW ProgramSet;
196
197 return mProgramSet;
198 }
199 //-----------------------------------------------------------------------
destroyProgramSet()200 void TargetRenderState::destroyProgramSet()
201 {
202 if (mProgramSet != NULL)
203 {
204 OGRE_DELETE mProgramSet;
205 mProgramSet = NULL;
206 }
207 }
208
209 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)210 void TargetRenderState::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source,
211 const LightList* pLightList)
212 {
213 for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
214 {
215 SubRenderState* curSubRenderState = *it;
216
217 curSubRenderState->updateGpuProgramsParams(rend, pass, source, pLightList);
218 }
219 }
220
221 //-----------------------------------------------------------------------
link(const RenderState & rhs,Pass * srcPass,Pass * dstPass)222 void TargetRenderState::link(const RenderState& rhs, Pass* srcPass, Pass* dstPass)
223 {
224 SubRenderStateList customSubRenderStates;
225
226 // Sort current render states.
227 sortSubRenderStates();
228
229 // Insert all custom sub render states. (I.E Not FFP sub render states).
230 const SubRenderStateList& subRenderStateList = rhs.getTemplateSubRenderStateList();
231
232 for (SubRenderStateListConstIterator itSrc=subRenderStateList.begin(); itSrc != subRenderStateList.end(); ++itSrc)
233 {
234 const SubRenderState* srcSubRenderState = *itSrc;
235 bool isCustomSubRenderState = true;
236
237 if (srcSubRenderState->getExecutionOrder() == FFP_TRANSFORM ||
238 srcSubRenderState->getExecutionOrder() == FFP_COLOUR ||
239 srcSubRenderState->getExecutionOrder() == FFP_LIGHTING ||
240 srcSubRenderState->getExecutionOrder() == FFP_TEXTURING ||
241 srcSubRenderState->getExecutionOrder() == FFP_FOG)
242 {
243 isCustomSubRenderState = false;
244 }
245
246
247 // Case it is a custom sub render state.
248 if (isCustomSubRenderState)
249 {
250 bool subStateTypeExists = false;
251
252 // Check if this type of sub render state already exists.
253 for (SubRenderStateListConstIterator itDst=mSubRenderStateList.begin(); itDst != mSubRenderStateList.end(); ++itDst)
254 {
255 if ((*itDst)->getType() == srcSubRenderState->getType())
256 {
257 subStateTypeExists = true;
258 break;
259 }
260 }
261
262 // Case custom sub render state not exits -> add it to custom list.
263 if (subStateTypeExists == false)
264 {
265 SubRenderState* newSubRenderState = NULL;
266
267 newSubRenderState = ShaderGenerator::getSingleton().createSubRenderState(srcSubRenderState->getType());
268 *newSubRenderState = *srcSubRenderState;
269 customSubRenderStates.push_back(newSubRenderState);
270 }
271 }
272 }
273
274 // Merge the local custom sub render states.
275 for (SubRenderStateListIterator itSrc=customSubRenderStates.begin(); itSrc != customSubRenderStates.end(); ++itSrc)
276 {
277 SubRenderState* customSubRenderState = *itSrc;
278
279 if (customSubRenderState->preAddToRenderState(this, srcPass, dstPass))
280 {
281 addSubRenderStateInstance(customSubRenderState);
282 }
283 else
284 {
285 ShaderGenerator::getSingleton().destroySubRenderState(customSubRenderState);
286 }
287 }
288 }
289
290 namespace {
291 struct CmpSubRenderStates {
operator ()Ogre::RTShader::__anondf415dbe0111::CmpSubRenderStates292 bool operator()(const SubRenderState* a, const SubRenderState* b) const
293 {
294 return a->getExecutionOrder() < b->getExecutionOrder();
295 }
296 };
297 }
298
299 //-----------------------------------------------------------------------
sortSubRenderStates()300 void TargetRenderState::sortSubRenderStates()
301 {
302 if (mSubRenderStateSortValid == false)
303 {
304 std::sort(mSubRenderStateList.begin(), mSubRenderStateList.end(), CmpSubRenderStates());
305 mSubRenderStateSortValid = true;
306 }
307 }
308
309 }
310 }
311