Rammschnev

Accessing Multiple Textures in PIXI Filter

Recommended Posts

I am trying to create a fragment shader via a PIXI.AbstractFilter to create a wave rippling effect to be applied to a background texture. I have already worked out the algorithm for the wave effect in JavaScript. What I am having difficulty doing is getting the data I need into the shader through PIXI.

For my effect to work, I need to have a large Float32Array to keep track of wave heights and a texture containing the original, unaltered contents of the background image to read from in order to apply the effect of pixel displacement (light refraction). I've been doing a lot of searching and have come up with some partial solutions. I attempt to load my large Float32Array into the shader as a texture with type GL.FLOAT (with the OES_texture_float extension) and an internal format of GL.LUMINANCE and read from it. From what I can tell, my shader isn't receiving my data the way I need it to. Just as a test, I set gl_FragColor to read from my data texture, and instead of the solid black that should have appeared, it rendered a color from either the source texture or the texture of the sprite that the filter is applied to.If I weren't using PIXI, what I would try next is to use gl.getUniformLocation, but it takes the current program as its first parameter, and I don't know of a way to access that.

The basic flow of my shader needs to go:

Read From Array -> Calculate displacement based on value -> Render the current fragment as the color at x+displacement, y+displacement -> Get updated version of array

This is my code in the constructor for my shader:

ws.Shader = function(tex) {
        // GLSL Fragment Shader for Wave Rendering
        ws.gl = game.renderer.gl;
        ws.flExt = ws.gl.getExtension("OES_texture_float");
        
        var unis = {
            
            dataTex: {
                type: "sampler2D",
                value: ws.gl.TEXTURE1
            },
            
            canvasTex: {
                type: "sampler2D",
                value: ws.gl.TEXTURE2
            },
        
            mapSize: {
                type: "2f",
                value: [ws.width+2,ws.height+2]
            },
            
            dispFactor: {
                type: "1f",
                value: 20.0
            },
            
            lumFactor: {
                type: "1f",
                value: 0.35
            }
            
        };
        
        var fragSrc = [
        "precision mediump float;",
        "varying vec2 vTextureCoord;",
        "varying vec4 vColor;",
        "uniform sampler2D uSampler;",
            
        "uniform sampler2D dataTex;",
        "uniform sampler2D canvasTex;",
            
        "uniform vec2 mapSize;",
        "uniform float dispFactor;",
        "uniform float lumFactor;",
            
        "void main(void) {",
            "vec2 imgSize = vec2(mapSize.x-2.0,mapSize.y-2.0);",
            "vec2 mapCoord = vec2((vTextureCoord.x*imgSize.x)+1.5,(vTextureCoord.y*imgSize.y)+1.5);",
            "float wave = texture2D(dataTex, mapCoord).r;",
            "float displace = wave*dispFactor;",
            
            "if (displace < 0.0) {",
                "displace = displace+1.0;",
            "}",
            
            "vec2 srcCoord = vec2((vTextureCoord.x*imgSize.x)+displace,(vTextureCoord.y*imgSize.y)+displace);",
            
            "if (srcCoord.x < 0.0) {",
                "srcCoord.x = 0.0;",
            "}",
            "else if (srcCoord.x > mapSize.x-2.0) {",
                "srcCoord.x = mapSize.x-2.0;",
            "}",
            
            "if (srcCoord.y < 0.0) {",
                "srcCoord.y = 0.0;",
            "}",
            "else if (srcCoord.y > mapSize.y-2.0) {",
                "srcCoord.y = mapSize.y-2.0;",
            "}",
            
            /*"srcCoord.x = srcCoord.x/imgSize.x;",
            "srcCoord.y = srcCoord.y/imgSize.y;",*/
            
            "float lum = wave*lumFactor;",
            "if (lum > 40.0) { lum = 40.0; }",
            "else if (lum < -40.0) { lum = -40.0; }",
            
            "gl_FragColor = texture2D(canvasTex, vec2(0.0,0.0));",
            "gl_FragColor.r = gl_FragColor.r + lum;",
            "gl_FragColor.g = gl_FragColor.g + lum;",
            "gl_FragColor.b = gl_FragColor.b + lum;",
            
        "}"];
        
        ws.shader = new PIXI.AbstractFilter(fragSrc, unis);
        
        // Send empty wave map to WebGL
        ws.activeWaveMap = new Float32Array((ws.width+2)*(ws.height+2));
        ws.dataPointerGL = ws.gl.createTexture();
        ws.gl.activeTexture(ws.gl.TEXTURE1);
        ws.gl.bindTexture(ws.gl.TEXTURE_2D, ws.dataPointerGL);
        
        // Non-Power-of-Two Texture Dimensions
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_MIN_FILTER, ws.gl.NEAREST);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_S, ws.gl.CLAMP_TO_EDGE);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_T, ws.gl.CLAMP_TO_EDGE);
        
        ws.gl.texImage2D(ws.gl.TEXTURE_2D, 0, ws.gl.LUMINANCE, ws.width+2,ws.height+2,0, ws.gl.LUMINANCE, ws.gl.FLOAT, ws.activeWaveMap);
        
        // Send texture data from canvas to WebGL
        var canvasTex = ws.gl.createTexture();
        ws.gl.activeTexture(ws.gl.TEXTURE2);
        ws.gl.bindTexture(ws.gl.TEXTURE_2D, canvasTex);
        
        // Non-Power-of-Two Texture Dimensions
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_MIN_FILTER, ws.gl.NEAREST);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_S, ws.gl.CLAMP_TO_EDGE);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_T, ws.gl.CLAMP_TO_EDGE);
        
        ws.gl.texImage2D(ws.gl.TEXTURE_2D, 0, ws.gl.RGBA, ws.gl.RGBA, ws.gl.UNSIGNED_BYTE, tex.imageData);
    }

I then attempt to update dataTex in the ws object's update loop:

        ws.activeWaveMap.set(ws.outgoingWaveMap);
        
        // WebGL Update
        ws.gl.activeTexture(ws.gl.TEXTURE1);
        ws.gl.bindTexture(ws.gl.TEXTURE_2D, ws.dataPointerGL);
        
        /*
        // Non-Power-of-Two Texture Dimensions
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_MIN_FILTER, ws.gl.NEAREST);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_S, ws.gl.CLAMP_TO_EDGE);
        ws.gl.texParameteri(ws.gl.TEXTURE_2D, ws.gl.TEXTURE_WRAP_T, ws.gl.CLAMP_TO_EDGE);*/
        
        ws.gl.texImage2D(ws.gl.TEXTURE_2D, 0, ws.gl.LUMINANCE, ws.width+2,ws.height+2,0, ws.gl.LUMINANCE, ws.gl.FLOAT, ws.activeWaveMap);

I'm sure that plenty of this isn't right, but I believe that I can sort things out once I can get to the point where I can actually access my data. Can anyone point me in the right direction? This is central enough to my project that I am willing to discard PIXI altogether if there isn't a way to implement what I am trying to do. Also, I am using PIXI via Phaser, if that makes a difference.

Thanks!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.