/* VideoSwitcherSimpleLuminanceToRB8_FormattingShader.frag.txt -- Luminance output formatter * * This shader converts a HDR luminance texture into a RGBA8 8bpc framebuffer * image, suitable for display with the Xiangru Li et al. "VideoSwitcher" video * attenuator device. The "Simple" converter uses a closed-form solution to * map luminance to (Red,Blue) channel output values. * * It expects the luminance image data in the red channel of the texture, * with values ranging from 0.0 - 1.0, remaps it into the bpc bit data range * of the device of 16 bpc, then converts the 16 bit integral luminance index * value into proper red, blue drive pixel output. * * The green and alpha channels are unused and simply set to a constant zero value. * * This shader is intended for use as a plugin for the 'FinalOutputFormattingBlit' * chain of the Psychtoolbox-3 imaging pipeline. * * (c)2007, 2008 by Mario Kleiner, part of PTB-3, licensed to you under MIT license. * See file License.txt in the Psychtoolbox root folder for the license. * */ #extension GL_ARB_texture_rectangle : enable /* The input Image - Usually from texture unit 0: */ uniform sampler2DRect Image; /* The btrr calibration value: Blue-To-Red-Ratio from calibration: */ uniform float btrr; /* btrr + 1, passed from host to save a floating point addition.: */ uniform float btrrPlusOne; /* (btrr + 1) / btrr, passed from host to save addition and division.: */ uniform float btrrFractionTerm; /* Declare external function for luminance color conversion: */ float icmTransformColor1(float incolor); void main() { vec4 outcolor = vec4(0.0); /* Retrieve HDR/High precision input luminance value from RED channel: */ /* The same value is stored (replicated) in the GREEN and BLUE channels */ /* if this is a drawn luminance image, so choice of channel doesn't matter. */ /* We expect these values to be in 0.0 - 1.0 range. */ /* We add a small numerical 'epsilon' offset of 1e-7 to the fetched value. */ /* This is to account for small numerical differences between GPU's float */ /* storage format and CPU's double format. This is not strictly neccessary, */ /* but we do it to achieve identical results between GPU and CPU conversion */ /* to simplify validation/testing and intermix of CPU and GPU methods. */ float lum = texture2DRect(Image, gl_TexCoord[0].st).r + 0e-7; /* Apply some color transformation (clamping, gamma correction etc.): */ lum = icmTransformColor1(lum); /* Remap 'lum' from 0.0 - 1.0 range to range 0.0 - 255.0. */ lum = lum * 255.0; /* First compute blue output channel: Value will be integral, clamped to [0; 255]: */ outcolor.b = min( 255.0, floor(btrrFractionTerm * lum) ); /* Compute remainder and compensate for that residual via red channel: */ outcolor.r = floor((btrrPlusOne * lum) - (outcolor.b * btrr) + 0.5); /* Need to remap out.br values from range 0 - 255 to framebuffers uint8 */ /* output range of 0.0 - 1.0: */ outcolor.rb = outcolor.rb / 255.0; /* Copy output pixel to RGBA8 fixed point framebuffer: */ gl_FragColor = outcolor; }