Newer
Older
pixi.js / src / core / shader / Shader.js
@Mat Groves Mat Groves on 11 Jan 2017 3 KB renamed Mesh to RawMesh
import extractUniformsFromSrc from './extractUniformsFromSrc';
import extractAttributesFromSrc from './extractAttributesFromSrc';
import generateUniformsSync from './generateUniformsSync';

let UID = 0;

// let math = require('../../../math');
/**
 * @class
 * @memberof PIXI
 * @extends PIXI.Shader
 */
class Shader
{
    /**
     * @param {string} [vertexSrc] - The source of the vertex shader.
     * @param {string} [fragmentSrc] - The source of the fragment shader.
     * @param {object} [uniforms] - Custom uniforms to use to augment the built-in ones.
     */
    constructor(vertexSrc, fragmentSrc, uniforms)
    {
        /**
         * The vertex shader.
         *
         * @member {string}
         */
        this.vertexSrc = vertexSrc || Shader.defaultVertexSrc;

        /**
         * The fragment shader.
         *
         * @member {string}
         */
        this.fragmentSrc = fragmentSrc || Shader.defaultFragmentSrc;

        // pull out the vertex and shader uniforms if they are not specified..
        // currently this does not extract structs only default types
        this.uniformData = uniforms || extractUniformsFromSrc(this.vertexSrc, this.fragmentSrc);
        // TODO - 'projectionMatrix|uSampler|translationMatrix');

        this.attributeData = extractAttributesFromSrc(this.vertexSrc);

        this.uniforms = {};

        // time to build some getters and setters!
        // I guess down the line this could sort of generate an instruction list rather than use dirty ids?
        // does the trick for now though!
        for (const i in this.uniformData)
        {
            if (!this.uniforms[i])
            {
                this.uniforms[i] = this.uniformData[i].value;
            }
        }

        // this is where we store shader references..
        // TODO we could cache this!
        this.glShaders = {};

        this.syncUniforms = generateUniformsSync(this.uniformData);
        this.id = UID++;
    }

    /**
     * The default vertex shader source
     *
     * @static
     * @constant
     */
    static get defaultVertexSrc()
    {
        return [
            'attribute vec2 aVertexPosition;',
            'attribute vec2 aTextureCoord;',

            'uniform mat3 projectionMatrix;',
            'uniform mat3 filterMatrix;',

            'varying vec2 vTextureCoord;',
            'varying vec2 vFilterCoord;',

            'void main(void){',
            '   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);',
            '   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;',
            '   vTextureCoord = aTextureCoord ;',
            '}',
        ].join('\n');
    }

    /**
     * The default fragment shader source
     *
     * @static
     * @constant
     */
    static get defaultFragmentSrc()
    {
        return [
            'varying vec2 vTextureCoord;',
            'varying vec2 vFilterCoord;',

            'uniform sampler2D uSampler;',
            'uniform sampler2D filterSampler;',

            'void main(void){',
            '   vec4 masky = texture2D(filterSampler, vFilterCoord);',
            '   vec4 sample = texture2D(uSampler, vTextureCoord);',
            '   vec4 color;',
            '   if(mod(vFilterCoord.x, 1.0) > 0.5)',
            '   {',
            '     color = vec4(1.0, 0.0, 0.0, 1.0);',
            '   }',
            '   else',
            '   {',
            '     color = vec4(0.0, 1.0, 0.0, 1.0);',
            '   }',
            '   gl_FragColor = mix(sample, masky, 0.5);',
            '   gl_FragColor *= sample.a;',
            '}',
        ].join('\n');
    }
}

export default Shader;