-
-
Notifications
You must be signed in to change notification settings - Fork 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
Component tock() method for post scene rendering operations. #1564
Conversation
vendor/VREffect.js
Outdated
@@ -232,7 +232,7 @@ THREE.VREffect = function ( renderer, onError ) { | |||
var cameraR = new THREE.PerspectiveCamera(); | |||
cameraR.layers.enable( 2 ); | |||
|
|||
this.render = function ( scene, camera ) { | |||
this.render = function ( scene, camera, renderTarget, forceClear ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not be changing the code in the vendor folder. If there's something to be changed in VREffect we should submit a PR to three.js https://github.com/mrdoob/three.js/blob/master/examples/js/effects/VREffect.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree and the change is both trivial and makes VREffect more consistent with the rest of three. I'll try submiting a PR to threejs as well but I suggest we keep the patched version for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vendor directory must not have any patched code. It's messy to maintain and easy to forget that we have ad-hoc changes. This PR assumes new functionality on the VR Effect and Three.js might not agree on the approach. This would force us to redo this patch or maintain a fork of VREffect. Let's share the changes on a PR on three.js to get their feedback before merging this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'm getting on it
This code is much cleaner that the previous attempt. @fernandojsg, What do you think? |
@dmarcos implementing the final compositor as a system does away with the need for ordered execution of behaviors so this PR provides all that's needed for post processing. This setup is more proper since there can be only one compositor active. I also included the example as there is no need anymore for further PRs for ordering as discussed with @ngokevin . Ordered execution could be implemented with something complex like the graph approach or something as simple as using a boolean flag on components to switch between behaviors.unshift/push in a-scene's addBehavior, but that's now unrelated to post proc and can be decided at a later time |
VREffect additions submitted to three.js dev mrdoob/three.js#9172 |
@wizgrav nice, thanks! |
Nice it seems mrdoob accepted the patch |
We can now copy and paste to the vendor directory |
tock: function () { | ||
var scene = this.sceneEl; | ||
var rt = scene.renderTarget; | ||
if (!scene.enablePostProcessing) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing curly brackets around return
@dmarcos Yeah that was very responsive and kind of them actually. I'll include the latest VREffect from three/dev in this PR. Also, a guy from the slack channel asked me and so I've also made another example. The approach taken on that, while not as efficient as I'd like, is more akin to the effect composer from three.js. Post effect components are very easy to write as they're just wrappers over the various three shaders. They just provide a shaderMaterial to the compositor system for blending to screen and a namespace to update uniforms. Should I include that as well? http://wizgrav.github.io/aframe/examples/test/post-processing-grain/ |
I still didn't check the code, by now I'm trying to run the demos with a headset and on chromium they won't work as the video won't load so maybe the demo version could be something simpler using just geometry? |
|
||
}); | ||
this.quadPost.material = this.brightMaterial; | ||
var rtOptions = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better use whole words for variables instead of abbreviations: renderTargetOptions
@fernandojsg I've updated the compositor to use VREffect instead of the vanilla WebGLRenderer for outputting to screen, can you check the examples now? Unfortunately I don't have an hmd available currently. I hacked a bit on webvr-polyfill and vr-mode-ui to enable vr on desktop and got an image that looked proper but failed to make the view rotate. I'll check on a mobile later on UPDATE: I have the suspicion that vrHMD.submitFrame(); in VREffect is the culprit here |
@fernandojsg I patched VREffect for hmd frame submission to be performed manually. I haven't updated this PR with the changes, which will also have to be propagated to three.js. Please check the live examples to see if it fixes the issue. http://wizgrav.github.io/aframe/examples/test/post-processing/ |
@wizgrav I've just tried the new version and it's still painting just one eye. I'll try to debug it this afternoon! |
src/core/scene/a-scene.js
Outdated
this.animationFrameID = effect.requestAnimationFrame(this.render); | ||
effect.render(this.object3D, this.camera); | ||
|
||
window.performance.mark('render-iteration-started'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move this post processing code to a different PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the timings with performance.mark? I so, sure these should be done in a timing PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I eas refering to the lines below tha check for the posproceesing component and do renderTarget stuff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so should I just leave in the renderTarget creation in setupRenderer and the tock definition in component? the render to texture is straightforward, there's no other way to do it. If you're weary about the renderTarget size checking and resize, unfortunately that's necessary with the current way VREffect works(doesn't hint when it changes the canvas size when going in/out of VR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the tock infrastructure as a way to introduce logic after rendering the scene. It is useful beyond postprocessing. I would make a separate PR that introduces all the postprocessing pieces on top of the tock
work that is postprocessing agnostic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would start by just doing (as analog to the tick):
effect.render(this.object3D, camera, null);
if (this.isPlaying) { this.tock(this.time, delta): }
`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't readily think of any logic besides post processing that would need to happen after the scene rendering. Having tick for scene updates and tock for post proc is clean, if tock where to be generic it would lead to issues like having to check inside components if post processing is actually enabled for the current frame. Without these checks the final compositor would overwrite the screen with redundant scene renderings or just black. The effect components would also do their, costly, work but the results would not be used
Thanks for the patience. I would like to keep the |
@dmarcos I'm not sure I understand. You mean keeping the tock infrastructure in but not actually calling it in render()? |
@wizgrav A use case for example we needed this for (and we hacked temporarly) is the ability to capture an animated gif of a running scene. |
@wizgrav we would call render: {
value: function () {
var effect = this.effect;
var camera = this.camera;
var delta = this.clock.getDelta() * 1000;
this.time = this.clock.elapsedTime * 1000;
if (this.isPlaying) { this.tick(this.time, delta); }
this.animationFrameID = effect.requestAnimationFrame(this.render);
effect.render(this.object3D, camera, renderTarget);
if (this.isPlaying) { this.tock(this.time, delta); }
this.effect.submitFrame();
window.performance.mark('render-iteration-finished');
} |
@dmarcos I understand why you want to keep something so core as simple and generic as possible, I'm thinking more from a convenience standpoint. The video recording is a good example Maybe we could add a boolean property to the component, to denote that it shouldn't execute when the renderTarget is not enabled for the current frame. Then the "postprocessing" attribute check would just toggle the renderTarget on/off. What do you think of this scheme? I insist on landing this because I feel that this feature has been discussed for a way long time (in my sense of time) it's been a year and I'd prefer to come up with a solution in this PR so the feature lands, it will give the projects coming out using the framework, a big increase in quality. |
I would not check for the |
The scene.renderTarget setting could also be done by the final compositor system itself utilizing both tick and tock. It sounds ok |
@dmarcos removed renderTarget handling from scene, that can now be set by a component/system, example here https://wizgrav.github.io/aframe-clubber/demo/ One minor thing I found was that system update is not called when changing attributes from the dom inspector, only with setAttribute(). I used to override setEntityAttribute to do that but took it out cause it caused a test to fail. This is unrelated to tock though and could be fixed in another PR. |
Thanks a lot for the patience. Longest running PR in aframe history. It need a rebase. |
@dmarcos rebased and also proposed mrdoob/three.js#9848 to threejs. It's as minimal as it can be and If accepted, it will solve all issues concerning post processing in VR(proper godrays and such). |
@dmarcos |
Yeah! Thanks very much for sticking with it. |
@wizgrav one last thing. I see changes on VREffect. Are those coming from the three repo? Do we need then! |
@dmarcos yes I made the checks for layer.leftBounds and layer.rightBounds less strict as @johnnyshankman reported that they were undefined instead of null which the original code checked against. I hadn't experienced that myself tbh so I can take it out and if encountered again we can open a new issue. Though I don't expect side effects even if we leave it in |
@dmarcos reverted VREffect. Also updated the tock related tests |
Amazing! it only took a year to land this 😄 @wizgrav It's fantastic you were able to bring it back home |
Description:
Enables post scene rendering operations in aframe.
Changes proposed:
Extends a-scene element with a .renderTarget(to be set by a component/system on demand) to enable the rendering of the scene in a texture.
Adds a tock() method on components/systems where post scene rendering logic can be performed.
An example showcasing the functionality is included.
https://wizgrav.github.io/aframe-clubber/demo/