Example #1
0
        public string GenerateCode(NodeHelper <TranslatedMaterialGraph.NodeInfo> node)
        {
            if (node.Type == NodeTypes.Special.Variable)
            {
                return(GenerateVarCode(node));
            }
            if (node.Extra.Define.IsIfDef)
            {
                return(GenerateIfDef(node));
            }
            //if (node.Type == NodeTypes.Texture2DSampler2DVec2
            //    || node.Type == NodeTypes.Texture2DSampler2DVec2Float
            //    || node.Type == NodeTypes.TextureCubeSamplerCubeVec3
            //    || node.Type == NodeTypes.TextureCubeSamplerCubeVec3Float
            //    )
            //{
            //    if (node.InputPins["sampler"].Links.Count == 0)
            //    {
            //        return "vec4(0.0,0.0,0.0,0.0)";
            //    }
            //}
            var args = node.InputPins.Select(_ => GenerateCode(_)).ToList();

            if (NodeTypes.IsConnectorType(node.Type))
            {
                return(args[0]);
            }
            if (NodeTypes.IsIfDefType(node.Type))
            {
                throw new InvalidOperationException("ifdef should be handeled at var code path");
            }

            if (node.Type == NodeTypes.VertexData)
            {
                return("i" + node.OutputPins[0].Id);
            }

            if (NodeTypes.IsAttribute(node.Type))
            {
                if (node.Name == "BlendIndices")
                {
                    return("ivec4(i" + node.Name + ")");
                }
                return("i" + node.Name);
            }

            if (NodeTypes.IsUniform(node.Type))
            {
                return("c" + node.Name);
            }
            if (NodeTypes.IsParameter(node.Type))
            {
                return("c" + node.Name);
            }

            string constType;

            if (NodeTypes._constants.TryGetValue(node.Type, out constType))
            {
                return(GetConstantValue(node.Value, constType));
            }
            switch (node.Type)
            {
            case NodeTypes.Function:
                return(node.Name + "(" + string.Join(",", args) + ")");

            case NodeTypes.Special.Default:
                return(GenerateDefaultValue(node.OutputPins[0].Type));

            case NodeTypes.Special.ShadowMapOutput:
                _writer.WriteLine(null, "    #ifdef VSM_SHADOW");
                _writer.WriteLine(null, "        float depth = " + args[0] + ".x / " + args[0] + ".y * 0.5 + 0.5;");
                _writer.WriteLine(null, "        gl_FragColor = vec4(depth, depth * depth, 1.0, 1.0);");
                _writer.WriteLine(null, "    #else");
                _writer.WriteLine(null, "        gl_FragColor = vec4(1.0);");
                _writer.WriteLine(null, "    #endif");
                return(null);

            case NodeTypes.Special.FinalColor:
                _writer.WriteLine(null, "gl_FragColor = " + args[0] + ";");
                return(null);

            case NodeTypes.Special.FragData0:
                _writer.WriteLine(null, "gl_FragData[0] = " + args[0] + ";");
                return(null);

            case NodeTypes.Special.FragData1:
                _writer.WriteLine(null, "gl_FragData[1] = " + args[0] + ";");
                return(null);

            case NodeTypes.Special.FragData2:
                _writer.WriteLine(null, "gl_FragData[2] = " + args[0] + ";");
                return(null);

            case NodeTypes.Special.FragData3:
                _writer.WriteLine(null, "gl_FragData[3] = " + args[0] + ";");
                return(null);

            case NodeTypes.FragCoord:
                return("gl_FragCoord");

            case NodeTypes.FrontFacing:
                return("gl_FrontFacing");

            case NodeTypes.LightColor:
            case NodeTypes.Opacity:
            case NodeTypes.AmbientColor:
            case NodeTypes.RefractionColor:
            case NodeTypes.PerPixelFloat:
            case NodeTypes.PerPixelVec2:
            case NodeTypes.PerPixelVec3:
            case NodeTypes.PerPixelVec4:
                return(args[0]);

            case NodeTypes.ObjectData:
            case NodeTypes.LightData:
            case NodeTypes.CameraData:
            case NodeTypes.ZoneData:
                throw new InvalidOperationException(
                          "This code shouldn't be executed. All uniforms must be split into individual nodes on preprocessing.");

            case NodeTypes.Special.SetVarying: {
                var arg         = args[0];
                var actualType  = GetType(node.InputPins[0].Type);
                var varyingType = GetVaryingType(node.InputPins[0].Type);
                if (actualType != varyingType)
                {
                    arg = varyingType + "(" + arg + ")";
                }
                var connectedNode = node.InputPins[0].ConnectedPins.FirstOrDefault()?.Node;
                if (connectedNode != null && addComments)
                {
                    _writer.WriteLine(null,
                                      "// based on node " + connectedNode.Name + " " + connectedNode.Value + " (type:" + connectedNode.Type +
                                      ", id:" + connectedNode.Id + "), cost estimation: " + connectedNode.Extra.EstimatedCost);
                }

                _writer.WriteLine(node.Extra.Define.Expression, "v" + node.Value + " = " + arg + ";");
            }
                return(null);

            case NodeTypes.Discard:
                _writer.WriteLine(null, "if (" + args[0] + ") discard;");
                return(null);

            case NodeTypes.Special.GetVarying: {
                var arg         = "v" + node.Value;
                var actualType  = GetType(node.OutputPins[0].Type);
                var varyingType = GetVaryingType(node.OutputPins[0].Type);
                if (actualType != varyingType)
                {
                    arg = actualType + "(" + arg + ")";
                }
                return(arg);
            }

            case NodeTypes.Sampler2D:
            case NodeTypes.Sampler3D:
            case NodeTypes.SamplerCube:
                return(GetSamplerName(node));

            //_writer.WriteLine("uniform "+node.OutputPins.First().Type+" s" + GetSamplerName(node) + ";");
            case NodeTypes.BreakVec4ToVec3AndFloat:
            case NodeTypes.BreakVec3ToVec2AndFloat:
            case NodeTypes.BreakVec4ToVec2AndVec2:
            case NodeTypes.BreakVec4ToVec2AndFloats:
            case NodeTypes.BreakVec2:
            case NodeTypes.BreakVec3:
            case NodeTypes.BreakVec4:
                if (node.OutputPins.Count != 1)
                {
                    throw new InvalidOperationException(node + " expected to have a single output.");
                }
                return(args[0] + "." + node.OutputPins[0].Id.ToLower());

            case NodeTypes.MultiplyFloatFloat:
            case NodeTypes.MultiplyVec2Float:
            case NodeTypes.MultiplyVec3Float:
            case NodeTypes.MultiplyVec4Float:
            case NodeTypes.MultiplyVec2Vec2:
            case NodeTypes.MultiplyVec3Vec3:
            case NodeTypes.MultiplyVec4Vec4:
            case NodeTypes.MultiplyVec4Mat4:
            case NodeTypes.MultiplyVec3Mat3:
            case NodeTypes.MultiplyMat3Vec3:
            case NodeTypes.MultiplyMat4x3Float:
            case NodeTypes.MultiplyMat4Float:
                return(GenBinaryOperator("*", args));

            case NodeTypes.MultiplyVec4Mat4x3:
                return("(" + GenBinaryOperator("*", args) + ").xyz");

            //case NodeTypes.MultiplyVec3Mat4:
            //case NodeTypes.MultiplyVec3Mat4x3:
            //    return GenBinaryOperator("*", new []{ "vec4("+args[0]+", 1.0)", args[1] });
            case NodeTypes.AddFloatFloat:
            case NodeTypes.AddVec2Vec2:
            case NodeTypes.AddVec3Vec3:
            case NodeTypes.AddVec4Vec4:
            case NodeTypes.AddMat4Mat4:
            case NodeTypes.AddMat4x3Mat4x3:
                return(GenBinaryOperator("+", args));

            case NodeTypes.SubtractFloatFloat:
            case NodeTypes.SubtractVec2Vec2:
            case NodeTypes.SubtractVec3Vec3:
            case NodeTypes.SubtractVec4Vec4:
                return(GenBinaryOperator("-", args));

            case NodeTypes.MinusFloat:
            case NodeTypes.MinusVec2:
            case NodeTypes.MinusVec3:
            case NodeTypes.MinusVec4:
                return(GenUnaryOperator("-", args));

            case NodeTypes.SaturateFloat:
                return("clamp(" + args[0] + ", 0.0, 1.0)");

            case NodeTypes.SaturateVec2:
                return("clamp(" + args[0] + ", vec2(0.0, 0.0), vec2(1.0, 1.0))");

            case NodeTypes.SaturateVec3:
                return("clamp(" + args[0] + ", vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0))");

            case NodeTypes.SaturateVec4:
                return("clamp(" + args[0] + ", vec4(0.0, 0.0, 0.0, 0.0), vec4(1.0, 1.0, 1.0, 1.0))");

            case NodeTypes.DivideFloatFloat:
            case NodeTypes.DivideVec2Float:
            case NodeTypes.DivideVec3Float:
            case NodeTypes.DivideVec4Float:
            case NodeTypes.DivideVec2Vec2:
            case NodeTypes.DivideVec3Vec3:
            case NodeTypes.DivideVec4Vec4:
                return(GenBinaryOperator("/", args));

            case NodeTypes.TernaryFloat:
            case NodeTypes.TernaryVec2:
            case NodeTypes.TernaryVec3:
            case NodeTypes.TernaryVec4:
                return("((" + args[0] + ")?(" + args[1] + "):(" + args[2] + "))");

            case NodeTypes.MakeVec4FromVec3:
                return(node.OutputPins[0].Type + "(" + string.Join(", ", args) + ", 1.0)");

            case NodeTypes.MakeMat4x3FromVec4Vec4Vec4:
                return("mat4(" + string.Join(", ", args) + ", vec4(0.0, 0.0, 0.0, 1.0))");

            case NodeTypes.MakeVec4FromVec3AndFloat:
            case NodeTypes.MakeVec4FromVec2AndVec2:
            case NodeTypes.MakeVec3FromVec2AndFloat:
            case NodeTypes.MakeVec2:
            case NodeTypes.MakeVec3:
            case NodeTypes.MakeVec4:
            case NodeTypes.MakeMat3FromVec3Vec3Vec3:
                return(node.OutputPins[0].Type + "(" + string.Join(", ", args) + ")");

            case NodeTypes.MakeMat3FromMat4:
            case NodeTypes.MakeMat3FromMat4x3:
                return("GetNormalMatrix(" + string.Join(", ", args) + ")");

            case NodeTypes.SampleVSMShadow:
                return("texture2D(" + string.Join(", ", args) + ").rg");

            case NodeTypes.SkinMatrixIndex:
                return("mat4(" + args[0] + "[" + args[1] + "*3], " +
                       args[0] + "[" + args[1] + "*3+1]," +
                       args[0] + "[" + args[1] + "*3+2], vec4(0.0, 0.0, 0.0, 1.0))");

            case NodeTypes.LightMatricesIndex:
            case NodeTypes.VertexLightsIndex:
                return(args[0] + "[" + args[1] + "]");

            case NodeTypes.PositionOutput:
                return(args[0]);

            case NodeTypes.LessThanFloatFloat:
                return(GenBinaryOperator("<", args));

            case NodeTypes.NotBool:
                return("!(" + args[0] + ")");

            case NodeTypes.EqualFloatFloat:
                return(GenBinaryOperator("==", args));

            case NodeTypes.NotEqualFloatFloat:
                return(GenBinaryOperator("!=", args));

            case NodeTypes.GreaterThanFloatFloat:
                return(GenBinaryOperator(">", args));

            case NodeTypes.LessThanEqualFloatFloat:
                return(GenBinaryOperator("<=", args));

            case NodeTypes.GreaterThanEqualFloatFloat:
                return(GenBinaryOperator(">=", args));

            case NodeTypes.AndAlso:
                return(GenBinaryOperator("&&", args));

            case NodeTypes.OrElse:
                return(GenBinaryOperator("||", args));

            default:
                var bracketIndex = node.Type.IndexOf("(");
                if (bracketIndex > 0)
                {
                    return(node.Type.Substring(0, bracketIndex) + "(" + string.Join(", ", args) + ")");
                }
                throw new MaterialCompilationException("Node " + node.Type + " isn't implemented yet.", node.Id);
            }
        }