Esempio n. 1
0
        public static void parse(String url, String src, OnShadersParsed onload)
        {
            List <shader_t> shaders = new List <shader_t>();

            ShaderTokenizer tokens = new ShaderTokenizer(src);

            // Parse a shader
            while (!tokens.EOF())
            {
                String name = tokens.next();

                shader_t shader = ShaderParser.parseShader(name, tokens);

                if (shader != null)
                {
                    shader.url = url;

                    if (shader.stages != null)
                    {
                        for (var i = 0; i < shader.stages.Count; ++i)
                        {
                            // Build a OpenGL shader program out of the stage parameters set here
                            shader.stages[i].shaderSrc = ShaderParser.buildShaderSource(shader, shader.stages[i]);
                        }
                    }
                }
                shaders.Add(shader);
            }

            // Send shaders to gl Thread
            onload(shaders);
        }
Esempio n. 2
0
        //
        // WebGL Shader creation
        //

        // This whole section is a bit ugly, but it gets the job done. The job, in this case, is translating
        // Quake 3 shaders into GLSL shader programs. We should probably be doing a bit more normalization here.

        public static shader_src_t buildShaderSource(shader_t shader, stage_t stage)
        {
            shader_src_t src = new shader_src_t();

            src.vertex   = ShaderParser.buildVertexShader(shader, stage);
            src.fragment = ShaderParser.buildFragmentShader(shader, stage);
            return(src);
        }
Esempio n. 3
0
        public static shader_t parseShader(String name, ShaderTokenizer tokens)
        {
            string param;
            String brace = tokens.next();

            if (brace != "{")
            {
                return(null);
            }

            shader_t shader = new shader_t();

            shader.name = name;

            // Parse a shader
            while (!tokens.EOF())
            {
                String token = tokens.next().ToLower();

                if (token == "}")
                {
                    break;
                }

                switch (token)
                {
                case "{":
                {
                    stage_t stage = ShaderParser.parseStage(tokens);

                    // I really really really don't like doing this, which basically just forces lightmaps to use the 'filter' blendmode
                    // but if I don't a lot of textures end up looking too bright. I'm sure I'm jsut missing something, and this shouldn't
                    // be needed.
                    if (stage.isLightmap == true && (stage.hasBlendFunc == true))
                    {
                        stage.blendSrc  = "GL_DST_COLOR";
                        stage.blendDest = "GL_ZERO";
                    }

                    // I'm having a ton of trouble getting lightingSpecular to work properly,
                    // so this little hack gets it looking right till I can figure out the problem
                    if (stage.alphaGen == "lightingspecular")
                    {
                        stage.blendSrc     = "GL_ONE";
                        stage.blendDest    = "GL_ZERO";
                        stage.hasBlendFunc = false;
                        stage.depthWrite   = true;
                        shader.stages      = new List <stage_t>();
                    }

                    if (stage.hasBlendFunc == true)
                    {
                        shader.blend = true;
                    }
                    else
                    {
                        shader.opaque = true;
                    }

                    shader.stages.Add(stage);
                }
                break;

                case "cull":
                    shader.cull = tokens.next();
                    break;

                case "deformvertexes":
                    deform_t deform = new deform_t();
                    deform.type = tokens.next().ToLower();

                    switch (deform.type)
                    {
                    case "wave":
                        deform.spread   = 1.0 / double.Parse(tokens.next());
                        deform.waveform = ShaderParser.parseWaveform(tokens);
                        break;

                    default: deform = null; break;
                    }

                    if (deform != null)
                    {
                        shader.vertexDeforms.Add(deform);
                    }
                    break;

                case "sort":
                    String sort = tokens.next().ToLower();

                    switch (sort)
                    {
                    case "portal": shader.sort = 1; break;

                    case "sky": shader.sort = 2; break;

                    case "opaque": shader.sort = 3; break;

                    case "banner": shader.sort = 6; break;

                    case "underwater": shader.sort = 8; break;

                    case "additive": shader.sort = 9; break;

                    case "nearest": shader.sort = 16; break;

                    default: shader.sort = int.Parse(sort); break;
                    }
                    ;
                    break;

                case "surfaceparm":
                    param = tokens.next().ToLower();

                    switch (param)
                    {
                    case "sky":
                        shader.sky = true;
                        break;

                    default: break;
                    }
                    break;

                case "skyparms":
                    param = tokens.next().ToLower();

                    shader.sky_env_map = new sky_env_map_p(param);;

                    break;

                default: break;
                }
            }

            if (shader.sort < 0 || shader.sort == 0)
            {
                shader.sort = (shader.opaque ? 3 : 9);
            }
            //if(!shader['sort']) {
            //shader['sort'] = (shader['opaque'] ? 3 : 9);
            //}

            return(shader);
        }
Esempio n. 4
0
        public static fragment_shader_src_t buildFragmentShader(shader_t stageShader, stage_t stage)
        {
            ShaderBuilder shader = new ShaderBuilder();

            shader.addVaryings("vTexCoord", "vec2");
            shader.addVaryings("vColor", "vec4");

            shader.addUniforms("texture", "sampler2D");
            shader.addUniforms("time", "float");

            shader.addLines("vec4 texColor = texture2D(texture, vTexCoord.st);");

            switch (stage.rgbGen)
            {
            case "vertex":
                shader.addLines("vec3 rgb = texColor.rgb * vColor.rgb;");
                break;

            case "wave":
                shader.addWaveform("rgbWave", stage.rgbWaveform, null);
                shader.addLines("vec3 rgb = texColor.rgb * rgbWave;");
                break;

            default:
                shader.addLines("vec3 rgb = texColor.rgb;");
                break;
            }

            switch (stage.alphaGen)
            {
            case "wave":
                shader.addWaveform("alpha", stage.alphaWaveform, null);
                break;

            case "lightingspecular":
                // For now this is VERY special cased. May not work well with all instances of lightingSpecular
                shader.addUniforms("lightmap", "sampler2D");

                shader.addVaryings("vLightCoord", "vec2");
                shader.addVaryings("vLight", "float");
                shader.addLines(
                    "vec4 light = texture2D(lightmap, vLightCoord.st);",
                    "rgb *= light.rgb;",
                    "rgb += light.rgb * texColor.a * 0.6;",     // This was giving me problems, so I'm ignorning an actual specular calculation for now
                    "float alpha = 1.0;"
                    );
                break;

            default:
                shader.addLines("float alpha = texColor.a;");
                break;
            }

            if (stage.alphaFunc != null)
            {
                switch (stage.alphaFunc)
                {
                case "GT0":
                    shader.addLines("if(alpha == 0.0) { discard; }");
                    break;

                case "LT128":
                    shader.addLines("if(alpha >= 0.5) { discard; }");
                    break;

                case "GE128":
                    shader.addLines("if(alpha < 0.5) { discard; }");
                    break;

                default:
                    break;
                }
            }

            shader.addLines("gl_FragColor = vec4(rgb, alpha);");

            fragment_shader_src_t frag_shader = new fragment_shader_src_t();

            frag_shader.source_code = shader.getSource();
            return(frag_shader);
        }
Esempio n. 5
0
        public static vertex_shader_src_t buildVertexShader(shader_t stageShader, stage_t stage)
        {
            ShaderBuilder shader;
            Dictionary <string, string> attribs, varyings, uniforms;
            List <string> statements;

            shader     = new ShaderBuilder();
            attribs    = new Dictionary <string, string>();
            varyings   = new Dictionary <string, string>();
            uniforms   = new Dictionary <string, string>();
            statements = new List <string>();

            shader.addAttribs("position", "vec3");
            shader.addAttribs("normal", "vec3");
            shader.addAttribs("color", "vec4");

            shader.addVaryings("vTexCoord", "vec2");
            shader.addVaryings("vColor", "vec4");

            shader.addUniforms("modelViewMat", "mat4");
            shader.addUniforms("projectionMat", "mat4");
            shader.addUniforms("time", "float");

            if (stage.isLightmap == true)
            {
                shader.addAttribs("lightCoord", "vec2");
            }
            else
            {
                shader.addAttribs("texCoord", "vec2");
            }

            shader.addLines("vec3 defPosition = position;");

            //shader.addAttribs(attribs);
            //shader.addVaryings(varyings);
            //shader.addUniforms(uniforms);
            //shader.addLines(statements);

            for (int i = 0; i < stageShader.vertexDeforms.Count; ++i)
            {
                deform_t deform = stageShader.vertexDeforms[i];

                switch (deform.type)
                {
                case "wave":
                    String name    = "deform" + i.ToString();
                    String offName = "deformOff" + i.ToString();

                    shader.addLine("float " + offName + " = (position.x + position.y + position.z) * " + ShaderBuilder.toStringAsFixed(deform.spread, 4) + ";");

                    var phase = deform.waveform.phase;
                    deform.waveform.phase = ShaderBuilder.toStringAsFixed((double)phase, 4) + " + " + offName;
                    shader.addWaveform(name, deform.waveform, null);
                    deform.waveform.phase = phase;

                    shader.addLine("defPosition += normal * " + name + ";");
                    break;

                default: break;
                }
            }

            shader.addLine("vec4 worldPosition = modelViewMat * vec4(defPosition, 1.0);");
            shader.addLine("vColor = color;");

            if (stage.tcGen == "environment")
            {
                shader.addLines(
                    "vec3 viewer = normalize(-worldPosition.xyz);",
                    "float d = dot(normal, viewer);",
                    "vec3 reflected = normal*2.0*d - viewer;",
                    "vTexCoord = vec2(0.5, 0.5) + reflected.xy * 0.5;"
                    );
            }
            else
            {
                // Standard texturing
                if (stage.isLightmap == true)
                {
                    shader.addLines("vTexCoord = lightCoord;");
                }
                else
                {
                    shader.addLines("vTexCoord = texCoord;");
                }
            }

            // tcMods
            for (int i = 0; i < stage.tcMods.Count; ++i)
            {
                tcMod_t tcMod = stage.tcMods[i];

                switch (tcMod.type)
                {
                case "rotate":
                    shader.addLines(
                        string.Format("float r = {0} * time;", ShaderBuilder.toStringAsFixed(tcMod.angle, 4)),
                        "vTexCoord -= vec2(0.5, 0.5);",
                        "vTexCoord = vec2(vTexCoord.s * cos(r) - vTexCoord.t * sin(r), vTexCoord.t * cos(r) + vTexCoord.s * sin(r));",
                        "vTexCoord += vec2(0.5, 0.5);"
                        );
                    break;

                case "scroll":
                    double sSpeed = tcMod.sSpeed;     // was tcMod['sSpeed'].toFixed(4)
                    double tSpeed = tcMod.tSpeed;

                    shader.addLines(string.Format("vTexCoord += vec2({0} * time, {1} * time); ", ShaderBuilder.toStringAsFixed(sSpeed, 4), ShaderBuilder.toStringAsFixed(tSpeed, 4)));
                    break;

                case "scale":
                    double scaleX = tcMod.scaleX;
                    double scaleY = tcMod.scaleY;

                    shader.addLines("vTexCoord *= vec2(" + ShaderBuilder.toStringAsFixed(scaleX, 4) + ", " + ShaderBuilder.toStringAsFixed(scaleY, 4) + ");");
                    break;

                case "stretch":
                    shader.addWaveform("stretchWave", tcMod.waveform, null);
                    shader.addLines(
                        "stretchWave = 1.0 / stretchWave;",
                        "vTexCoord *= stretchWave;",
                        "vTexCoord += vec2(0.5 - (0.5 * stretchWave), 0.5 - (0.5 * stretchWave));"
                        );
                    break;

                case "turb":
                    String tName = "turbTime" + i.ToString();
                    shader.addLines(
                        "float " + tName + " = " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.phase, 4) + " + time * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.freq, 4) + ";",
                        "vTexCoord.s += sin( ( ( position.x + position.z )* 1.0/128.0 * 0.125 + " + tName + " ) * 6.283) * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.amp, 4) + ';',
                        "vTexCoord.t += sin( ( position.y * 1.0/128.0 * 0.125 + " + tName + " ) * 6.283) * " + ShaderBuilder.toStringAsFixed(tcMod.turbulance.amp, 4) + ";"
                        );
                    break;

                default: break;
                }
            }

            switch (stage.alphaGen)
            {
            case "lightingspecular":
                shader.addAttribs("lightCoord", "vec2");
                shader.addVaryings("vLightCoord", "vec2");
                shader.addLines("vLightCoord = lightCoord;");
                break;

            default:
                break;
            }

            shader.addLines("gl_Position = projectionMat * worldPosition;");


            vertex_shader_src_t vertex_shader = new vertex_shader_src_t();

            vertex_shader.source_code = shader.getSource();
            return(vertex_shader);
        }