pixijs / lights

Adds dynamic lighting via deferred shading to PixiJS
https://pixijs.io/lights/docs/index.html
MIT License
198 stars 29 forks source link

no clearBeforeRender #12

Open gillesboisson opened 8 years ago

gillesboisson commented 8 years ago

Hello,

Renderer does not clear its content before rendering, even if force clearBeforeRenderboolean to true. Otherwise, this is great start, good work guys.

Regards,

mw4ll4c3 commented 8 years ago

Well... technically, yes it does clear before rendering! But there are three targets across passes.

1 & 2: The "diffuse" and "normal" steps are rendered to two texture targets, which are then 3: used by the lighting system, to render to the real target. 4: Any unlit elements are drawn on top of this, to the real target.

It's the RenderTextures in Passes 1 & 2 that aren't being cleared. Two ways to do that:

a: If you feel comfortable rebuilding, add these two lines to WebGLDeferredRender.render(), before or after the textures are filled and used. (I chose "before" so I can use the textures in Pass 4, for visual debugging.)

this.diffuseTexture.clear();
this.normalsTexture.clear();

b: If you just want it to work for now, you should be able to do the same thing in your loop, before-or-after each distinct render call e.g.

myRenderer.render(myContainer);
myRenderer.diffuseTexture.clear();
myRenderer.normalsTexture.clear();

Just be aware there are lots of other things "missing" from this exceptionally clever piece of groundwork. It's enabled only for standard sprites, and accurate only at the original angle and aspect.

I've got some code which addresses some of that, and more, which I will try to put up soon. I hit a few snags, but if someone else is looking / testing it's probably the time to just do it.

gillesboisson commented 8 years ago

Thanks for the feedback, Looks very promising, I'll try to find some time to learn more about PixiJS and shader and see if can give a hand. I also see that we need to copy the diffuse texture alpha channel to its normal texture, otherwise you have le lighting applied to its transparent part. I'll take a look on it

cheers mate

mw4ll4c3 commented 8 years ago

Good eye and testing! It goes both ways: you can paint color over the lighting info, and paint lighting info over the color.

Deferred lighting (Pass 3) is "naive" and performed in screen-space. Meaning which object is which doesn't matter... just the two flat images produced, of the entire scene.

Check out the image (below) from my local WIP, with the "visual debug" I mentioned above. The top is "right" and the bottom is "wrong."

Obviously, if it's practical, you want to prepare the assets that way ahead of time. Doing it per-frame would be way too costly (a more complicated shader, AND you must upload/bind two textures at once. You'd likely end up with smaller batches / more draw calls (for each Diffuse-and-Normal combination.)

You might be able to do work something out using masking (you still pay per-frame, but less.) Or perhaps sacrifice some memory and preprocess the textures at load time / sprite creation time? There are many methods at your disposal, see https://pixijs.github.io/docs/PIXI.Texture.html https://pixijs.github.io/docs/PIXI.RenderTexture.html

Something similar needs to be done anyway for the normal map textures. The artifacts on the sprites' edges are due to it blending with #0000 or #FFF0... which is how 99% of image editors save fully-transparent pixels in PNG format :(

Those are already "bad values" for normal mapping... but then they get "rotated" with the rest of the colors... wreaking absolute havoc! (Also a problem that could be solved at asset-level, but more complicated and software-dependent.)

dont-mess-up-your-clipping

gillesboisson commented 8 years ago

thanks for the details, I was also thinking finding a way to apply for each sprites its rotation when it render the scene normal map. I investigated on how pixijs SpriteRender / TextureShader work and I didn't find a clean way to extends this two class without touching pixijs core classes. I'll post few question on pixijs repo cheers

ivanpopelyshev commented 6 years ago

Solution for current v4 version (http://pixijs.io/examples/#/layers/normals.js)

need extra black sprite for diffuse, then you can use any background or foreground you want.

 var diffuseLayer = new PIXI.display.Layer(PIXI.lights.diffuseGroup);
  diffuseLayer.clearColor = [0,0,0,0];
  stage.addChild(diffuseLayer);
  var blackSprite = new PIXI.Sprite(diffuseLayer.getRenderTexture());
  blackSprite.tint = 0;
  stage.addChild(blackSprite);
  stage.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
  stage.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));