Skip to content
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

Feature Request: Add support for 3DLUT color grading #19457

Closed
gkjohnson opened this issue May 25, 2020 · 7 comments · Fixed by #20558
Closed

Feature Request: Add support for 3DLUT color grading #19457

gkjohnson opened this issue May 25, 2020 · 7 comments · Fixed by #20558

Comments

@gkjohnson
Copy link
Collaborator

I see that there's been some work done in the past in #15360 and @greggman has put together a nice article on the topic here. It's not entirely clear to me why the previous PR was closed but I wanted to bring this up as a nice addition to three.js. The utility has been better explained in the two links above but 3DLUTs are great for controlling the look and feel of a scene.

3DLUTs are supported in a variety of 3d engines and video editing software include Unity, Unreal Engine, and Babylonjs. There are also a couple existing file formats for them including .cube and .3dl (though 3dl looks relatively undocumented).

These formats are available online and can also be created in tools like Photoshop and would enable more artistic control over the look of the final scene.

I figure that just like gamma correction there could be a postprocessing effect and WebGLRenderer support that adds the LUT application to the end of the built in shaders:

const lut = new LUTLoader().load( '../path/to/lut.3dl' );
renderer.colorLUT3D = lut;
@greggman
Copy link
Contributor

If you were going to add this to three.js I'd expect you'd add LUTLoader.js to examples/jsm/loaders and otherwise it's just a post processing effect so you'd add LUTPass.js to examples/jsm/postprocessing

@gkjohnson
Copy link
Collaborator Author

@greggman

It's true making a postprocessing effect is probably a best first step. I'm not sure why #15360 was closed but would you mind if I modernized it and made a new PR based on that code?

Also while you're here you mentioned in #15360 (comment) that a LUT would be faster than the listed shaders in WebGL2 -- how would that be?

@AlexDaniel
Copy link

A bit surprised that an example for LUTs is not provided! Yes, it probably makes sense to have different loaders for different formats, and then just pass a 3d texture to the shader.

Also while you're here you mentioned in #15360 (comment) that a LUT would be faster than the listed shaders in WebGL2 -- how would that be?

I'm pretty sure performance differences will be minimal, if any. Applying a lut to a fragment is simply taking a value from a texture (with interpolation), there is not much that can be faster than that, but then the mentioned color filters are also extremely simple with just a few math operations, so who knows.

@AlexDaniel
Copy link

Ah, by the way, I'd like to note that not all LUTs are in weird formats, some are just images. For example, see HALD CLUTs. The beauty of these formats is that you can apply any color operation on identity luts using the software of your choice.

obs-studio is using this format, which is more “readable” than HALD CLUTs, but I still cannot figure out where it originates and what it actually is.

@gkjohnson
Copy link
Collaborator Author

A bit surprised that an example for LUTs is not provided

I've wound up implementing a LUT loader and shader in a separate project of my own here:

https://github.com/gkjohnson/threejs-sandbox/tree/master/3d-lut

It includes parsers for the 3DL and CUBE LUT formats but would make sense to include more or support image LUTs more cleanly. I chose those formats because Photoshop lets you export them. I'll probably try to contribute it back to three.js as an example at some point. Right now it generates a 2d DataTexture rather than a 3d one to support WebGL2 but it would make sense to add 3d texture support, as well.

I'm pretty sure performance differences will be minimal, if any. Applying a lut to a fragment is simply taking a value from a texture (with interpolation), there is not much that can be faster than that, but then the mentioned color filters are also extremely simple with just a few math operations, so who knows.

WebGL1 doesn't support 3d textures so interpolation along depth must be done manually -- I suspect the performance benefits in WebGL2 over WebGL1 come from the automatic interpolation in 3d textures.

@AlexDaniel
Copy link

@gkjohnson I'm pretty sure texture parameter here can't be named that way, I'm getting errors because it seems to understand it as a call to texture. Just renaming it to tex1 makes it work, thanks! Good enough for now until there's an official solution, I guess.

@gkjohnson
Copy link
Collaborator Author

gkjohnson commented Oct 20, 2020

@gkjohnson I'm pretty sure texture parameter here can't be named that way, I'm getting errors because it seems to understand it as a call to texture. Just renaming it to tex1 makes it work, thanks! Good enough for now until there's an official solution, I guess.

That code needs to be changed if you're using WebGL2, yes. texture is a valid variable name in WebGL1 and is running in the example page, though. I'm not maintaining those files for broader use or with three.js updates which is one of the reasons why I haven't contributed them yet. If you're interested in seeing specific changes to that implementation you're free to contribute them back to that repo and maybe we can get it to a point where we can make a PR into three sooner rather than later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants