I'm unsure if this is really a bug or not, as I'm unsure if using display colorspaces with scene referred colorspaces in a OCIO::ColorSpaceTransform is valid (i.e. not a DisplayViewTransform).
Here's my code, with OCIO v2.4.2.
auto config = OCIO::Config::CreateFromFile("ocio://default");
auto cst = OCIO::ColorSpaceTransform::Create();
cst->setDst("Rec.1886 Rec.709 - Display");
// cst->setSrc("Linear Rec.709 (sRGB)");
cst->setSrc("Gamma 2.4 Encoded Rec.709"); // <- this causes issue
auto group = OCIO::GroupTransform::Create();
group->appendTransform(cst);
auto proc = config->getProcessor(group)->getOptimizedGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_LOSSLESS); // <- setting to NONE fixes it
auto gpuShaderInfo = OCIO::GpuShaderDesc::CreateShaderDesc();
gpuShaderInfo->setLanguage(OCIO::GpuLanguage::GPU_LANGUAGE_HLSL_SM_5_0);
proc->extractGpuShaderInfo(gpuShaderInfo);
const char *text = gpuShaderInfo->getShaderText();
std::cout << text << std::endl;
With the linear Rec709 space set as the source, I get the following shader text which is what I'd expect, e.g. just a 2.4 gamma transform:
// Declaration of the OCIO shader function
float4 OCIOMain(float4 inPixel)
{
float4 outColor = inPixel;
// Add Gamma 'basicRev' processing
{
float4 gamma = float4(0.41666666666666669, 0.41666666666666669, 0.41666666666666669, 1.);
float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
return outColor;
}
However with the 2.4 gamma space set as the source, I'd expect a no-op transform. Instead I get this (a gamma of 5.76?):
// Declaration of the OCIO shader function
float4 OCIOMain(float4 inPixel)
{
float4 outColor = inPixel;
// Add Gamma 'basicRev' processing
{
float4 gamma = float4(0.17361111111111113, 0.17361111111111113, 0.17361111111111113, 1.);
float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
return outColor;
}
With OPTIMIZATION_NONE it seems reasonable:
// Declaration of the OCIO shader function
float4 OCIOMain(float4 inPixel)
{
float4 outColor = inPixel;
// Add Gamma 'basicPassThruFwd' processing
{
float4 gamma = float4(2.3999999999999999, 2.3999999999999999, 2.3999999999999999, 1.);
float4 breakPnt = float4(0., 0., 0., 0.);
float4 isAboveBreak = float4((outColor[0] > breakPnt[0]) ? 1.0 : 0.0, (outColor[1] > breakPnt[1]) ? 1.0 : 0.0, (outColor[2] > breakPnt[2]) ? 1.0 : 0.0, (outColor[3] > breakPnt[3]) ? 1.0 : 0.0);
float4 powSeg = pow(max( float4(0., 0., 0., 0.), outColor ), gamma);
float4 res = isAboveBreak * powSeg + ( float4(1., 1., 1., 1.) - isAboveBreak ) * outColor;
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
// Add Matrix processing
{
float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
float4 tmp = res;
res = mul(tmp, float4x4(0.43963298191949191, 0.089776442958842226, 0.017541170383172787, 0., 0.38298869815155351, 0.81343942874897801, 0.11154655330238722, 0., 0.1773783199289555, 0.096784128292177099, 0.87091227631444246, 0., 0., 0., 0., 1.));
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
// Add Matrix processing
{
float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
float4 tmp = res;
res = mul(tmp, float4x4(0.93827984927725538, 0.33736889078783672, 0.0011739508496858789, 0., -0.0044514458123613987, 0.72952156669026536, -0.0037107064020525625, 0., 0.016627523586776168, -0.066890457478102336, 1.0915945063122465, 0., 0., 0., 0., 1.));
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
// Add Matrix processing
{
float4 res = float4(outColor.rgb.r, outColor.rgb.g, outColor.rgb.b, outColor.a);
float4 tmp = res;
res = mul(tmp, float4x4(3.2409699419045213, -0.96924363628087973, 0.055630079696993649, 0., -1.5373831775700932, 1.8759675015077204, -0.20397695888897652, 0., -0.4986107602930035, 0.04155505740717564, 1.0569715142428788, 0., 0., 0., 0., 1.));
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
// Add Gamma 'basicRev' processing
{
float4 gamma = float4(0.41666666666666669, 0.41666666666666669, 0.41666666666666669, 1.);
float4 res = pow( max( float4(0., 0., 0., 0.), outColor ), gamma );
outColor.rgb = float3(res.x, res.y, res.z);
outColor.a = res.w;
}
return outColor;
}
I'm unsure if this is really a bug or not, as I'm unsure if using display colorspaces with scene referred colorspaces in a OCIO::ColorSpaceTransform is valid (i.e. not a DisplayViewTransform).
Here's my code, with OCIO v2.4.2.
With the linear Rec709 space set as the source, I get the following shader text which is what I'd expect, e.g. just a 2.4 gamma transform:
However with the 2.4 gamma space set as the source, I'd expect a no-op transform. Instead I get this (a gamma of 5.76?):
With OPTIMIZATION_NONE it seems reasonable: