phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
37.12k stars 7.1k forks source link

Phaser rendering black screen depending on how I instantiate a shader #4758

Closed alexandernst closed 5 years ago

alexandernst commented 5 years ago

Version

Description

If I create a shader using this.add.shader(), I get the expected result (a blurred image rendered in my camera view), but if I create that same shader using new Phaser.GameObjects.Shader(), I get a black screen.

Example Test Code

Check lines 95 and 96. Commenting line 95 and uncommenting line 96 produces a black screen. https://codepen.io/alexandernst/pen/aboKepQ?editors=1010

Additional Information

Inserting a few console.log() with non-existant variables before the setRenderToTexture call, instead of black screen I get the original (unblurred) image. This makes me think that this might be some sort of race condition bug.

pavel-shirobok commented 5 years ago

@alexandernst Hi, I guess the main problem is you don't add it to update list/scene. So this.add.existing(shader) fix the problem on your codepen.

alexandernst commented 5 years ago

But why would I add the shader to the scene? This is not what I want to do. I'm creating a shader, rendering a texture (the image) inside it, and then I render the result to a texture, which I then apply (with the setTexture() method) to the image that's inside my scene.

In theory, I shouldn't have to add the shader to the scene. Is that correct or am I misreading the docs?

pavel-shirobok commented 5 years ago

I guess problem is not that it should be on scene, but it should be in update list, as phaser can dont know about your shader, as you've no registered it in any places. I'm not an expert or developer of this repo, but I can suggest you to try make 2 things:

alexandernst commented 5 years ago

I ran some more tests, and I don't the update list is the problem here. Check for example this demo: https://codepen.io/alexandernst/pen/JjPwNJa?editors=0010#0

I'm doing the following things (in that order):

The result keeps being a black screen, but note that I'm using this.add, so this should be adding everything to the scene.

alexandernst commented 5 years ago

I was able to fix my problem :)

blur.glsl

#ifdef GL_ES
precision mediump float;
#endif

const float pi = 3.141592653589793238462643383279502884; // atan(1.0) * 4.0;
uniform vec2 resolution;
uniform sampler2D iChannel0;

varying vec2 fragCoord;

float normpdf(in float x, in float sigma) {
    return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
}

vec4 texture(sampler2D s, vec2 c) {
  return texture2D(s, c);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec4 c = texture(iChannel0, fragCoord.xy / resolution.xy);

    //declare stuff
    const int mSize = 7;
    const int kSize = (mSize - 1) / 2;
    float kernel[mSize];
    vec4 final_colour = vec4(0.0);

    //create the 1-D kernel
    float sigma = 7.0;
    float Z = 0.0;
    for (int j = 0; j <= kSize; ++j) {
        kernel[kSize + j] = kernel[kSize - j] = normpdf(float(j), sigma);
    }

    //get the normalization factor (as the gaussian has been clamped)
    for (int j = 0; j < mSize; ++j) {
        Z += kernel[j];
    }

    //read out the texels
    for (int i = -kSize; i <= kSize; ++i) {
        for (int j=-kSize; j <= kSize; ++j) {
            final_colour += kernel[kSize + j] * kernel[kSize + i] * texture(iChannel0, (fragCoord.xy + vec2(float(i), float(j))) / resolution.xy);
        }
    }

    fragColor = (final_colour / (Z * Z));
}

void main(void) {
    mainImage(gl_FragColor, fragCoord.xy);
}

my js

import "phaser";
import fizzbuzz from "./assets/codes/fizzbuzz.bbcode";
import blur from "./shaders/blur.glsl";

export default class WIP extends Phaser.Scene {
    constructor(config) {
        super({
            key: "WIP"
        });
    }

    create() {
        this.code = this.add.rexBBCodeText(0, 0);
        this.code.typing = this.plugins.get("TextTypingPlugin").add(this.code, {
            speed: 1,
            typeMode: "left-to-right",
        }).start(fizzbuzz);
        this.code.setVisible(false);

        // Render texture
        this.renderTexture = this.make.renderTexture({ width: 2048, height: 2048, add: false });

        // Shader model
        const blur_baseshader = new Phaser.Display.BaseShader('blur', blur);
        this.shader = this.add.shader(blur_baseshader, 0, 0, 2048, 2048);
        this.shader.setSampler2DBuffer('iChannel0', this.renderTexture.glTexture, 2048, 2048, 0);
        this.shader.setRenderToTexture('BlurBuffer', true);

        // Image that will be used to draw the shader output
        this.add.image(10, 10, 'BlurBuffer').setOrigin(0);
    }

    update(time, delta) {
        this.renderTexture.clear();
        this.renderTexture.draw(this.code, 40, 0);
    }
}