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 //-----------------------------------------------------------------------------
SGScriptTranslator()33 SGScriptTranslator::SGScriptTranslator() :
34 mGeneratedRenderState(NULL)
35 {
36 }
37
38 //-----------------------------------------------------------------------------
translate(ScriptCompiler * compiler,const AbstractNodePtr & node)39 void SGScriptTranslator::translate(ScriptCompiler* compiler, const AbstractNodePtr &node)
40 {
41 ObjectAbstractNode* obj = static_cast<ObjectAbstractNode*>(node.get());
42 ObjectAbstractNode* parent = static_cast<ObjectAbstractNode*>(obj->parent);
43
44 // Translate section within a pass context.
45 if (parent->id == ID_PASS)
46 {
47 translatePass(compiler, node);
48 }
49 if (parent->id == ID_TEXTURE_UNIT)
50 {
51 translateTextureUnit(compiler, node);
52 }
53 }
54
55 //-----------------------------------------------------------------------------
getGeneratedSubRenderState(const String & typeName)56 SubRenderState* SGScriptTranslator::getGeneratedSubRenderState(const String& typeName)
57 {
58 //check if we are in the middle of parsing
59 if (mGeneratedRenderState)
60 {
61 /** Get the list of the template sub render states composing this render state. */
62 const SubRenderStateList& rsList =
63 mGeneratedRenderState->getTemplateSubRenderStateList();
64
65 SubRenderStateList::const_iterator it = rsList.begin();
66 SubRenderStateList::const_iterator itEnd = rsList.end();
67 for(; it != itEnd; ++it)
68 {
69 if ((*it)->getType() == typeName)
70 return *it;
71 }
72 }
73 return NULL;
74 }
75
76 //-----------------------------------------------------------------------------
77 /*
78 note: we can know the texture unit index by getting parent then finding it in the list of children
79 */
translateTextureUnit(ScriptCompiler * compiler,const AbstractNodePtr & node)80 void SGScriptTranslator::translateTextureUnit(ScriptCompiler* compiler, const AbstractNodePtr &node)
81 {
82 ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
83 TextureUnitState* texState = any_cast<TextureUnitState*>(obj->parent->context);
84 Pass* pass = texState->getParent();
85 Technique* technique = pass->getParent();
86 Material* material = technique->getParent();
87 ShaderGenerator* shaderGenerator = ShaderGenerator::getSingletonPtr();
88 String dstTechniqueSchemeName = obj->name;
89 bool techniqueCreated;
90
91 // Make sure the scheme name is valid - use default if none exists.
92 if (dstTechniqueSchemeName.empty())
93 dstTechniqueSchemeName = ShaderGenerator::DEFAULT_SCHEME_NAME;
94
95
96 //check if technique already created
97 techniqueCreated = shaderGenerator->hasShaderBasedTechnique(material->getName(),
98 material->getGroup(),
99 technique->getSchemeName(),
100 dstTechniqueSchemeName);
101
102 if (techniqueCreated == false)
103 {
104 // Create the shader based technique.
105 techniqueCreated = shaderGenerator->createShaderBasedTechnique(technique,
106 dstTechniqueSchemeName,
107 shaderGenerator->getCreateShaderOverProgrammablePass());
108 }
109
110
111
112 // Case technique successfully created.
113 if (techniqueCreated)
114 {
115 //Attempt to get the render state which might have been created by the pass parsing
116 mGeneratedRenderState = shaderGenerator->getRenderState(dstTechniqueSchemeName,
117 material->getName(), material->getGroup(), pass->getIndex());
118
119 // Go over all the render state properties.
120 for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
121 {
122 if((*i)->type == ANT_PROPERTY)
123 {
124 PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>((*i).get());
125 SubRenderState* subRenderState = ShaderGenerator::getSingleton().createSubRenderState(compiler, prop, texState, this);
126
127 if (subRenderState)
128 {
129 addSubRenderState(subRenderState, dstTechniqueSchemeName, material->getName(),
130 material->getGroup(), pass->getIndex());
131 }
132 }
133 else
134 {
135 processNode(compiler, *i);
136 }
137 }
138
139 mGeneratedRenderState = NULL;
140 }
141 }
142
143
144 //-----------------------------------------------------------------------------
translatePass(ScriptCompiler * compiler,const AbstractNodePtr & node)145 void SGScriptTranslator::translatePass(ScriptCompiler* compiler, const AbstractNodePtr &node)
146 {
147 ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
148 Pass* pass = any_cast<Pass*>(obj->parent->context);
149 Technique* technique = pass->getParent();
150 Material* material = technique->getParent();
151 ShaderGenerator* shaderGenerator = ShaderGenerator::getSingletonPtr();
152 String dstTechniqueSchemeName = obj->name;
153 bool techniqueCreated;
154
155 // Make sure the scheme name is valid - use default if none exists.
156 if (dstTechniqueSchemeName.empty())
157 dstTechniqueSchemeName = ShaderGenerator::DEFAULT_SCHEME_NAME;
158
159
160 // Create the shader based technique.
161 techniqueCreated = shaderGenerator->createShaderBasedTechnique(technique,
162 dstTechniqueSchemeName,
163 shaderGenerator->getCreateShaderOverProgrammablePass());
164
165
166 // Case technique successfully created.
167 if (techniqueCreated)
168 {
169 // Go over all the render state properties.
170 for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
171 {
172 if((*i)->type == ANT_PROPERTY)
173 {
174 PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>((*i).get());
175
176 // Handle light count property.
177 if (prop->name == "light_count")
178 {
179 if (prop->values.size() != 3)
180 {
181 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
182 }
183 else
184 {
185 std::vector<int> lightCount;
186 if (getVector(prop->values.begin(), prop->values.end(), lightCount, 3))
187 {
188 shaderGenerator->createScheme(dstTechniqueSchemeName);
189 RenderState* renderState = shaderGenerator->getRenderState(dstTechniqueSchemeName,
190 material->getName(), material->getGroup(), pass->getIndex());
191
192 renderState->setLightCount(lightCount.data());
193 renderState->setLightCountAutoUpdate(false);
194 }
195 else
196 {
197 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
198 }
199 }
200 }
201
202 // Handle the rest of the custom properties.
203 else
204 {
205 SubRenderState* subRenderState = ShaderGenerator::getSingleton().createSubRenderState(compiler, prop, pass, this);
206 if (subRenderState)
207 {
208 addSubRenderState(subRenderState, dstTechniqueSchemeName, material->getName(), material->getGroup(), pass->getIndex());
209 }
210 }
211 }
212 else
213 {
214 processNode(compiler, *i);
215 }
216 }
217
218 mGeneratedRenderState = NULL;
219 }
220
221 }
222
223 //-----------------------------------------------------------------------------
addSubRenderState(SubRenderState * newSubRenderState,const String & dstTechniqueSchemeName,const String & materialName,const String & groupName,unsigned short passIndex)224 void SGScriptTranslator::addSubRenderState(SubRenderState* newSubRenderState,
225 const String& dstTechniqueSchemeName, const String& materialName, const String& groupName, unsigned short passIndex)
226 {
227 assert(newSubRenderState);
228
229 //check if a different sub render state of the same type already exists
230 ShaderGenerator* shaderGenerator = ShaderGenerator::getSingletonPtr();
231
232 //create a new scheme if needed
233 shaderGenerator->createScheme(dstTechniqueSchemeName);
234
235 //update the active render state
236 mGeneratedRenderState = shaderGenerator->getRenderState(dstTechniqueSchemeName, materialName, groupName, passIndex);
237
238 //add the new sub render state
239 mGeneratedRenderState->addTemplateSubRenderState(newSubRenderState);
240 }
241
242 }
243 }
244