[SOLVED] Hardware generated lookup tables

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

[SOLVED] Hardware generated lookup tables

Post by kubatp »

Hi,
I just got an advice to use hardware based lookup tables described here http://http.developer.nvidia.com/GPUGem ... ter24.html

Does anyone here have an experience with this in OGRE?
Last edited by kubatp on Fri Jun 21, 2019 5:29 pm, edited 1 time in total.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Hardware generated lookup tables

Post by xrgo »

Hi, yes! its posible in many formats, you can edit pixel by pixel and/or use shaders.. just explain us a little what you want to achieve.
If you want to achieve color grading effects (like in the link)? I have some code for that and a workflow that involves taking a screenshot, open it with photoshop edit it and save the table and walla! it looks the same in your game :), I'll be glad to share
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Hardware generated lookup tables

Post by kubatp »

Hi xrgo,
firstly thank you very much for your reply and willingness to help.
xrgo wrote:just explain us a little what you want to achieve
I was told that I should try (or play with) different lookup tables to see project (the game) with different colour formats (literally "add some grading and harmonize your overall colour scheme"). Because I was not even sure that this is possible in Ogre (I havent found any references in forums neither in manual),I wanted to be sure this is even possible.

I have number of questions, if you would be so nice to answer those:
  1. Is this feature supported directly by Ogre engine? Something like setting up the table and pass it to the viewport (or something like that)?
  2. Is there a measurable performance impact when using these tables?
  3. How to use these tables for specific materials? Shaders?
  4. I would be very happy for any code snippet which would shed more light on that.
Thank you for any advices.
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Hardware generated lookup tables

Post by kubatp »

Hi xrgo,
still there?:)
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Hardware generated lookup tables

Post by xrgo »

kubatp wrote:Hi xrgo,
still there?:)
Yes! really sorry, didn't noticed you posted :/
kubatp wrote:I was told that I should try (or play with) different lookup tables to see project (the game) with different colour formats (literally "add some grading and harmonize your overall colour scheme")
yep, that's "color grading"
kubatp wrote:Is this feature supported directly by Ogre engine? Something like setting up the table and pass it to the viewport (or something like that)?
yes, definitely possible, but not out of the box, you have to write your own shaders (or copy paste mine lol), but this one is really easy, just a few lines. you can "pass it to the viewport" using a compositor effect.
kubatp wrote:Is there a measurable performance impact when using these tables?
almost zero, this compositor effect is reaaaally cheap. unless you want to dynamically change the lookup table on cpu, but you usually do that in Photoshop as I'll explain later
kubatp wrote:How to use these tables for specific materials? Shaders?
that will be just another texture sampler.
kubatp wrote:I would be very happy for any code snippet which would shed more light on that.
let's go!:

I am using Ogre 2.1, so this shader is for GL3+ rendersystem, but it should work with previous version with just a few tweeks. also *disclaimer* I didn't tested the next codes as-is, I extracted them from my pipeline, so there might by a typo or something missing.

this is the shader that does the magic, ColorGradingFP.glsl:

Code: Select all

#version 330

layout(location = 0, index = 0) out vec4 outColour;

in block
{
   vec2 uv0;
} inPs;

uniform sampler2D renderSampler;
uniform sampler3D lutTable;
uniform float blend;

//for a lutSize of 16;
#define scale 0.9375 //(lutSize - 1.0) / lutSize;
#define offset 0.03125 //1.0 / (2.0 * lutSize);

void main()
{
	vec3 renderColor = texture2D( renderSampler, inPs.uv0 ).xyz; //get the original image

	vec3 newColor = texture(lutTable, scale * renderColor.xyz + offset).xyz; //get the new color from the lutTable
	vec3 finalColor = renderColor*(1.0-blend) + newColor*(blend); //blend it in

	outColour = vec4(finalColor,1);
}
This is the Material definition:

Code: Select all

fragment_program ColorGradingFP glsl
{
	source ColorGradingFP.glsl
}

