gkjohnson / three-gpu-pathtracer

Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.
https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/index.html
MIT License
1.33k stars 132 forks source link

Orthographic camera support #152

Closed vinkovsky closed 2 years ago

vinkovsky commented 2 years ago

Hey! An incredible project! Are you planning to add an orthographic camera in the near future? This would make it possible to create cool images like this one

164291812-ab100a57-8c62-4d50-b3c3-5a8cd2a74faa

It would also be great to see the fog effect. For example

164180642-2c65f372-6d16-4f77-9658-6d41b6a44075

I created this image with the support of Erich Loftis and his amazing project: https://erichlof.github.io/THREE.js-PathTracing-Renderer/Volumetric_Rendering.html

It will be very cool to have a react area light, a directional light and a spotlight

promontis commented 2 years ago

Is the orthographic camera a different technique? I would think that you could just drop in a different camera, not? If not, Would be awesome though, if it was supported!

vinkovsky commented 2 years ago

Hi @promontis! I tried to add an orthographic camera, but it didn't have any effect

vinkovsky commented 2 years ago

This is how Erich Loftis implemented the orthographic camera. Maybe it can be useful.

https://github.com/erichlof/THREE.js-PathTracing-Renderer/commit/8edc42678f9a04cbe8989ed405fa8061f6f5dbad

promontis commented 2 years ago

@vinkovsky ah so, it needs an extra implementation. Seems like not so much code, so hoping these genius guys can have a look at it 🤗

gkjohnson commented 2 years ago

Hi @vinkovsky! Thanks for the kind words. I don't have a plan immediately to work on orthographic rendering support (so many things to work on!) but if you'd like to take a shot at implementing it yourself I'm happy to provide some guidance!

Otherwise if this is a feature for professional work I'm happy to talk about contracting options and funding for prioritizing this work.

bhouston commented 2 years ago

I'll put a bounty of $500USD on an accepted PR that adds this feature in a seamless way if someone other than @gkjohnson can add it to this project. :)

Assuming @gkjohnson is okay with me doing this bounty.

gkjohnson commented 2 years ago

This is great, thanks @bhouston!

For anyone interested here's what I would expect of the addition for orthographic camera support:

I suppose depth of field could kind of be added for an orthographic camera but I think that would be atypical? It might be a nice plus but not expected for initial support.

erichlof commented 2 years ago

Hey all! Just wanted to drop in to say that all bounty hunters (thanks @bhouston !) are more than welcome to steal my code, as I have just recently implemented this Orthographic camera feature for my renderer. @vinkovsky linked to it a few posts back in this thread.

It literally only takes about 3 or 4 lines of shader code, and whatever JS code you need to add the feature for the end user. I would do it myself (for free), but like @gkjohnson, I've got a lot of other stuff on my plate at the moment. But to help any folks who are interested, I'll try to give a quick overview of the technical ray tracing-related part of this.

I'm a visual person, so I like to see it in my mind - here it goes: For normal 3d perspective camera ray generation, you make all of the ray origins the same as the camera position (this is the easiest part!). It's like they are all uniform when they start out. But then each ray's direction 'fans' out from the camera location and pierces a view plane pixel, then continues on out into the scene, to interact with whatever geometry you have in the world. The severity of this 'fanning' out is directly determined by the user's desired field of view (FOV) for the camera, which moves the view plane back and forth, closer and farther from the camera location. When you add up all the rays together visually, they look like a square-base pyramid with the apex at the camera location, and the view plane which sort of 'chops off' the top of the pyramid. CG people like to call it a view frustum, but it's just a pyramid with the top chopped off, lol. This is what produces the perspective projection and makes farther objects smaller on the screen (they take up less pixels).

For the Orthographic camera however, we take the roles of camera ray positions and directions and flip everything on its head. Instead of starting at the camera, the ray Origins themselves are 'fanned' out along the camera's Right and Up vectors, or U and V vectors if you like. You can directly obtain these from the camera's matrix. The user's FOV setting now plays a different role- it 'slides' these camera ray Origins along the camera's Right and Up vectors, determining the 'field of view' or width and height of the starting picture frame. Then for the ray directions, (this is the easy part!) - they are all exactly the same as the camera's view direction. Like how all the Origins were the same for perspective cameras, the Directions are all the same for the orthographic cameras. Pretty nifty!

I can't remember where I learned this trick: I think it was from some freely available lecture presentation slides for a college CG class online in PowerPoint format. But regardless, it literally only takes the role reversal of the camera ray Origins and Directions to flip back and forth between Perspective and Orthographic.

Hope this helps get someone out there started. Best of luck! -Erich

JustASquid commented 2 years ago

Hard to resist - having recently completed Peter Shirley's Ray Tracing series, I'm having a crack at this :) And thanks for the jumping off point @erichlof!

@gkjohnson I do have a question.

// Jitter the camera ray by finding a new subpixel point to point to from the camera origin
// This is better than just jittering the camera position since it actually results in divergent
// rays providing better coverage for the pixel
{
        // TODO: the complexity here could be improved
        vec3 cameraOrigin = ( cameraWorldMatrix * vec4( 0.0, 0.0, 0.0, 1.0 ) ).xyz;
        vec3 ss00, ss01, ss10, temp;
        ndcToCameraRay( vec2( - 1.0, - 1.0 ), cameraWorldMatrix, invProjectionMatrix, ss00, temp );
        ndcToCameraRay( vec2( - 1.0, 1.0 ), cameraWorldMatrix, invProjectionMatrix, ss01, temp );
        ndcToCameraRay( vec2( 1.0, - 1.0 ), cameraWorldMatrix, invProjectionMatrix, ss10, temp );

        vec3 ssdX = ( ss10 - ss00 ) / resolution.x;
        vec3 ssdY = ( ss01 - ss00 ) / resolution.y;
        rayOrigin += tentFilter( rand() ) * ssdX + tentFilter( rand() ) * ssdY;
        rayDirection = normalize( rayOrigin - cameraOrigin );
}

This ray jittering code is quite specific to a perspective camera. Personally, I'd have implemented this by jittering the input ndc coordinates, however the comment seems to indicate that there is some benefit to jittering the ray origin after finding the "base" ray origin/direction. The tent filter also comes into play here - is there any reference you have for this implementation so that I could adapt it to the orthographic case?

EDIT: On further inspection, it's not as specific to the perspective camera as I originally thought - see the PR for my potential solution.

alvinalexander commented 2 years ago

I was going to take a stab at this but it seems @JustASquid has made some good progress already:) I also just completed a ray tracing course hehe, and I am interested in getting involved, if you have other beginner friendly issues @gkjohnson.

gkjohnson commented 2 years ago

Hey @alvinalexander! Issues I'm not planning to work on immediate are marked with the "help wanted" label - some are definitely more complicated than others and I'll hopefully be adding some more when I have a chance.

Some of the more approachably-sized ones might be #91, #147, or #31. Improvements or thoughts on sampling patterns would also be helpful (#58, #59). If any of those are of interest let me know and I can help expand on any of them!

bhouston commented 2 years ago

@alvinalexander i just put another bounty on an accepted PR to the first issue that @gkjohnson listed above! #91

alvinalexander commented 2 years ago

Cool! I'd be happy to take a look at #91 @gkjohnson if you could expand a bit on what you expect and maybe point me to some relevant parts of the codebase that would be great:)