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