material ColorGradingMat
{
	technique
	{
		pass
		{
			depth_check off
			depth_write off
			cull_hardware none

			fragment_program_ref ColorGradingFP
			{
				param_named renderSampler int 0
				param_named lutTable int 1
				param_named blend float 1 //starts full blended
			}
			vertex_program_ref Ogre/Compositor/Quad_vs
			{
			}
			texture_unit
			{
				filtering bilinear
				tex_address_mode border
				tex_border_colour 0 0 0 0
			}
			texture_unit lutTable
			{
				texture IdentityLUT.dds 3d 0
				filtering linear linear linear
				tex_address_mode clamp
			}
		}
	}
}
notice that the material needs a "IdentityLUT.dds" that is this file:
https://www.dropbox.com/s/di8ij4lswc065 ... T.dds?dl=0
this file will do nothing (that's why is called identity), so for testing you could use this one (change it in the material definition):
https://www.dropbox.com/s/j2z9dve1jcxze ... T.dds?dl=0
that will bring a sepia look to the image. I will explain how to generate this files later.

You will also need the "Ogre/Compositor/Quad_vs" program accesible in your resource locations (its included with Ogre in its media files)

then to make it work just apply ir as any other compositor effect:
in 1.X, should be like this, (not sure its been a long time since I dont use it):
ÇolorGrading.compositor:

Code: Select all

compositor ColorGrading
{
    technique
    {
        texture rt0 target_width_scaled 1.0 target_height_scaled 1.0 PF_R8G8B8

        target rt0 { input previous }

        target_output
        {
            // Start with clear output
            input none
            pass render_quad
            {
                material ColorGradingMat
                input 0 rt0
            }
        }
    }
}
in your C++ Code:

Code: Select all

Ogre::CompositorInstance* mCompositor;
        mCompositor= Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "ColorGrading");
        mCompositor->setEnabled(true);
and in 2.X should be like this:

Code: Select all

compositor_node mainRenderNode
{
	in 0 renderWindow
  
  texture render target_width target_height PF_R8G8B8
    
	target render
	{
		pass clear
		{
			colour_value 0 0 0 1
		}

		pass render_scene
		{
		}
	}
  target renderWindow
  {
    pass render_quad
    {
      material	ColorGradingMat
      input		0	render
    }
  }
}

workspace MainWorkspace
{
	connect_output mainRenderNode 0
}
and use that Workspace when addingWorkspace in your code...
with that if you used the SepiaLut it should look sepia :)


Now, that part was very boring since is like you should apply any fullscreen compositor effect... this is the interesting part:
How to generate the lookup tables using photoshop (or any other program like gimp)

First you need to install the Nvidia Texture Tools for photoshop, just to have DDS support..

then take a Screenshot of your application

Load it into Photoshop.

Also load the "IdentityLUT.dds" table in top of the screenshot (at the corner so it wont bother you), it should look like a strip:
Image

then you can create an adjustment layer or merge both layers (the lut table and screenshot)

then apply any color correction that you want (curves, levels, hue, saturation, etc) until you have a look that suits you
Image
make really sure that the color correction also affected the lut table.

then crop the image until you have only the lut table perfectly, you should have an image of 256*16px
Image

and save it to DDS as a 3D/Volume Image with this settings:
Image

Finally just use your "MyNewSuperLut.dds" in the ColorGradingMat and you should see your game in real time with the color correction that you did in Photoshop applied :)

you can do many other things later, like change the lut table by code, or blend multiple lut tables, change the intensity, etc etc.

Hope it helps! Cheers!
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Hardware generated lookup tables

Post by kubatp »

Wow!

Thank you very much for such a detailed answer. I will go through the whole answer very carefully and try out as much as I can before I ask anything more.
I really appreciate your effort Xrgo
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

[SOLVED] Re: Hardware generated lookup tables

Post by kubatp »

Hello xrgo,
I know that it has been two years since the last post but I would like to thank you very much for such a detailed response again. It was very helpful and it all worked as you described.
I somehow forgot to answer it but here it goes :)

Thank you for such support and help!
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [SOLVED] Hardware generated lookup tables

Post by xrgo »

=D glad I could help!
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: [SOLVED] Hardware generated lookup tables

Post by kubatp »

There is still one thing I don't understand. You showed me how to create a LUT texture in Photoshop. I did that and it works as you described.
But when it is created in Photoshop, it is a pure 2D texture so why do I have to set it in the plugin as a Volume texture. It does have only one slice in the outcome texture, no?
How does this

Code: Select all

float3 newColor = tex3D(lutTable, scale * output.xyz + offset).xyz; 
work in the shader?

Thank you for for your patience:)
Post Reply