166 OCIO::DisplayViewTransformRcPtr transform = OCIO::DisplayViewTransform::Create();
169 transform->setView(
view);
171 OCIO::LegacyViewingPipelineRcPtr vpt = OCIO::LegacyViewingPipeline::Create();
173 vpt->setDisplayViewTransform(transform);
192 vpt->setLooksOverride(
look);
193 vpt->setLooksOverrideEnabled(
true);
196 OCIO::GroupTransformRcPtr approximateTransform = OCIO::GroupTransform::Create();
200 const double exposureGain = pow(2.0,
exposure);
202 const double minRange = 0.001;
210 const double newMin[] = {0.0, 0.0, 0.0, 0.0};
211 const double newMax[] = {exposureGain, exposureGain, exposureGain, 1.0};
215 OCIO::MatrixTransform::Fit(m44, offset4, oldMin, oldMax, newMin, newMax);
216 OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
218 mtx->setOffset(offset4);
219 vpt->setLinearCC(mtx);
222 approximateTransform->appendTransform(mtx);
267 config->getDefaultLumaCoefs(lumacoef);
270 OCIO::MatrixTransform::View(m44, offset, channelHot, lumacoef);
271 OCIO::MatrixTransformRcPtr swizzleTransform = OCIO::MatrixTransform::Create();
272 swizzleTransform->setMatrix(m44);
273 swizzleTransform->setOffset(offset);
274 vpt->setChannelView(swizzleTransform);
279 double exponent = 1.0 / std::max(1e-6,
gamma);
280 const double exponent4f[] = {exponent, exponent, exponent, exponent};
281 OCIO::ExponentTransformRcPtr expTransform = OCIO::ExponentTransform::Create();
282 expTransform->setValue(exponent4f);
283 vpt->setDisplayCC(expTransform);
286 approximateTransform->appendTransform(expTransform);
293 }
catch (OCIO::Exception &e) {
295 errKrita <<
"OCIO exception while parsing the current context:" << e.what();
307 warnKrita <<
"OCIO inverted matrix does not exist!";
317 QOpenGLContext *ctx = QOpenGLContext::currentContext();
321 if (ctx->format().majorVersion() >= 3) {
322 QOpenGLExtraFunctions *f = ctx->extraFunctions();
326 }
else if (ctx->hasExtension(
"GL_OES_texture_float")
327 && (ctx->hasExtension(
"GL_EXT_texture_storage") || ctx->hasExtension(
"EXT_color_buffer_float"))
328 && ctx->hasExtension(
"GL_OES_texture_float_linear")) {
329 QOpenGLExtraFunctions *f = ctx->extraFunctions();
334 dbgKrita <<
"OcioDisplayFilter::updateShader"
335 <<
"OpenGL ES v2+ support detected but no OES_texture_float,"
336 "GL_EXT_color_buffer_float or GL_EXT_texture_storage, or GL_OES_texture_float_linear were found";
339#if defined(QT_OPENGL_3)
341#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
342 QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
344 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
345 profile.setVersion(3,2);
346 QOpenGLFunctions_3_2_Core *f =
reinterpret_cast<QOpenGLFunctions_3_2_Core *
>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
355#if defined(QT_OPENGL_3)
356#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
357#if defined(Q_OS_MAC) && defined(QT_OPENGL_3_2)
358 QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
360 QOpenGLFunctions_3_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_0>();
363#if defined(Q_OS_MAC) && defined(QT_OPENGL_3_2)
364 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
365 profile.setVersion(3,2);
366 QOpenGLFunctions_3_2_Core *f =
reinterpret_cast<QOpenGLFunctions_3_2_Core *
>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
368 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
369 profile.setVersion(3,0);
370 QOpenGLFunctions_3_0 *f =
reinterpret_cast<QOpenGLFunctions_3_0 *
>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
379#if !defined(QT_OPENGL_ES_2)
380#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
381 QOpenGLFunctions_2_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_0>();
383 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
384 profile.setVersion(2,0);
385 QOpenGLFunctions_2_0 *f =
reinterpret_cast<QOpenGLFunctions_2_0 *
>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
408 qWarning() <<
"Failed to get valid OpenGL functions for OcioDisplayFilter!";
412 bool shouldRecompileShader =
false;
415 OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();
417#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
419 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_3_0);
421 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_1_0);
425 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_3);
427 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
431 shaderDesc->setFunctionName(
"OCIODisplay");
432 shaderDesc->setResourcePrefix(
"ocio_");
435#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
438 const auto gpu =
m_processor->getOptimizedGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT);
442 m_processor->getOptimizedLegacyGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT, lut3DEdgeSize);
445 gpu->extractGpuShaderInfo(shaderDesc);
459 f->glDeleteTextures(1, &tex.m_uid);
465 unsigned currIndex = 1;
469 const unsigned maxTexture3D = shaderDesc->getNum3DTextures();
470 for (
unsigned idx = 0; idx < maxTexture3D; ++idx) {
473 const char *textureName =
nullptr;
474 const char *samplerName =
nullptr;
475 unsigned edgelen = 0;
476 OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
477 shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, interpolation);
479 if (!textureName || !*textureName || !samplerName || !*samplerName || edgelen == 0) {
480 errOpenGL <<
"The texture data is corrupted";
484 const float *values =
nullptr;
485 shaderDesc->get3DTextureValues(idx, values);
487 errOpenGL <<
"The texture values are missing";
495 if (values ==
nullptr) {
496 errOpenGL <<
"3D LUT" << idx <<
"Missing texture data";
500 f->glGenTextures(1, &texId);
502 f->glActiveTexture(GL_TEXTURE0 + currIndex);
504 f->glBindTexture(GL_TEXTURE_3D, texId);
507 if (interpolation == OCIO::INTERP_NEAREST) {
508 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
509 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
511 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
512 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
520 f->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F_ARB, edgelen, edgelen, edgelen, 0, GL_RGB, GL_FLOAT, values);
525 m_lut3dTexIDs.push_back({texId, textureName, samplerName, GL_TEXTURE_3D});
532 const unsigned maxTexture2D = shaderDesc->getNumTextures();
533 for (
unsigned idx = 0; idx < maxTexture2D; ++idx) {
536 const char *textureName =
nullptr;
537 const char *samplerName =
nullptr;
540 OCIO::GpuShaderDesc::TextureType channel = OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
541 OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
543#if OCIO_VERSION_HEX >= 0x2030000
544 OCIO::GpuShaderCreator::TextureDimensions dimensions;
545 shaderDesc->getTexture(idx, textureName, samplerName, width, height, channel, dimensions, interpolation);
547 shaderDesc->getTexture(idx, textureName, samplerName, width, height, channel, interpolation);
550 if (!textureName || !*textureName || !samplerName || !*samplerName || width == 0) {
551 errOpenGL <<
"The texture data is corrupted";
555 const float *values =
nullptr;
556 shaderDesc->getTextureValues(idx, values);
558 errOpenGL <<
"The texture values are missing";
566 if (values ==
nullptr) {
567 errOpenGL <<
"1D LUT" << idx <<
"Missing texture data.";
571 unsigned internalformat = GL_RGB32F_ARB;
572 unsigned format = GL_RGB;
574 if (channel == OCIO::GpuShaderCreator::TEXTURE_RED_CHANNEL) {
575 internalformat = GL_R32F;
579 f->glGenTextures(1, &texId);
581 f->glActiveTexture(GL_TEXTURE0 + currIndex);
583#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
589 f->glBindTexture(GL_TEXTURE_2D, texId);
592 if (interpolation == OCIO::INTERP_NEAREST) {
593 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
594 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
596 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
597 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
605 f->glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_FLOAT, values);
606#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
609 errOpenGL <<
"1D texture detected @" << idx <<
", not supported by OpenGLES";
617 unsigned type = GL_TEXTURE_2D;
618 m_lut3dTexIDs.push_back({texId, textureName, samplerName, type});
623 QString shaderCacheID = QString::fromLatin1(shaderDesc->getCacheID());
629 m_program = QString::fromLatin1(
"%1\n").arg(shaderDesc->getShaderText());
630 shouldRecompileShader =
true;
636 const unsigned maxUniforms = shaderDesc->getNumUniforms();
637 for (
unsigned idx = 0; idx < maxUniforms; ++idx) {
638 OCIO::GpuShaderDesc::UniformData data;
639 const char *name = shaderDesc->getUniform(idx, data);
640 if (data.m_type == OCIO::UNIFORM_UNKNOWN) {
641 errOpenGL <<
"Uniform" << idx <<
"has an unknown type";
649 return shouldRecompileShader;
654 for (
unsigned int idx = 0; idx <
m_lut3dTexIDs.size(); ++idx) {
656 f->glActiveTexture(GL_TEXTURE0 + 1 + idx);
657 f->glBindTexture(data.m_type, data.m_uid);
658 program->setUniformValue(
program->uniformLocation(data.m_samplerName), GLint(1 + idx));
662 const int m_handle =
program->uniformLocation(uniform.m_name);
664 const OCIO::GpuShaderDesc::UniformData &m_data = uniform.m_data;
667 if (m_data.m_getDouble) {
668 program->setUniformValue(m_handle,
static_cast<GLfloat
>(m_data.m_getDouble()));
669 }
else if (m_data.m_getBool) {
670 program->setUniformValue(m_handle,
static_cast<GLfloat
>(m_data.m_getBool() ? 1.0f : 0.0f));
671 }
else if (m_data.m_getFloat3) {
672 program->setUniformValue(m_handle,
673 m_data.m_getFloat3()[0],
674 m_data.m_getFloat3()[1],
675 m_data.m_getFloat3()[2]);
676 }
else if (m_data.m_vectorFloat.m_getSize && m_data.m_vectorFloat.m_getVector) {
677 program->setUniformValueArray(m_handle,
678 m_data.m_vectorFloat.m_getVector(),
679 m_data.m_vectorFloat.m_getSize(),
681 }
else if (m_data.m_vectorInt.m_getSize && m_data.m_vectorInt.m_getVector) {
682 program->setUniformValueArray(m_handle, m_data.m_vectorInt.m_getVector(), m_data.m_vectorInt.m_getSize());
684 errOpenGL <<
"Uniform" << uniform.m_name <<
"is not linked to any value";