Jump to content

Render Texture mirrors Filters on Y axis


SilverKnightDragon
 Share

Recommended Posts

Hi, I am making a Lighting filter for PIXIJS 4 in RPGmaker MV but I've encountered some strange behavior regarding Render Textures. for some strange reason, rendering the scene to a render textures causes the position of the lights to mirror on the Y axis and I have no idea why.
here are some photo's of what i mean.
Below is a Screenshot of the scene in real time.
realtime.PNG.5c5e9ee47aa2d9c5d4dfa1b9e88b84d0.PNG

 

and this is the resulting render Texture.

RenderTexture.PNG.a13e31d7fefeb15d944234b8beaf5044.PNG

As you can see, the blue light close to thew center barely moved, while the yellow one moved from the bottom of the screen to the top. neither lights changed in X-axis values.  the lights themselves do not move, this only appears in the render texture.

the render texture is generated using this code on one of the RPGmaker Events script call, however the effect seems to be affecting all PIXI render textures, including those used by the default engine.
here is the code the generate the render texture an make a sprite. the sprite is rendered to the scene.

 

rt = PIXI.RenderTexture.create(1280,720);
renderer = Graphics._renderer;
renderer.render(SceneManager._scene, rt);
sprt = new PIXI.Sprite(rt);
SceneManager._scene.addChild(sprt);

 

At first  I thought it may have to do with Transformation Matricies within the shader. As far as i know I couln't find anything obvious. here's a test shader I prepared below below.
 

varying vec2 vTextureCoord;
uniform sampler2D uSampler;

vec4 lightDiffuse(vec2 lposition,vec4 ldiffuse,float lquadratic,float llinear){
    
    float distance=length(lposition-gl_FragCoord.xy);
    float attenuation=1./(1.+llinear*
        distance+
        lquadratic*(distance*distance));
        
        return ldiffuse*attenuation;
    }
    
    void main(){
        
        vec4 result=vec4(0.,0.,0.,0.);
        
        vec4 ambience=vec4(.1,.1,.1,1.);
        //Hard coded light 2
        vec2 lPositionA=vec2(720.,200.);
        vec4 lDiffuseA=vec4(0.,1.,1.,1.);
        
        //Hard coded light 1
        vec2 lPositionB=vec2(100.,125.);
        vec4 lDiffuseB=vec4(1.,1.,0.,1.);
        
        result+=lightDiffuse(lPositionA,lDiffuseA,.07,.05);
        result+=lightDiffuse(lPositionB,lDiffuseB,.007,.005);
        
        gl_FragColor=vec4(ambience.rgb+result.rgb,1)*texture2D(uSampler,vTextureCoord);
    }

 

I've also prepared a test plugin for RPG maker that will load said shader and apply it as a filter the the Scenes Spriteset. (essentially Container containing sprites and tile maps but no UI or system sprites).

Even with those hard coded values, the issue still arises, hence why I though it may a matrix issue.



The plugin loads the loads the shader on start up and stores globally, then when you enter a Map scene, the map sprite will also create a filter for itself that contains the shader code. I can provide a build if its necessary. The code looks for the shader in "/js/Shaders/". the Shaders folter doesnt normally exist in RPGmaker projects.
 

var DSE = DSE || {};
DSE.Lighting = function (_export) {


    _export.shader = null;


    function loadShader(name, type) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', '/js/Shaders/' + name + type);
        xhr.onreadystatechange = _onShaderLoad.bind(this, xhr, type);
        xhr.send();
    }

    function _onShaderLoad(xhr, type) {
        console.log("shader loaded?");

        if (type == ".frag") {
            _export.shader = xhr.responseText;
        }
    }

    loadShader("LightTest", ".frag");

    /**
      * @override 
      */
    Spriteset_Map.prototype.createLowerLayer = function () {
        Spriteset_Base.prototype.createLowerLayer.call(this);
        this.createParallax();
        this.createTilemap();
        this.createCharacters();
        this.createShadow();
        this.createDestination();
        this.createLightLayers();
        this.createWeather();
    };

    Spriteset_Map.prototype.createLightLayers = function () {

        console.log(_export.shader);
        this._filters = [new PIXI.Filter('', _export.shader)];
    };



    return _export;

}({});

upon using both of those files and the script call in a new project the result is the same.

I've yet to look in the PIXI JS file itself , but i figured I'd start either the PIXI.Filter or Render texture classes. I'm not sure exactly how they work, but I hope its simple enough. I couldn't find anything on google about this nor on this forums aside from this: https://github.com/pixijs/pixijs/issues/2074
which upon reading seems to be an entirely different issue. Anyway , I'm posting this here, to make sure it isn't something silly I've done rather than a bug with PIXIJs.
Any advice would be greatly appreciated.
 

Edited by SilverKnightDragon
adding more details
Link to comment
Share on other sites

Hi! You use gl_FragCoord in shader, and its really not reliable in pixi, because pixi renderTextures have flipped Y compared to main framebuffer. This was done to avoid flipping Y of all texture on upload, which is usual way of opengl/webgl.

To avoid that thing, you have to actually use vTextureCoord. According to https://github.com/pixijs/pixijs/wiki/v4-Creating-Filters   , you can get pixel coord from "vTextureCoord * filterArea.xy"  m you need "uniform vec4 filterArea" for that.

Btw, for v5/v6 its different, in case you'll move to next version of rpgmaker

Link to comment
Share on other sites

Thank you that did the trick! I was totally unaware of any internal Y flipping on textures withing the main frame buffer.
It worked everywhere else so that got me. I even visited to that link several times and still didn't get it.

I knew V5 was different when it came to filters, I think you can even use GL structs in in that version. which would definitely help when adding say 24 lights to a scene
(v4 doesn't seem to support them, i had to use banks of arrays to make it work, the type parameter in the uniform data structures seems to pick them up but can't do anything with them.).

For anyone else that has this issue or possibly something similar.
Be sure to have this in the shader when using pixel (or frag) coordinates.

uniform vec4 filterArea;

PIXI JS v4 will pass the values automatically, adding uniforms isn't necessary.


then using my shader code as example replace the gl_FragCoord code with the corresponding one that's used for PIXIJS v4 filters, in this case Line 6 (or 7 after adding the uniform):

float distance=length(lposition-(vTextureCoord*filterArea.xy));


hopefully that helps someone else too.


 

Link to comment
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...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...