Jump to content

Procedural texture, shader + batching


wnr
 Share

Recommended Posts

Hello,

I'm working on a 2D infinite world built by destructible quads. The quads are rendered procedurally by using a noise shader + color mapping. This because I want to learn shaders, and have no seams or repeating as the camera moves around. I've managed to implement this and all is well, except for the horrible performance of my naive implementation.

I've made an example that captures the gist of my naive implementation, by using n meshes and shaders: https://www.pixiplayground.com/#/edit/kuHFKOZiQsydVdzrP1PrT

When I monitored the scene by using Spector.js, I understood that the problem is the meshes not being batched so that each mesh results in a WebGL drawCall. So having n meshes means n drawCalls. I went further to test having n sprites/geometries without shaders, which indeed performs much faster by being batched into a single drawCall. I tried mesh instancing, which did result in only 1 drawCall, but the performance was still really bad. I don't know why, the only difference I noticed is that the function drawElementsInstanced was being used instead of drawElements...

After reading many many posts on this forum about batching, I came to the conclusion that I needed to implement my own batching plugin. So I've tried, and here is the result: https://www.pixiplayground.com/#/edit/kTcHxuSMF7wvehlHvpQPY

The performance is great, as all meshes are batched into 1 drawCall. However, I get the feeling that this is the wrong approach. Hacking the AbstractBatchRenderer the way I do seems awful, and I'm having a hard time understanding how to handle the uniforms. More specifically, I cannot manage to set my colormap texture uniform correctly, it keeps uploading a white 16x16 texture to WebGL. Also, I don't understand how to send mesh-instance specific uniforms to my plugin shader, like "uWorldPosition" in my example.

I would really appreciate some help, as I've banged my head against this for a week now 😅

 Cheers

Link to comment
Share on other sites

> Hacking the AbstractBatchRenderer the way I do seems awful

Its supposed to be this way :)

I'm having a hard time understanding how to handle the uniforms. 

ShukantPal approach : https://api.pixijs.io/pixi-batch-renderer.html

my approach: https://github.com/pixijs/pixi-projection/blob/master/src/base/webgl/UniformBatchRenderer.ts

here I stop batch if sprite uses different "uniforms" object (I compare as a link, not fields)

 it keeps uploading a white 16x16 texture to WebGL

The thing is , first MAX_TEXTURES units are needed for batching purposes, and by default pixi texture in shader is bound to 0, 1 , e.t.c. which contradics batching.

However, in AbstractBatchRenderer  you can add more features by overriding certain methods. There's `buildTexturesAndDrawCalls` in it, that can be hacked to take one more texture into account. For example, for my masked renderer( maskSprite ) I added one more texture in texture array: https://github.com/pixijs/pixi-heaven/blob/eb554499afe3fcbb42bb4d4f77edb2ee0c27b7fa/src/twotint/sprites/MaskedBatchRenderer.ts#L148-L210 . You can compare it and vanilla pixi implementations to understand what is going on there.

====

Current AbstractBatchRenderer architecture exists because of mine and ShukantPal's plugins. I've banged the head against it for many hours long time ago.

Edited by ivan.popelyshev
Link to comment
Share on other sites

Thank you Ivan,

I've now managed to create two solutions that are able to render my desired output with great performance. One approach is to hack the AbstractBatchRenderer (per your suggestion) like so: https://www.pixiplayground.com/#/edit/VgBCR9r6_ZLx94VzCC_Fn . Is this how you would have done? I had to remove the texture binding in order for my colormap uniform texture to work.

Another approach that performs great is to use mesh instancing like so: https://www.pixiplayground.com/#/edit/k3LQY3-KoA0E61Nu07UBI . However, it seems a bit tedious to remove/add instances. 

What are the pros/cons of these two approaches? In the plugin approach, I had to add the "uWorldPosition" uniform in order to keep track of the global world position of each vertex. I was surprised that it was not needed in the mesh instancing approach. I think my understanding of the transforms are too low, perhaps this is a bit off topic 😛 

Thank you for your input!

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...