]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/generate.cpp
Recognize swizzles in GLSL
[libs/gl.git] / source / glsl / generate.cpp
index 53676c26784cf7d32709639fea843459e3cf4269..3e53c1526daa88c43766dbfc4a019d267c317157 100644 (file)
@@ -1,3 +1,4 @@
+#include <algorithm>
 #include <msp/core/hash.h>
 #include <msp/core/raii.h>
 #include <msp/strings/lexicalcast.h>
@@ -367,11 +368,43 @@ void VariableResolver::visit(MemberAccess &memacc)
                if(i!=strct->members.variables.end())
                        declaration = i->second;
        }
+       else if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(memacc.left->type))
+       {
+               bool scalar_swizzle = ((basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT) && memacc.member.size()==1);
+               bool vector_swizzle = (basic->kind==BasicTypeDeclaration::VECTOR && memacc.member.size()<=4);
+               if(scalar_swizzle || vector_swizzle)
+               {
+                       static const char component_names[] = { 'x', 'r', 's', 'y', 'g', 't', 'z', 'b', 'p', 'w', 'a', 'q' };
+
+                       bool ok = true;
+                       UInt8 components[4] = { };
+                       for(unsigned i=0; (ok && i<memacc.member.size()); ++i)
+                               ok = ((components[i] = (find(component_names, component_names+12, memacc.member[i])-component_names)/3) < 4);
+
+                       if(ok)
+                       {
+                               Swizzle *swizzle = new Swizzle;
+                               swizzle->source = memacc.source;
+                               swizzle->line = memacc.line;
+                               swizzle->oper = memacc.oper;
+                               swizzle->left = memacc.left;
+                               swizzle->component_group = memacc.member;
+                               swizzle->count = memacc.member.size();
+                               copy(components, components+memacc.member.size(), swizzle->components);
+                               r_replacement_expr = swizzle;
+                       }
+               }
+       }
 
        r_any_resolved |= (declaration!=memacc.declaration);
        memacc.declaration = declaration;
 }
 
+void VariableResolver::visit(Swizzle &swizzle)
+{
+       visit_and_replace(swizzle.left);
+}
+
 void VariableResolver::visit(UnaryExpression &unary)
 {
        visit_and_replace(unary.expression);
@@ -589,6 +622,20 @@ void ExpressionResolver::visit(MemberAccess &memacc)
                resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue);
 }
 
+void ExpressionResolver::visit(Swizzle &swizzle)
+{
+       TraversingVisitor::visit(swizzle);
+
+       if(BasicTypeDeclaration *left_basic = dynamic_cast<BasicTypeDeclaration *>(swizzle.left->type))
+       {
+               BasicTypeDeclaration *left_elem = get_element_type(*left_basic);
+               if(swizzle.count==1)
+                       resolve(swizzle, left_elem, swizzle.left->lvalue);
+               else if(left_basic->kind==BasicTypeDeclaration::VECTOR && left_elem)
+                       resolve(swizzle, find_type(*left_elem, left_basic->kind, swizzle.count), swizzle.left->lvalue);
+       }
+}
+
 void ExpressionResolver::visit(UnaryExpression &unary)
 {
        TraversingVisitor::visit(unary);