-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Draft] WebGL2 Multisample Renderbuffers #8120
Conversation
I've written multiple before for OpenGL. Did you check to see which multi-sample levels are available before setting them? I think that is necessary for robustness. |
@bhouston The spec already checks against MAX_SAMPLES and generates an INVALID_OPERATION error if above threshold. We could add that check for robustness and better error messaging before setting up the render buffer storage, throwing a I'm not sure how to detect the possible sample levels. Seems like it needs to be power of two and based on the sized internal format of the render buffer. See |
Ok, FireFox Nightly now supports multisample renderbuffers so we can start testing a bit. Here is a nice easy reference: Notes:
The last two points introduces a bit of architectural changes. I'm not sure how best to implement with ThreeJS codebase, but I'll poke around. |
@mattdesl This is very nice work you are doing. :) What we did to make our code simple is that we required people to create a texture for our MS render target, just like one creates a texture for non-MS render targets. But we didn't use it during MS rendering, but we used it as the write (not read) target for the MS render target (the 0-sampled FBO.) Thus we had a "commit"-type function that would read the MS render target to the texture. |
The benefit of the above design is that whether we did MS or non-MS, there was always a texture with the results of the render. Now we were not rendering to screen, which may introduce more design issues. |
@bhouston That's nice, I think I'll do the same. It looks like ThreeJS doesn't set up any color buffer render storage, which is needed for MSAA. I can implement a way that it only sets up specific color buffer render storage with MSAA targets, but it seems like it would be simpler to have all render targets specify a color buffer storage. |
Hmm the only thing with your approach is that the sample counts need to match. Say user creates a RenderTarget with samples=4, internally we need two WebGLRenderTargets; one with samples=4 and one with samples=0. Then we "commit" (blit) the framebuffers to make it all transparent to the user, so they are just operating on the internal samples=0 target. Is that correct? |
Yeah, you have the idea I was trying to communicate. Also, I'm not saying this is the best idea, it is just what we did. You could also make subclass of WebGLRenderTarget that contains the second MSAA one, and has a commit to the first. This way you can pass the MultiSampleWebGLRenderTarget into the code that uses just a WebGLRenderTarget and it will work. But that code could detect if it is a MSAA one (such as WebGLRenderer) and use the advanced features, commiting after it is done so that the class is still compatible with everything else. |
…n hold its own FBO/Renderbuffers
Ok, now it looks like this: var target = new THREE.WebGLRenderTargetMultisample(window.innerWidth, window.innerHeight);
target.texture.minFilter = THREE.LinearFilter;
target.texture.format = THREE.RGBFormat;
target.texture.generateMipmaps = false;
target.stencilBuffer = false;
target.depthBuffer = true;
target.samples = 8; If samples is zero, or if the context is WebGL1, the above has the same behaviour as normal WebGLRenderTarget. It uses RGB8 or RGBA8 for internal formats (needs to match the 0-sample texture for blitting), so other ThreeJS texture formats won't work right now. It will try to use The code changes don't support MSAA cube targets. Maybe another design/architectural style would be needed for that? In FireFox this seems to be working pretty well! I can get up to 8 samples on my late 2013 15" MBP, and performance is still pretty great. 🎉 Chrome is still bugging out, I've pinged Tojiro. |
Well, one could add a true/false as to whether it should fail if it can not be achieved. I think in most cases one will want to have it use the highest samples it can successfully use, but in other cases, such as offline rendering, it may want to fall back to the manual MSAA pass that I PR'ed the other day. |
Another thing that came up has to do with EffectComposer. Chances are you only want the first pass to use MSAA, and the rest should ping-pong two 0-sample targets. I ended up having to change some things in EffectComposer to get this working properly. |
It is easy, a pass can do anything if the result is a 0-sample target. I just created an MSAAPass that did this manually. Having a real Multisample pass is no different. |
This seems informative and on topic? What is the technical name for the method of aliases when a given pixel has samples taken randomly from four surrounding quadrants, and if they are close enough (agreeing) does not sample 4 more in that disagreeing quadrant? Eventually when they are all close enough (to a set limit) an appropriate relative average is made? Is this exclusive to the definition of Raytracing (of which there are many formulas Hanning, blackman, catmull-rom)? is it called Ray Variance? So the idea of that here is not a sensible approach? I guess the example is in the middle of a sphere it does less sampling as it's more uniform, while the edge requires more samples. (Another form of the formulas simply called [in Houdini etc.] "Edge Detection Filter" comes to mind in this example.) Is this what you mean by "real Multisample pass"? and again I'm guessing it's not GPU or real-time friendly but it sounds maybe more efficient if possible (on mass in the GPU). The article also talks about using samples over time somehow, but that suggests pixel tracking vectors to my thinking? This works well and looks pro and proper (nice job). Further I keep thinking about how a helper could scan a scene to ultimately disable quality features, based on (adjustable user/device preference settings like) framerate (and/or object distance) and this seems like the perfect thing for dynamically changing based on performance on the specific device. Ironically you maybe need aliasing more at distance, where as geo-detail (and/or particle count) might work the other way around [similarly like I figure shadow-map res and probably most textures would]. You could even disable shadows entirely for distance objects if you preferred object detail etc. |
I guess this is essential an Effect Composer, Vector based Motion Blur Anti-aliasing proposal (at least to me it seems to be) suggested, I believe by this same article linked to earlier https://www.cse.ust.hk/~psander/docs/tempcoj.pdf in my previous message, and am still wondering if I’ll finish reading it myself before writing on it?! The color itself is also a spline vector. |
Aesthetics note... Could we name it |
Ok, renamed! 😄 Outstanding issues:
|
@bhouston I can't seem to figure out how to get a MSAAPass without an extra (unnecessary) pass, since each pass can't modify the read/write targets of the EffectComposer. e.g. function MSAAPass (scene, camera) {
this.scene = scene;
this.camera = camera;
this.enabled = true;
this.clear = true;
this.needsSwap = false;
}
MSAAPass.prototype = {
_updateMultisampleTarget: function (width, height) { ... },
render: function (renderer, writeBuffer, readBuffer, delta) {
// Lazily create / update a WebGLMultisampleRenderTarget
this._updateMultisampleTarget(readBuffer.width, readBuffer.height);
// ???
// renderer.render(this.scene, this.camera, readBuffer, this.clear);
}
}; |
@mattdesl asked:
I am in favor of the basics first. :) More features can come later.
Yes, we should clamp to max in my opinion. No crashes.
Very much so. Why not just take my ManualMSAARenderPass example and swap out my code with yours -- you should have similar results but it should be faster. :) |
Conflicts: build/three.js
This is an early draft of multisample RenderBuffers to ThreeJS. This is a WebGL2 feature.
Multisample renderbuffers don't even work yet in Chrome Canary or FireFox Nightly, but hopefully this can start the discussion.
I figure it should go like this:
Open questions: