diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 47df11c7..2ea55273 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -433,6 +433,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmRenderNode.fd > addLastPressToHistory(TOUCH_COORDS, g_pInputManager->getClickMode() == CLICKMODE_KILL, true); }); + + m_finalScreenShader = makeShared(); } CHyprOpenGLImpl::~CHyprOpenGLImpl() { @@ -639,94 +641,6 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attr return image; } -void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program, bool silent) { - GLint maxLength = 0; - if (program) - glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &maxLength); - else - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); - - std::vector errorLog(maxLength); - if (program) - glGetProgramInfoLog(shader, maxLength, &maxLength, errorLog.data()); - else - glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); - std::string errorStr(errorLog.begin(), errorLog.end()); - - const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr; - - Log::logger->log(Log::ERR, "Failed to link shader: {}", FULLERROR); - - if (!silent) - g_pConfigManager->addParseError(FULLERROR); -} - -GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic, bool silent) { - auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert, dynamic, silent); - if (dynamic) { - if (vertCompiled == 0) - return 0; - } else - RASSERT(vertCompiled, "Compiling shader failed. VERTEX nullptr! Shader source:\n\n{}", vert); - - auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag, dynamic, silent); - if (dynamic) { - if (fragCompiled == 0) - return 0; - } else - RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT nullptr! Shader source:\n\n{}", frag); - - auto prog = glCreateProgram(); - glAttachShader(prog, vertCompiled); - glAttachShader(prog, fragCompiled); - glLinkProgram(prog); - - glDetachShader(prog, vertCompiled); - glDetachShader(prog, fragCompiled); - glDeleteShader(vertCompiled); - glDeleteShader(fragCompiled); - - GLint ok; - glGetProgramiv(prog, GL_LINK_STATUS, &ok); - if (dynamic) { - if (ok == GL_FALSE) { - logShaderError(prog, true, silent); - return 0; - } - } else { - if (ok != GL_TRUE) - logShaderError(prog, true); - RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); - } - - return prog; -} - -GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool dynamic, bool silent) { - auto shader = glCreateShader(type); - - auto shaderSource = src.c_str(); - - glShaderSource(shader, 1, &shaderSource, nullptr); - glCompileShader(shader); - - GLint ok; - glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); - - if (dynamic) { - if (ok == GL_FALSE) { - logShaderError(shader, false, silent); - return 0; - } - } else { - if (ok != GL_TRUE) - logShaderError(shader, false); - RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); - } - - return shader; -} - void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_renderData.pMonitor = pMonitor; @@ -878,7 +792,7 @@ void CHyprOpenGLImpl::end() { m_renderData.outFB->bind(); blend(false); - if (m_finalScreenShader.program < 1 && !g_pHyprRenderer->m_crashingInProgress) + if (m_finalScreenShader->program() < 1 && !g_pHyprRenderer->m_crashingInProgress) renderTexturePrimitive(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox); else renderTexture(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox, {}); @@ -962,31 +876,6 @@ static std::string processShader(const std::string& filename, const std::map(); const bool isDynamic = m_shadersInitialized; @@ -996,256 +885,64 @@ bool CHyprOpenGLImpl::initShaders() { std::map includes; loadShaderInclude("rounding.glsl", includes); loadShaderInclude("CM.glsl", includes); + loadShaderInclude("gain.glsl", includes); + loadShaderInclude("border.glsl", includes); shaders->TEXVERTSRC = processShader("tex300.vert", includes); shaders->TEXVERTSRC320 = processShader("tex320.vert", includes); - GLuint prog; - if (!*PCM) m_cmSupported = false; else { - const auto TEXFRAGSRCCM = processShader("CM.frag", includes); + std::vector CM_SHADERS = {{ + {SH_FRAG_CM_RGBA, "CMrgba.frag"}, + {SH_FRAG_CM_RGBX, "CMrgbx.frag"}, + {SH_FRAG_CM_BLURPREPARE, "CMblurprepare.frag"}, + {SH_FRAG_CM_BORDER1, "CMborder.frag"}, + }}; - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCCM, true, true); - if (m_shadersInitialized && m_cmSupported && prog == 0) + bool success = false; + for (const auto& desc : CM_SHADERS) { + const auto fragSrc = processShader(desc.file, includes); + + if (!(success = shaders->frag[desc.id]->createProgram(shaders->TEXVERTSRC, fragSrc, true, true))) + break; + } + + if (m_shadersInitialized && m_cmSupported && !success) g_pHyprNotificationOverlay->addNotification(I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_CM_RELOAD_FAILED), CHyprColor{}, 15000, ICON_WARNING); - m_cmSupported = prog > 0; - if (m_cmSupported) { - shaders->m_shCM.program = prog; - getCMShaderUniforms(shaders->m_shCM); - getRoundingShaderUniforms(shaders->m_shCM); - shaders->m_shCM.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shCM.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shCM.uniformLocations[SHADER_TEX_TYPE] = glGetUniformLocation(prog, "texType"); - shaders->m_shCM.uniformLocations[SHADER_ALPHA_MATTE] = glGetUniformLocation(prog, "texMatte"); - shaders->m_shCM.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shCM.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shCM.uniformLocations[SHADER_MATTE_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoordMatte"); - shaders->m_shCM.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shCM.uniformLocations[SHADER_DISCARD_OPAQUE] = glGetUniformLocation(prog, "discardOpaque"); - shaders->m_shCM.uniformLocations[SHADER_DISCARD_ALPHA] = glGetUniformLocation(prog, "discardAlpha"); - shaders->m_shCM.uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = glGetUniformLocation(prog, "discardAlphaValue"); - shaders->m_shCM.uniformLocations[SHADER_APPLY_TINT] = glGetUniformLocation(prog, "applyTint"); - shaders->m_shCM.uniformLocations[SHADER_TINT] = glGetUniformLocation(prog, "tint"); - shaders->m_shCM.uniformLocations[SHADER_USE_ALPHA_MATTE] = glGetUniformLocation(prog, "useAlphaMatte"); - shaders->m_shCM.createVao(); - } else + m_cmSupported = success; + + if (!m_cmSupported) Log::logger->log( Log::ERR, "WARNING: CM Shader failed compiling, color management will not work. It's likely because your GPU is an old piece of garbage, don't file bug reports " "about this!"); } - const auto FRAGSHADOW = processShader("shadow.frag", includes); - const auto FRAGBORDER1 = processShader("border.frag", includes); - const auto FRAGBLURPREPARE = processShader("blurprepare.frag", includes); - const auto FRAGBLURFINISH = processShader("blurfinish.frag", includes); - const auto QUADFRAGSRC = processShader("quad.frag", includes); - const auto TEXFRAGSRCRGBA = processShader("rgba.frag", includes); - const auto TEXFRAGSRCRGBAPASSTHRU = processShader("passthru.frag", includes); - const auto TEXFRAGSRCRGBAMATTE = processShader("rgbamatte.frag", includes); - const auto FRAGGLITCH = processShader("glitch.frag", includes); - const auto TEXFRAGSRCRGBX = processShader("rgbx.frag", includes); - const auto TEXFRAGSRCEXT = processShader("ext.frag", includes); - const auto FRAGBLUR1 = processShader("blur1.frag", includes); - const auto FRAGBLUR2 = processShader("blur2.frag", includes); + std::vector FRAG_SHADERS = {{ + {SH_FRAG_QUAD, "quad.frag"}, + {SH_FRAG_RGBA, "rgba.frag"}, + {SH_FRAG_PASSTHRURGBA, "passthru.frag"}, + {SH_FRAG_MATTE, "rgbamatte.frag"}, + {SH_FRAG_GLITCH, "glitch.frag"}, + {SH_FRAG_RGBX, "rgbx.frag"}, + {SH_FRAG_EXT, "ext.frag"}, + {SH_FRAG_BLUR1, "blur1.frag"}, + {SH_FRAG_BLUR2, "blur2.frag"}, + {SH_FRAG_BLURPREPARE, "blurprepare.frag"}, + {SH_FRAG_BLURFINISH, "blurfinish.frag"}, + {SH_FRAG_SHADOW, "shadow.frag"}, + {SH_FRAG_BORDER1, "border.frag"}, + }}; - prog = createProgram(shaders->TEXVERTSRC, QUADFRAGSRC, isDynamic); - if (!prog) - return false; - shaders->m_shQUAD.program = prog; - getRoundingShaderUniforms(shaders->m_shQUAD); - shaders->m_shQUAD.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shQUAD.uniformLocations[SHADER_COLOR] = glGetUniformLocation(prog, "color"); - shaders->m_shQUAD.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shQUAD.createVao(); + for (const auto& desc : FRAG_SHADERS) { + const auto fragSrc = processShader(desc.file, includes); - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBA, isDynamic); - if (!prog) - return false; - shaders->m_shRGBA.program = prog; - getRoundingShaderUniforms(shaders->m_shRGBA); - shaders->m_shRGBA.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shRGBA.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shRGBA.uniformLocations[SHADER_ALPHA_MATTE] = glGetUniformLocation(prog, "texMatte"); - shaders->m_shRGBA.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shRGBA.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shRGBA.uniformLocations[SHADER_MATTE_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoordMatte"); - shaders->m_shRGBA.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shRGBA.uniformLocations[SHADER_DISCARD_OPAQUE] = glGetUniformLocation(prog, "discardOpaque"); - shaders->m_shRGBA.uniformLocations[SHADER_DISCARD_ALPHA] = glGetUniformLocation(prog, "discardAlpha"); - shaders->m_shRGBA.uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = glGetUniformLocation(prog, "discardAlphaValue"); - shaders->m_shRGBA.uniformLocations[SHADER_APPLY_TINT] = glGetUniformLocation(prog, "applyTint"); - shaders->m_shRGBA.uniformLocations[SHADER_TINT] = glGetUniformLocation(prog, "tint"); - shaders->m_shRGBA.uniformLocations[SHADER_USE_ALPHA_MATTE] = glGetUniformLocation(prog, "useAlphaMatte"); - shaders->m_shRGBA.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU, isDynamic); - if (!prog) - return false; - shaders->m_shPASSTHRURGBA.program = prog; - shaders->m_shPASSTHRURGBA.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shPASSTHRURGBA.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shPASSTHRURGBA.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shPASSTHRURGBA.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shPASSTHRURGBA.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAMATTE, isDynamic); - if (!prog) - return false; - shaders->m_shMATTE.program = prog; - shaders->m_shMATTE.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shMATTE.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shMATTE.uniformLocations[SHADER_ALPHA_MATTE] = glGetUniformLocation(prog, "texMatte"); - shaders->m_shMATTE.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shMATTE.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shMATTE.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGGLITCH, isDynamic); - if (!prog) - return false; - shaders->m_shGLITCH.program = prog; - shaders->m_shGLITCH.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shGLITCH.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shGLITCH.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shGLITCH.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shGLITCH.uniformLocations[SHADER_DISTORT] = glGetUniformLocation(prog, "distort"); - shaders->m_shGLITCH.uniformLocations[SHADER_TIME] = glGetUniformLocation(prog, "time"); - shaders->m_shGLITCH.uniformLocations[SHADER_FULL_SIZE] = glGetUniformLocation(prog, "screenSize"); - shaders->m_shGLITCH.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBX, isDynamic); - if (!prog) - return false; - shaders->m_shRGBX.program = prog; - getRoundingShaderUniforms(shaders->m_shRGBX); - shaders->m_shRGBX.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shRGBX.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shRGBX.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shRGBX.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shRGBX.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shRGBX.uniformLocations[SHADER_DISCARD_OPAQUE] = glGetUniformLocation(prog, "discardOpaque"); - shaders->m_shRGBX.uniformLocations[SHADER_DISCARD_ALPHA] = glGetUniformLocation(prog, "discardAlpha"); - shaders->m_shRGBX.uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = glGetUniformLocation(prog, "discardAlphaValue"); - shaders->m_shRGBX.uniformLocations[SHADER_APPLY_TINT] = glGetUniformLocation(prog, "applyTint"); - shaders->m_shRGBX.uniformLocations[SHADER_TINT] = glGetUniformLocation(prog, "tint"); - shaders->m_shRGBX.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCEXT, isDynamic); - if (!prog) - return false; - shaders->m_shEXT.program = prog; - getRoundingShaderUniforms(shaders->m_shEXT); - shaders->m_shEXT.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shEXT.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shEXT.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shEXT.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shEXT.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shEXT.uniformLocations[SHADER_DISCARD_OPAQUE] = glGetUniformLocation(prog, "discardOpaque"); - shaders->m_shEXT.uniformLocations[SHADER_DISCARD_ALPHA] = glGetUniformLocation(prog, "discardAlpha"); - shaders->m_shEXT.uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = glGetUniformLocation(prog, "discardAlphaValue"); - shaders->m_shEXT.uniformLocations[SHADER_APPLY_TINT] = glGetUniformLocation(prog, "applyTint"); - shaders->m_shEXT.uniformLocations[SHADER_TINT] = glGetUniformLocation(prog, "tint"); - shaders->m_shEXT.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR1, isDynamic); - if (!prog) - return false; - shaders->m_shBLUR1.program = prog; - shaders->m_shBLUR1.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shBLUR1.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shBLUR1.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shBLUR1.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shBLUR1.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shBLUR1.uniformLocations[SHADER_RADIUS] = glGetUniformLocation(prog, "radius"); - shaders->m_shBLUR1.uniformLocations[SHADER_HALFPIXEL] = glGetUniformLocation(prog, "halfpixel"); - shaders->m_shBLUR1.uniformLocations[SHADER_PASSES] = glGetUniformLocation(prog, "passes"); - shaders->m_shBLUR1.uniformLocations[SHADER_VIBRANCY] = glGetUniformLocation(prog, "vibrancy"); - shaders->m_shBLUR1.uniformLocations[SHADER_VIBRANCY_DARKNESS] = glGetUniformLocation(prog, "vibrancy_darkness"); - shaders->m_shBLUR1.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR2, isDynamic); - if (!prog) - return false; - shaders->m_shBLUR2.program = prog; - shaders->m_shBLUR2.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shBLUR2.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shBLUR2.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shBLUR2.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shBLUR2.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shBLUR2.uniformLocations[SHADER_RADIUS] = glGetUniformLocation(prog, "radius"); - shaders->m_shBLUR2.uniformLocations[SHADER_HALFPIXEL] = glGetUniformLocation(prog, "halfpixel"); - shaders->m_shBLUR2.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGBLURPREPARE, isDynamic); - if (!prog) - return false; - shaders->m_shBLURPREPARE.program = prog; - getCMShaderUniforms(shaders->m_shBLURPREPARE); - - shaders->m_shBLURPREPARE.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shBLURPREPARE.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shBLURPREPARE.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shBLURPREPARE.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shBLURPREPARE.uniformLocations[SHADER_CONTRAST] = glGetUniformLocation(prog, "contrast"); - shaders->m_shBLURPREPARE.uniformLocations[SHADER_BRIGHTNESS] = glGetUniformLocation(prog, "brightness"); - shaders->m_shBLURPREPARE.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGBLURFINISH, isDynamic); - if (!prog) - return false; - shaders->m_shBLURFINISH.program = prog; - // getCMShaderUniforms(shaders->m_shBLURFINISH); - - shaders->m_shBLURFINISH.uniformLocations[SHADER_TEX] = glGetUniformLocation(prog, "tex"); - shaders->m_shBLURFINISH.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shBLURFINISH.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shBLURFINISH.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shBLURFINISH.uniformLocations[SHADER_BRIGHTNESS] = glGetUniformLocation(prog, "brightness"); - shaders->m_shBLURFINISH.uniformLocations[SHADER_NOISE] = glGetUniformLocation(prog, "noise"); - shaders->m_shBLURFINISH.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGSHADOW, isDynamic); - if (!prog) - return false; - - shaders->m_shSHADOW.program = prog; - getCMShaderUniforms(shaders->m_shSHADOW); - getRoundingShaderUniforms(shaders->m_shSHADOW); - shaders->m_shSHADOW.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shSHADOW.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shSHADOW.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shSHADOW.uniformLocations[SHADER_BOTTOM_RIGHT] = glGetUniformLocation(prog, "bottomRight"); - shaders->m_shSHADOW.uniformLocations[SHADER_RANGE] = glGetUniformLocation(prog, "range"); - shaders->m_shSHADOW.uniformLocations[SHADER_SHADOW_POWER] = glGetUniformLocation(prog, "shadowPower"); - shaders->m_shSHADOW.uniformLocations[SHADER_COLOR] = glGetUniformLocation(prog, "color"); - shaders->m_shSHADOW.createVao(); - - prog = createProgram(shaders->TEXVERTSRC, FRAGBORDER1, isDynamic); - if (!prog) - return false; - - shaders->m_shBORDER1.program = prog; - getCMShaderUniforms(shaders->m_shBORDER1); - getRoundingShaderUniforms(shaders->m_shBORDER1); - shaders->m_shBORDER1.uniformLocations[SHADER_PROJ] = glGetUniformLocation(prog, "proj"); - shaders->m_shBORDER1.uniformLocations[SHADER_THICK] = glGetUniformLocation(prog, "thick"); - shaders->m_shBORDER1.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(prog, "pos"); - shaders->m_shBORDER1.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(prog, "texcoord"); - shaders->m_shBORDER1.uniformLocations[SHADER_BOTTOM_RIGHT] = glGetUniformLocation(prog, "bottomRight"); - shaders->m_shBORDER1.uniformLocations[SHADER_FULL_SIZE_UNTRANSFORMED] = glGetUniformLocation(prog, "fullSizeUntransformed"); - shaders->m_shBORDER1.uniformLocations[SHADER_RADIUS_OUTER] = glGetUniformLocation(prog, "radiusOuter"); - shaders->m_shBORDER1.uniformLocations[SHADER_GRADIENT] = glGetUniformLocation(prog, "gradient"); - shaders->m_shBORDER1.uniformLocations[SHADER_GRADIENT2] = glGetUniformLocation(prog, "gradient2"); - shaders->m_shBORDER1.uniformLocations[SHADER_GRADIENT_LENGTH] = glGetUniformLocation(prog, "gradientLength"); - shaders->m_shBORDER1.uniformLocations[SHADER_GRADIENT2_LENGTH] = glGetUniformLocation(prog, "gradient2Length"); - shaders->m_shBORDER1.uniformLocations[SHADER_ANGLE] = glGetUniformLocation(prog, "angle"); - shaders->m_shBORDER1.uniformLocations[SHADER_ANGLE2] = glGetUniformLocation(prog, "angle2"); - shaders->m_shBORDER1.uniformLocations[SHADER_GRADIENT_LERP] = glGetUniformLocation(prog, "gradientLerp"); - shaders->m_shBORDER1.uniformLocations[SHADER_ALPHA] = glGetUniformLocation(prog, "alpha"); - shaders->m_shBORDER1.createVao(); + if (!shaders->frag[desc.id]->createProgram(shaders->TEXVERTSRC, fragSrc, isDynamic)) + return false; + } } catch (const std::exception& e) { if (!m_shadersInitialized) @@ -1266,7 +963,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { static auto PDT = CConfigValue("debug:damage_tracking"); - m_finalScreenShader.destroy(); + m_finalScreenShader->destroy(); if (path.empty() || path == STRVAL_EMPTY) return; @@ -1280,47 +977,23 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { std::string fragmentShader((std::istreambuf_iterator(infile)), (std::istreambuf_iterator())); - m_finalScreenShader.program = createProgram( // - fragmentShader.starts_with("#version 320 es") // do not break existing custom shaders - ? - m_shaders->TEXVERTSRC320 : - m_shaders->TEXVERTSRC, - fragmentShader, true); - - if (!m_finalScreenShader.program) { + if (!m_finalScreenShader->createProgram( // + fragmentShader.starts_with("#version 320 es") // do not break existing custom shaders + ? + m_shaders->TEXVERTSRC320 : + m_shaders->TEXVERTSRC, + fragmentShader, true)) { // Error will have been sent by now by the underlying cause return; } - m_finalScreenShader.uniformLocations[SHADER_POINTER_HIDDEN] = glGetUniformLocation(m_finalScreenShader.program, "pointer_hidden"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_KILLING] = glGetUniformLocation(m_finalScreenShader.program, "pointer_killing"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_SHAPE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_shape"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_SHAPE_PREVIOUS] = glGetUniformLocation(m_finalScreenShader.program, "pointer_shape_previous"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_SWITCH_TIME] = glGetUniformLocation(m_finalScreenShader.program, "pointer_switch_time"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_POSITIONS] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_positions"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_TIMES] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_times"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_KILLED] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_killed"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_PRESSED_TOUCHED] = glGetUniformLocation(m_finalScreenShader.program, "pointer_pressed_touched"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_INACTIVE_TIMEOUT] = glGetUniformLocation(m_finalScreenShader.program, "pointer_inactive_timeout"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_LAST_ACTIVE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_last_active"); - m_finalScreenShader.uniformLocations[SHADER_POINTER_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "pointer_size"); - m_finalScreenShader.uniformLocations[SHADER_POINTER] = glGetUniformLocation(m_finalScreenShader.program, "pointer_position"); - m_finalScreenShader.uniformLocations[SHADER_PROJ] = glGetUniformLocation(m_finalScreenShader.program, "proj"); - m_finalScreenShader.uniformLocations[SHADER_TEX] = glGetUniformLocation(m_finalScreenShader.program, "tex"); - m_finalScreenShader.uniformLocations[SHADER_TIME] = glGetUniformLocation(m_finalScreenShader.program, "time"); - if (m_finalScreenShader.uniformLocations[SHADER_TIME] != -1) - m_finalScreenShader.initialTime = m_globalTimer.getSeconds(); - m_finalScreenShader.uniformLocations[SHADER_WL_OUTPUT] = glGetUniformLocation(m_finalScreenShader.program, "wl_output"); - m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "screen_size"); - if (m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] == -1) - m_finalScreenShader.uniformLocations[SHADER_FULL_SIZE] = glGetUniformLocation(m_finalScreenShader.program, "screenSize"); - m_finalScreenShader.uniformLocations[SHADER_TEX_ATTRIB] = glGetAttribLocation(m_finalScreenShader.program, "texcoord"); - m_finalScreenShader.uniformLocations[SHADER_POS_ATTRIB] = glGetAttribLocation(m_finalScreenShader.program, "pos"); + if (m_finalScreenShader->getUniformLocation(SHADER_TIME) != -1) + m_finalScreenShader->setInitialTime(m_globalTimer.getSeconds()); static auto uniformRequireNoDamage = [this](eShaderUniform uniform, const std::string& name) { if (*PDT == 0) return; - if (m_finalScreenShader.uniformLocations[uniform] == -1) + if (m_finalScreenShader->getUniformLocation(uniform) == -1) return; // The screen shader uses the uniform @@ -1344,8 +1017,6 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { uniformRequireNoDamage(SHADER_POINTER_KILLING, "pointer_killing"); uniformRequireNoDamage(SHADER_POINTER_SHAPE, "pointer_shape"); uniformRequireNoDamage(SHADER_POINTER_SHAPE_PREVIOUS, "pointer_shape_previous"); - - m_finalScreenShader.createVao(); } void CHyprOpenGLImpl::clear(const CHyprColor& color) { @@ -1465,11 +1136,11 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC newBox, Math::wlTransformToHyprutils(Math::invertTransform(!m_monitorTransformEnabled ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); - useProgram(m_shaders->m_shQUAD.program); - m_shaders->m_shQUAD.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + auto shader = useShader(m_shaders->frag[SH_FRAG_QUAD]); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); // premultiply the color as well as we don't work with straight alpha - m_shaders->m_shQUAD.setUniformFloat4(SHADER_COLOR, col.r * col.a, col.g * col.a, col.b * col.a, col.a); + shader->setUniformFloat4(SHADER_COLOR, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = box; transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, @@ -1479,12 +1150,12 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); // Rounded corners - m_shaders->m_shQUAD.setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); - m_shaders->m_shQUAD.setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); - m_shaders->m_shQUAD.setUniformFloat(SHADER_RADIUS, data.round); - m_shaders->m_shQUAD.setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); + shader->setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); + shader->setUniformFloat(SHADER_RADIUS, data.round); + shader->setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); - glBindVertexArray(m_shaders->m_shQUAD.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; @@ -1543,19 +1214,19 @@ static bool isHDR2SDR(const NColorManagement::SImageDescription& imageDescriptio targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22); } -void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, - bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) { +void CHyprOpenGLImpl::passCMUniforms(WP shader, const NColorManagement::PImageDescription imageDescription, + const NColorManagement::PImageDescription targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) { static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); if (m_renderData.surface.valid() && ((!m_renderData.surface->m_colorManagement.valid() && *PSDREOTF >= 1) || (*PSDREOTF == 2 && m_renderData.surface->m_colorManagement.valid() && imageDescription->value().transferFunction == NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_SRGB))) { - shader.setUniformInt(SHADER_SOURCE_TF, NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_GAMMA22); + shader->setUniformInt(SHADER_SOURCE_TF, NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_GAMMA22); } else - shader.setUniformInt(SHADER_SOURCE_TF, imageDescription->value().transferFunction); + shader->setUniformInt(SHADER_SOURCE_TF, imageDescription->value().transferFunction); - shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription->value().transferFunction); + shader->setUniformInt(SHADER_TARGET_TF, targetImageDescription->value().transferFunction); const auto targetPrimaries = targetImageDescription->getPrimaries(); @@ -1563,28 +1234,28 @@ void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::PI targetPrimaries->value().red.x, targetPrimaries->value().red.y, targetPrimaries->value().green.x, targetPrimaries->value().green.y, targetPrimaries->value().blue.x, targetPrimaries->value().blue.y, targetPrimaries->value().white.x, targetPrimaries->value().white.y, }; - shader.setUniformMatrix4x2fv(SHADER_TARGET_PRIMARIES, 1, false, glTargetPrimaries); + shader->setUniformMatrix4x2fv(SHADER_TARGET_PRIMARIES, 1, false, glTargetPrimaries); const bool needsSDRmod = modifySDR && isSDR2HDR(imageDescription->value(), targetImageDescription->value()); const bool needsHDRmod = !needsSDRmod && isHDR2SDR(imageDescription->value(), targetImageDescription->value()); - shader.setUniformFloat2(SHADER_SRC_TF_RANGE, imageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), - imageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); - shader.setUniformFloat2(SHADER_DST_TF_RANGE, targetImageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), - targetImageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); + shader->setUniformFloat2(SHADER_SRC_TF_RANGE, imageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), + imageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); + shader->setUniformFloat2(SHADER_DST_TF_RANGE, targetImageDescription->value().getTFMinLuminance(needsSDRmod ? sdrMinLuminance : -1), + targetImageDescription->value().getTFMaxLuminance(needsSDRmod ? sdrMaxLuminance : -1)); - shader.setUniformFloat(SHADER_SRC_REF_LUMINANCE, imageDescription->value().getTFRefLuminance(-1)); - shader.setUniformFloat(SHADER_DST_REF_LUMINANCE, targetImageDescription->value().getTFRefLuminance(-1)); + shader->setUniformFloat(SHADER_SRC_REF_LUMINANCE, imageDescription->value().getTFRefLuminance(-1)); + shader->setUniformFloat(SHADER_DST_REF_LUMINANCE, targetImageDescription->value().getTFRefLuminance(-1)); const float maxLuminance = needsHDRmod ? imageDescription->value().getTFMaxLuminance(-1) : (imageDescription->value().luminances.max > 0 ? imageDescription->value().luminances.max : imageDescription->value().luminances.reference); - shader.setUniformFloat(SHADER_MAX_LUMINANCE, - maxLuminance * targetImageDescription->value().luminances.reference / - (needsHDRmod ? imageDescription->value().getTFRefLuminance(-1) : imageDescription->value().luminances.reference)); - shader.setUniformFloat(SHADER_DST_MAX_LUMINANCE, targetImageDescription->value().luminances.max > 0 ? targetImageDescription->value().luminances.max : 10000); - shader.setUniformFloat(SHADER_SDR_SATURATION, needsSDRmod && m_renderData.pMonitor->m_sdrSaturation > 0 ? m_renderData.pMonitor->m_sdrSaturation : 1.0f); - shader.setUniformFloat(SHADER_SDR_BRIGHTNESS, needsSDRmod && m_renderData.pMonitor->m_sdrBrightness > 0 ? m_renderData.pMonitor->m_sdrBrightness : 1.0f); + shader->setUniformFloat(SHADER_MAX_LUMINANCE, + maxLuminance * targetImageDescription->value().luminances.reference / + (needsHDRmod ? imageDescription->value().getTFRefLuminance(-1) : imageDescription->value().luminances.reference)); + shader->setUniformFloat(SHADER_DST_MAX_LUMINANCE, targetImageDescription->value().luminances.max > 0 ? targetImageDescription->value().luminances.max : 10000); + shader->setUniformFloat(SHADER_SDR_SATURATION, needsSDRmod && m_renderData.pMonitor->m_sdrSaturation > 0 ? m_renderData.pMonitor->m_sdrSaturation : 1.0f); + shader->setUniformFloat(SHADER_SDR_BRIGHTNESS, needsSDRmod && m_renderData.pMonitor->m_sdrBrightness > 0 ? m_renderData.pMonitor->m_sdrBrightness : 1.0f); const auto cacheKey = std::make_pair(imageDescription->id(), targetImageDescription->id()); if (!primariesConversionCache.contains(cacheKey)) { auto conversion = imageDescription->getPrimaries()->convertMatrix(targetImageDescription->getPrimaries()); @@ -1596,10 +1267,10 @@ void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::PI }; primariesConversionCache.insert(std::make_pair(cacheKey, glConvertMatrix)); } - shader.setUniformMatrix3fv(SHADER_CONVERT_MATRIX, 1, false, primariesConversionCache[cacheKey]); + shader->setUniformMatrix3fv(SHADER_CONVERT_MATRIX, 1, false, primariesConversionCache[cacheKey]); } -void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const PImageDescription imageDescription) { +void CHyprOpenGLImpl::passCMUniforms(WP shader, const PImageDescription imageDescription) { passCMUniforms(shader, imageDescription, m_renderData.pMonitor->m_imageDescription, true, m_renderData.pMonitor->m_sdrMinLuminance, m_renderData.pMonitor->m_sdrMaxLuminance); } @@ -1629,40 +1300,40 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c if (m_monitorTransformEnabled) TRANSFORM = Math::composeTransform(MONITOR_INVERTED, TRANSFORM); - Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); - Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); + Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); - SShader* shader = nullptr; + WP shader; - bool usingFinalShader = false; + bool usingFinalShader = false; - const bool CRASHING = m_applyFinalShader && g_pHyprRenderer->m_crashingInProgress; + const bool CRASHING = m_applyFinalShader && g_pHyprRenderer->m_crashingInProgress; - auto texType = tex->m_type; + auto texType = tex->m_type; if (CRASHING) { - shader = &m_shaders->m_shGLITCH; + shader = m_shaders->frag[SH_FRAG_GLITCH]; usingFinalShader = true; - } else if (m_applyFinalShader && m_finalScreenShader.program) { - shader = &m_finalScreenShader; + } else if (m_applyFinalShader && m_finalScreenShader->program()) { + shader = m_finalScreenShader; usingFinalShader = true; } else { if (m_applyFinalShader) { - shader = &m_shaders->m_shPASSTHRURGBA; + shader = m_shaders->frag[SH_FRAG_PASSTHRURGBA]; usingFinalShader = true; } else { switch (tex->m_type) { - case TEXTURE_RGBA: shader = &m_shaders->m_shRGBA; break; - case TEXTURE_RGBX: shader = &m_shaders->m_shRGBX; break; + case TEXTURE_RGBA: shader = m_shaders->frag[SH_FRAG_RGBA]; break; + case TEXTURE_RGBX: shader = m_shaders->frag[SH_FRAG_RGBX]; break; - case TEXTURE_EXTERNAL: shader = &m_shaders->m_shEXT; break; // might be unused + case TEXTURE_EXTERNAL: shader = m_shaders->frag[SH_FRAG_EXT]; break; // might be unused default: RASSERT(false, "tex->m_iTarget unsupported!"); } } } if (m_renderData.currentWindow && m_renderData.currentWindow->m_ruleApplicator->RGBX().valueOrDefault()) { - shader = &m_shaders->m_shRGBX; + shader = m_shaders->frag[SH_FRAG_RGBX]; texType = TEXTURE_RGBX; } @@ -1694,26 +1365,28 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c (*PPASS == 1 && !isHDRSurface && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR_EDID)) && m_renderData.pMonitor->inFullscreenMode()) /* Fullscreen window with pass cm enabled */; - if (!skipCM && !usingFinalShader && (texType == TEXTURE_RGBA || texType == TEXTURE_RGBX)) - shader = &m_shaders->m_shCM; + if (!skipCM && !usingFinalShader) { + if (texType == TEXTURE_RGBA) + shader = m_shaders->frag[SH_FRAG_CM_RGBA]; + else if (texType == TEXTURE_RGBX) + shader = m_shaders->frag[SH_FRAG_CM_RGBX]; - useProgram(shader->program); + shader = useShader(shader); - if (shader == &m_shaders->m_shCM) { - shader->setUniformInt(SHADER_TEX_TYPE, texType); if (data.cmBackToSRGB) { static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); auto chosenSdrEotf = *PSDREOTF != 3 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB; - passCMUniforms(*shader, imageDescription, CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}), true, -1, -1); + passCMUniforms(shader, imageDescription, CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}), true, -1, -1); } else - passCMUniforms(*shader, imageDescription); - } + passCMUniforms(shader, imageDescription); + } else + shader = useShader(shader); shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); shader->setUniformInt(SHADER_TEX, 0); if ((usingFinalShader && *PDT == 0) || CRASHING) - shader->setUniformFloat(SHADER_TIME, m_globalTimer.getSeconds() - shader->initialTime); + shader->setUniformFloat(SHADER_TIME, m_globalTimer.getSeconds() - shader->getInitialTime()); else if (usingFinalShader) shader->setUniformFloat(SHADER_TIME, 0.f); @@ -1815,7 +1488,7 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c shader->setUniformInt(SHADER_APPLY_TINT, 0); } - glBindVertexArray(shader->uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (data.allowCustomUV && m_renderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { const float customUVs[] = { m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVTopLeft.y, m_renderData.primarySurfaceUVTopLeft.x, @@ -1823,10 +1496,10 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVBottomRight.y, }; - glBindBuffer(GL_ARRAY_BUFFER, shader->uniformLocations[SHADER_SHADER_VBO_UV]); + glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO_UV)); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(customUVs), customUVs); } else { - glBindBuffer(GL_ARRAY_BUFFER, shader->uniformLocations[SHADER_SHADER_VBO_UV]); + glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO_UV)); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(fullVerts), fullVerts); } @@ -1875,8 +1548,6 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, const CBox& box) Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); - SShader* shader = &m_shaders->m_shPASSTHRURGBA; - glActiveTexture(GL_TEXTURE0); tex->bind(); @@ -1890,10 +1561,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, const CBox& box) tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); } - useProgram(shader->program); + auto shader = useShader(m_shaders->frag[SH_FRAG_PASSTHRURGBA]); shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); shader->setUniformInt(SHADER_TEX, 0); - glBindVertexArray(shader->uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); m_renderData.damage.forEachRect([this](const auto& RECT) { scissor(&RECT); @@ -1922,9 +1593,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, const CBox& box, CFra Mat3x3 matrix = m_renderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); - SShader* shader = &m_shaders->m_shMATTE; - - useProgram(shader->program); + auto shader = useShader(m_shaders->frag[SH_FRAG_MATTE]); shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); shader->setUniformInt(SHADER_TEX, 0); shader->setUniformInt(SHADER_ALPHA_MATTE, 1); @@ -1936,7 +1605,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, const CBox& box, CFra auto matteTex = matte.getTexture(); matteTex->bind(); - glBindVertexArray(shader->uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); m_renderData.damage.forEachRect([this](const auto& RECT) { scissor(&RECT); @@ -2009,33 +1678,32 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi currentTex->bind(); currentTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); - useProgram(m_shaders->m_shBLURPREPARE.program); + WP shader; // From FB to sRGB const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); - m_shaders->m_shBLURPREPARE.setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) { - passCMUniforms(m_shaders->m_shBLURPREPARE, m_renderData.pMonitor->m_imageDescription, DEFAULT_IMAGE_DESCRIPTION); - m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_SDR_SATURATION, - m_renderData.pMonitor->m_sdrSaturation > 0 && - m_renderData.pMonitor->m_imageDescription->value().transferFunction == - NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? - m_renderData.pMonitor->m_sdrSaturation : - 1.0f); - m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_SDR_BRIGHTNESS, - m_renderData.pMonitor->m_sdrBrightness > 0 && - m_renderData.pMonitor->m_imageDescription->value().transferFunction == - NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? - m_renderData.pMonitor->m_sdrBrightness : - 1.0f); - } + shader = useShader(m_shaders->frag[SH_FRAG_CM_BLURPREPARE]); + passCMUniforms(shader, m_renderData.pMonitor->m_imageDescription, DEFAULT_IMAGE_DESCRIPTION); + shader->setUniformFloat(SHADER_SDR_SATURATION, + m_renderData.pMonitor->m_sdrSaturation > 0 && + m_renderData.pMonitor->m_imageDescription->value().transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? + m_renderData.pMonitor->m_sdrSaturation : + 1.0f); + shader->setUniformFloat(SHADER_SDR_BRIGHTNESS, + m_renderData.pMonitor->m_sdrBrightness > 0 && + m_renderData.pMonitor->m_imageDescription->value().transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? + m_renderData.pMonitor->m_sdrBrightness : + 1.0f); + } else + shader = useShader(m_shaders->frag[SH_FRAG_BLURPREPARE]); - m_shaders->m_shBLURPREPARE.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_CONTRAST, *PBLURCONTRAST); - m_shaders->m_shBLURPREPARE.setUniformFloat(SHADER_BRIGHTNESS, *PBLURBRIGHTNESS); - m_shaders->m_shBLURPREPARE.setUniformInt(SHADER_TEX, 0); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniformFloat(SHADER_CONTRAST, *PBLURCONTRAST); + shader->setUniformFloat(SHADER_BRIGHTNESS, *PBLURBRIGHTNESS); + shader->setUniformInt(SHADER_TEX, 0); - glBindVertexArray(m_shaders->m_shBLURPREPARE.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (!damage.empty()) { damage.forEachRect([this](const auto& RECT) { @@ -2049,7 +1717,7 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi } // declare the draw func - auto drawPass = [&](SShader* pShader, CRegion* pDamage) { + auto drawPass = [&](WP shader, ePreparedFragmentShader frag, CRegion* pDamage) { if (currentRenderToFB == PMIRRORFB) PMIRRORSWAPFB->bind(); else @@ -2063,21 +1731,19 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi currentTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); - useProgram(pShader->program); - // prep two shaders - pShader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - pShader->setUniformFloat(SHADER_RADIUS, *PBLURSIZE * a); // this makes the blursize change with a - if (pShader == &m_shaders->m_shBLUR1) { - m_shaders->m_shBLUR1.setUniformFloat2(SHADER_HALFPIXEL, 0.5f / (m_renderData.pMonitor->m_pixelSize.x / 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y / 2.f)); - m_shaders->m_shBLUR1.setUniformInt(SHADER_PASSES, BLUR_PASSES); - m_shaders->m_shBLUR1.setUniformFloat(SHADER_VIBRANCY, *PBLURVIBRANCY); - m_shaders->m_shBLUR1.setUniformFloat(SHADER_VIBRANCY_DARKNESS, *PBLURVIBRANCYDARKNESS); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniformFloat(SHADER_RADIUS, *PBLURSIZE * a); // this makes the blursize change with a + if (frag == SH_FRAG_BLUR1) { + shader->setUniformFloat2(SHADER_HALFPIXEL, 0.5f / (m_renderData.pMonitor->m_pixelSize.x / 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y / 2.f)); + shader->setUniformInt(SHADER_PASSES, BLUR_PASSES); + shader->setUniformFloat(SHADER_VIBRANCY, *PBLURVIBRANCY); + shader->setUniformFloat(SHADER_VIBRANCY_DARKNESS, *PBLURVIBRANCYDARKNESS); } else - m_shaders->m_shBLUR2.setUniformFloat2(SHADER_HALFPIXEL, 0.5f / (m_renderData.pMonitor->m_pixelSize.x * 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y * 2.f)); - pShader->setUniformInt(SHADER_TEX, 0); + shader->setUniformFloat2(SHADER_HALFPIXEL, 0.5f / (m_renderData.pMonitor->m_pixelSize.x * 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y * 2.f)); + shader->setUniformInt(SHADER_TEX, 0); - glBindVertexArray(pShader->uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (!pDamage->empty()) { pDamage->forEachRect([this](const auto& RECT) { @@ -2103,14 +1769,16 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi CRegion tempDamage{damage}; // and draw + auto shader = useShader(m_shaders->frag[SH_FRAG_BLUR1]); for (auto i = 1; i <= BLUR_PASSES; ++i) { tempDamage = damage.copy().scale(1.f / (1 << i)); - drawPass(&m_shaders->m_shBLUR1, &tempDamage); // down + drawPass(shader, SH_FRAG_BLUR1, &tempDamage); // down } + shader = useShader(m_shaders->frag[SH_FRAG_BLUR2]); for (auto i = BLUR_PASSES - 1; i >= 0; --i) { tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big - drawPass(&m_shaders->m_shBLUR2, &tempDamage); // up + drawPass(shader, SH_FRAG_BLUR2, &tempDamage); // up } // finalize the image @@ -2131,14 +1799,14 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi currentTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); - useProgram(m_shaders->m_shBLURFINISH.program); - m_shaders->m_shBLURFINISH.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - m_shaders->m_shBLURFINISH.setUniformFloat(SHADER_NOISE, *PBLURNOISE); - m_shaders->m_shBLURFINISH.setUniformFloat(SHADER_BRIGHTNESS, *PBLURBRIGHTNESS); + auto shader = useShader(m_shaders->frag[SH_FRAG_BLURFINISH]); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniformFloat(SHADER_NOISE, *PBLURNOISE); + shader->setUniformFloat(SHADER_BRIGHTNESS, *PBLURBRIGHTNESS); - m_shaders->m_shBLURFINISH.setUniformInt(SHADER_TEX, 0); + shader->setUniformInt(SHADER_TEX, 0); - glBindVertexArray(m_shaders->m_shBLURFINISH.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (!damage.empty()) { damage.forEachRect([this](const auto& RECT) { @@ -2491,19 +2159,21 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr const auto BLEND = m_blend; blend(true); - useProgram(m_shaders->m_shBORDER1.program); + WP shader; - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); - m_shaders->m_shBORDER1.setUniformInt(SHADER_SKIP_CM, skipCM); - if (!skipCM) - passCMUniforms(m_shaders->m_shBORDER1, DEFAULT_IMAGE_DESCRIPTION); + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); + if (!skipCM) { + shader = useShader(m_shaders->frag[SH_FRAG_CM_BORDER1]); + passCMUniforms(shader, DEFAULT_IMAGE_DESCRIPTION); + } else + shader = useShader(m_shaders->frag[SH_FRAG_BORDER1]); - m_shaders->m_shBORDER1.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - m_shaders->m_shBORDER1.setUniform4fv(SHADER_GRADIENT, grad.m_colorsOkLabA.size() / 4, grad.m_colorsOkLabA); - m_shaders->m_shBORDER1.setUniformInt(SHADER_GRADIENT_LENGTH, grad.m_colorsOkLabA.size() / 4); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ANGLE, sc(grad.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ALPHA, data.a); - m_shaders->m_shBORDER1.setUniformInt(SHADER_GRADIENT2_LENGTH, 0); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniform4fv(SHADER_GRADIENT, grad.m_colorsOkLabA.size() / 4, grad.m_colorsOkLabA); + shader->setUniformInt(SHADER_GRADIENT_LENGTH, grad.m_colorsOkLabA.size() / 4); + shader->setUniformFloat(SHADER_ANGLE, sc(grad.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); + shader->setUniformFloat(SHADER_ALPHA, data.a); + shader->setUniformInt(SHADER_GRADIENT2_LENGTH, 0); CBox transformedBox = newBox; transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, @@ -2512,15 +2182,15 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_FULL_SIZE_UNTRANSFORMED, sc(newBox.width), sc(newBox.height)); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_RADIUS, round); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_RADIUS_OUTER, data.outerRound == -1 ? round : data.outerRound); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_THICK, scaledBorderSize); + shader->setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE_UNTRANSFORMED, sc(newBox.width), sc(newBox.height)); + shader->setUniformFloat(SHADER_RADIUS, round); + shader->setUniformFloat(SHADER_RADIUS_OUTER, data.outerRound == -1 ? round : data.outerRound); + shader->setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); + shader->setUniformFloat(SHADER_THICK, scaledBorderSize); - glBindVertexArray(m_shaders->m_shBORDER1.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); // calculate the border's region, which we need to render over. No need to run the shader on // things outside there @@ -2575,23 +2245,24 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr const auto BLEND = m_blend; blend(true); - useProgram(m_shaders->m_shBORDER1.program); + WP shader; + const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); + if (!skipCM) { + shader = useShader(m_shaders->frag[SH_FRAG_CM_BORDER1]); + passCMUniforms(shader, DEFAULT_IMAGE_DESCRIPTION); + } else + shader = useShader(m_shaders->frag[SH_FRAG_BORDER1]); - const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); - m_shaders->m_shBORDER1.setUniformInt(SHADER_SKIP_CM, skipCM); - if (!skipCM) - passCMUniforms(m_shaders->m_shBORDER1, DEFAULT_IMAGE_DESCRIPTION); - - m_shaders->m_shBORDER1.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - m_shaders->m_shBORDER1.setUniform4fv(SHADER_GRADIENT, grad1.m_colorsOkLabA.size() / 4, grad1.m_colorsOkLabA); - m_shaders->m_shBORDER1.setUniformInt(SHADER_GRADIENT_LENGTH, grad1.m_colorsOkLabA.size() / 4); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ANGLE, sc(grad1.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniform4fv(SHADER_GRADIENT, grad1.m_colorsOkLabA.size() / 4, grad1.m_colorsOkLabA); + shader->setUniformInt(SHADER_GRADIENT_LENGTH, grad1.m_colorsOkLabA.size() / 4); + shader->setUniformFloat(SHADER_ANGLE, sc(grad1.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); if (!grad2.m_colorsOkLabA.empty()) - m_shaders->m_shBORDER1.setUniform4fv(SHADER_GRADIENT2, grad2.m_colorsOkLabA.size() / 4, grad2.m_colorsOkLabA); - m_shaders->m_shBORDER1.setUniformInt(SHADER_GRADIENT2_LENGTH, grad2.m_colorsOkLabA.size() / 4); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ANGLE2, sc(grad2.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ALPHA, data.a); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_GRADIENT_LERP, lerp); + shader->setUniform4fv(SHADER_GRADIENT2, grad2.m_colorsOkLabA.size() / 4, grad2.m_colorsOkLabA); + shader->setUniformInt(SHADER_GRADIENT2_LENGTH, grad2.m_colorsOkLabA.size() / 4); + shader->setUniformFloat(SHADER_ANGLE2, sc(grad2.m_angle / (std::numbers::pi / 180.0)) % 360 * (std::numbers::pi / 180.0)); + shader->setUniformFloat(SHADER_ALPHA, data.a); + shader->setUniformFloat(SHADER_GRADIENT_LERP, lerp); CBox transformedBox = newBox; transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x, @@ -2600,15 +2271,15 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); - m_shaders->m_shBORDER1.setUniformFloat2(SHADER_FULL_SIZE_UNTRANSFORMED, sc(newBox.width), sc(newBox.height)); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_RADIUS, round); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_RADIUS_OUTER, data.outerRound == -1 ? round : data.outerRound); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); - m_shaders->m_shBORDER1.setUniformFloat(SHADER_THICK, scaledBorderSize); + shader->setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE_UNTRANSFORMED, sc(newBox.width), sc(newBox.height)); + shader->setUniformFloat(SHADER_RADIUS, round); + shader->setUniformFloat(SHADER_RADIUS_OUTER, data.outerRound == -1 ? round : data.outerRound); + shader->setUniformFloat(SHADER_ROUNDING_POWER, data.roundingPower); + shader->setUniformFloat(SHADER_THICK, scaledBorderSize); - glBindVertexArray(m_shaders->m_shBORDER1.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); // calculate the border's region, which we need to render over. No need to run the shader on // things outside there @@ -2653,29 +2324,29 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun blend(true); - useProgram(m_shaders->m_shSHADOW.program); + auto shader = useShader(m_shaders->frag[SH_FRAG_SHADOW]); const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription->id() == DEFAULT_IMAGE_DESCRIPTION->id(); - m_shaders->m_shSHADOW.setUniformInt(SHADER_SKIP_CM, skipCM); + shader->setUniformInt(SHADER_SKIP_CM, skipCM); if (!skipCM) - passCMUniforms(m_shaders->m_shSHADOW, DEFAULT_IMAGE_DESCRIPTION); + passCMUniforms(shader, DEFAULT_IMAGE_DESCRIPTION); - m_shaders->m_shSHADOW.setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); - m_shaders->m_shSHADOW.setUniformFloat4(SHADER_COLOR, col.r, col.g, col.b, col.a * a); + shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix()); + shader->setUniformFloat4(SHADER_COLOR, col.r, col.g, col.b, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); const auto BOTTOMRIGHT = Vector2D(newBox.width - (range + round), newBox.height - (range + round)); const auto FULLSIZE = Vector2D(newBox.width, newBox.height); // Rounded corners - m_shaders->m_shSHADOW.setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); - m_shaders->m_shSHADOW.setUniformFloat2(SHADER_BOTTOM_RIGHT, sc(BOTTOMRIGHT.x), sc(BOTTOMRIGHT.y)); - m_shaders->m_shSHADOW.setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); - m_shaders->m_shSHADOW.setUniformFloat(SHADER_RADIUS, range + round); - m_shaders->m_shSHADOW.setUniformFloat(SHADER_ROUNDING_POWER, roundingPower); - m_shaders->m_shSHADOW.setUniformFloat(SHADER_RANGE, range); - m_shaders->m_shSHADOW.setUniformFloat(SHADER_SHADOW_POWER, SHADOWPOWER); + shader->setUniformFloat2(SHADER_TOP_LEFT, sc(TOPLEFT.x), sc(TOPLEFT.y)); + shader->setUniformFloat2(SHADER_BOTTOM_RIGHT, sc(BOTTOMRIGHT.x), sc(BOTTOMRIGHT.y)); + shader->setUniformFloat2(SHADER_FULL_SIZE, sc(FULLSIZE.x), sc(FULLSIZE.y)); + shader->setUniformFloat(SHADER_RADIUS, range + round); + shader->setUniformFloat(SHADER_ROUNDING_POWER, roundingPower); + shader->setUniformFloat(SHADER_RANGE, range); + shader->setUniformFloat(SHADER_SHADOW_POWER, SHADOWPOWER); - glBindVertexArray(m_shaders->m_shSHADOW.uniformLocations[SHADER_SHADER_VAO]); + glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)); if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; @@ -2977,12 +2648,14 @@ void CHyprOpenGLImpl::initMissingAssetTexture() { m_missingAssetTexture = tex; } -void CHyprOpenGLImpl::useProgram(GLuint prog) { - if (m_currentProgram == prog) - return; +WP CHyprOpenGLImpl::useShader(WP prog) { + if (m_currentProgram == prog->program()) + return prog; - glUseProgram(prog); - m_currentProgram = prog; + glUseProgram(prog->program()); + m_currentProgram = prog->program(); + + return prog; } void CHyprOpenGLImpl::initAssets() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index e71429b7..857cb891 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -81,23 +81,43 @@ enum eMonitorExtraRenderFBs : uint8_t { FB_MONITOR_RENDER_EXTRA_BLUR, }; +enum ePreparedFragmentShader : uint8_t { + SH_FRAG_QUAD = 0, + SH_FRAG_RGBA, + SH_FRAG_PASSTHRURGBA, + SH_FRAG_MATTE, + SH_FRAG_RGBX, + SH_FRAG_EXT, + SH_FRAG_BLUR1, + SH_FRAG_BLUR2, + SH_FRAG_CM_BLURPREPARE, + SH_FRAG_BLURPREPARE, + SH_FRAG_BLURFINISH, + SH_FRAG_SHADOW, + SH_FRAG_CM_BORDER1, + SH_FRAG_BORDER1, + SH_FRAG_GLITCH, + SH_FRAG_CM_RGBA, + SH_FRAG_CM_RGBX, + + SH_FRAG_LAST, +}; + +struct SFragShaderDesc { + ePreparedFragmentShader id; + const char* file; +}; + struct SPreparedShaders { - std::string TEXVERTSRC; - std::string TEXVERTSRC320; - SShader m_shQUAD; - SShader m_shRGBA; - SShader m_shPASSTHRURGBA; - SShader m_shMATTE; - SShader m_shRGBX; - SShader m_shEXT; - SShader m_shBLUR1; - SShader m_shBLUR2; - SShader m_shBLURPREPARE; - SShader m_shBLURFINISH; - SShader m_shSHADOW; - SShader m_shBORDER1; - SShader m_shGLITCH; - SShader m_shCM; + SPreparedShaders() { + for (auto& f : frag) { + f = makeShared(); + } + } + + std::string TEXVERTSRC; + std::string TEXVERTSRC320; + std::array, SH_FRAG_LAST> frag; }; struct SMonitorRenderData { @@ -274,9 +294,7 @@ class CHyprOpenGLImpl { bool initShaders(); - GLuint createProgram(const std::string&, const std::string&, bool dynamic = false, bool silent = false); - GLuint compileShader(const GLuint&, std::string, bool dynamic = false, bool silent = false); - void useProgram(GLuint prog); + WP useShader(WP prog); void ensureLockTexturesRendered(bool load); @@ -375,13 +393,12 @@ class CHyprOpenGLImpl { SP m_lockDeadTexture; SP m_lockDead2Texture; SP m_lockTtyTextTexture; - SShader m_finalScreenShader; + SP m_finalScreenShader; CTimer m_globalTimer; GLuint m_currentProgram; ASP m_backgroundResource; bool m_backgroundResourceFailed = false; - void logShaderError(const GLuint&, bool program = false, bool silent = false); void createBGTextureForMonitor(PHLMONITOR); void initDRMFormats(); void initEGL(bool gbm); @@ -403,9 +420,9 @@ class CHyprOpenGLImpl { CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurFramebufferWithDamage(float a, CRegion* damage, CFramebuffer& source); - void passCMUniforms(SShader&, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, + void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1); - void passCMUniforms(SShader&, const NColorManagement::PImageDescription imageDescription); + void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription); void renderTexturePrimitive(SP tex, const CBox& box); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data); diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp index 5081d4c4..635e1328 100644 --- a/src/render/Shader.cpp +++ b/src/render/Shader.cpp @@ -1,4 +1,5 @@ #include "Shader.hpp" +#include "../config/ConfigManager.hpp" #include "render/OpenGL.hpp" #define EPSILON(x, y) (std::abs((x) - (y)) < 1e-5f) @@ -14,51 +15,235 @@ static bool compareFloat(auto a, auto b) { return true; } -SShader::SShader() { - uniformLocations.fill(-1); +CShader::CShader() { + m_uniformLocations.fill(-1); } -SShader::~SShader() { +CShader::~CShader() { destroy(); } -void SShader::createVao() { +void CShader::logShaderError(const GLuint& shader, bool program, bool silent) { + GLint maxLength = 0; + if (program) + glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + else + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + + std::vector errorLog(maxLength); + if (program) + glGetProgramInfoLog(shader, maxLength, &maxLength, errorLog.data()); + else + glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); + std::string errorStr(errorLog.begin(), errorLog.end()); + + const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr; + + Log::logger->log(Log::ERR, "Failed to link shader: {}", FULLERROR); + + if (!silent) + g_pConfigManager->addParseError(FULLERROR); +} + +GLuint CShader::compileShader(const GLuint& type, std::string src, bool dynamic, bool silent) { + auto shader = glCreateShader(type); + + auto shaderSource = src.c_str(); + + glShaderSource(shader, 1, &shaderSource, nullptr); + glCompileShader(shader); + + GLint ok; + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + + if (dynamic) { + if (ok == GL_FALSE) { + logShaderError(shader, false, silent); + return 0; + } + } else { + if (ok != GL_TRUE) + logShaderError(shader, false); + RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); + } + + return shader; +} + +bool CShader::createProgram(const std::string& vert, const std::string& frag, bool dynamic, bool silent) { + auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert, dynamic, silent); + if (dynamic) { + if (vertCompiled == 0) + return false; + } else + RASSERT(vertCompiled, "Compiling shader failed. VERTEX nullptr! Shader source:\n\n{}", vert); + + auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag, dynamic, silent); + if (dynamic) { + if (fragCompiled == 0) + return false; + } else + RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT nullptr! Shader source:\n\n{}", frag); + + auto prog = glCreateProgram(); + glAttachShader(prog, vertCompiled); + glAttachShader(prog, fragCompiled); + glLinkProgram(prog); + + glDetachShader(prog, vertCompiled); + glDetachShader(prog, fragCompiled); + glDeleteShader(vertCompiled); + glDeleteShader(fragCompiled); + + GLint ok; + glGetProgramiv(prog, GL_LINK_STATUS, &ok); + if (dynamic) { + if (ok == GL_FALSE) { + logShaderError(prog, true, silent); + return false; + } + } else { + if (ok != GL_TRUE) + logShaderError(prog, true); + RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); + } + + m_program = prog; + + getUniformLocations(); + createVao(); + return true; +} + +// its fine to call glGet on shaders that dont have the uniform +// this however hardcodes the name now. #TODO maybe dont +void CShader::getUniformLocations() { + auto getUniform = [this](const GLchar* name) { return glGetUniformLocation(m_program, name); }; + auto getAttrib = [this](const GLchar* name) { return glGetAttribLocation(m_program, name); }; + + m_uniformLocations[SHADER_PROJ] = getUniform("proj"); + m_uniformLocations[SHADER_COLOR] = getUniform("color"); + m_uniformLocations[SHADER_ALPHA_MATTE] = getUniform("texMatte"); + m_uniformLocations[SHADER_TEX_TYPE] = getUniform("texType"); + + // shader has #include "CM.glsl" + m_uniformLocations[SHADER_SKIP_CM] = getUniform("skipCM"); + m_uniformLocations[SHADER_SOURCE_TF] = getUniform("sourceTF"); + m_uniformLocations[SHADER_TARGET_TF] = getUniform("targetTF"); + m_uniformLocations[SHADER_SRC_TF_RANGE] = getUniform("srcTFRange"); + m_uniformLocations[SHADER_DST_TF_RANGE] = getUniform("dstTFRange"); + m_uniformLocations[SHADER_TARGET_PRIMARIES] = getUniform("targetPrimaries"); + m_uniformLocations[SHADER_MAX_LUMINANCE] = getUniform("maxLuminance"); + m_uniformLocations[SHADER_SRC_REF_LUMINANCE] = getUniform("srcRefLuminance"); + m_uniformLocations[SHADER_DST_MAX_LUMINANCE] = getUniform("dstMaxLuminance"); + m_uniformLocations[SHADER_DST_REF_LUMINANCE] = getUniform("dstRefLuminance"); + m_uniformLocations[SHADER_SDR_SATURATION] = getUniform("sdrSaturation"); + m_uniformLocations[SHADER_SDR_BRIGHTNESS] = getUniform("sdrBrightnessMultiplier"); + m_uniformLocations[SHADER_CONVERT_MATRIX] = getUniform("convertMatrix"); + // + m_uniformLocations[SHADER_TEX] = getUniform("tex"); + m_uniformLocations[SHADER_ALPHA] = getUniform("alpha"); + m_uniformLocations[SHADER_POS_ATTRIB] = getAttrib("pos"); + m_uniformLocations[SHADER_TEX_ATTRIB] = getAttrib("texcoord"); + m_uniformLocations[SHADER_MATTE_TEX_ATTRIB] = getAttrib("texcoordMatte"); + m_uniformLocations[SHADER_DISCARD_OPAQUE] = getUniform("discardOpaque"); + m_uniformLocations[SHADER_DISCARD_ALPHA] = getUniform("discardAlpha"); + m_uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = getUniform("discardAlphaValue"); + /* set in createVao + m_uniformLocations[SHADER_SHADER_VAO] + m_uniformLocations[SHADER_SHADER_VBO_POS] + m_uniformLocations[SHADER_SHADER_VBO_UV] + */ + m_uniformLocations[SHADER_TOP_LEFT] = getUniform("topLeft"); + m_uniformLocations[SHADER_BOTTOM_RIGHT] = getUniform("bottomRight"); + + // compat for screenshaders + auto fullSize = getUniform("fullSize"); + if (fullSize == -1) + fullSize = getUniform("screen_size"); + if (fullSize == -1) + fullSize = getUniform("screenSize"); + m_uniformLocations[SHADER_FULL_SIZE] = fullSize; + + m_uniformLocations[SHADER_FULL_SIZE_UNTRANSFORMED] = getUniform("fullSizeUntransformed"); + m_uniformLocations[SHADER_RADIUS] = getUniform("radius"); + m_uniformLocations[SHADER_RADIUS_OUTER] = getUniform("radiusOuter"); + m_uniformLocations[SHADER_ROUNDING_POWER] = getUniform("roundingPower"); + m_uniformLocations[SHADER_THICK] = getUniform("thick"); + m_uniformLocations[SHADER_HALFPIXEL] = getUniform("halfpixel"); + m_uniformLocations[SHADER_RANGE] = getUniform("range"); + m_uniformLocations[SHADER_SHADOW_POWER] = getUniform("shadowPower"); + m_uniformLocations[SHADER_USE_ALPHA_MATTE] = getUniform("useAlphaMatte"); + m_uniformLocations[SHADER_APPLY_TINT] = getUniform("applyTint"); + m_uniformLocations[SHADER_TINT] = getUniform("tint"); + m_uniformLocations[SHADER_GRADIENT] = getUniform("gradient"); + m_uniformLocations[SHADER_GRADIENT_LENGTH] = getUniform("gradientLength"); + m_uniformLocations[SHADER_GRADIENT2] = getUniform("gradient2"); + m_uniformLocations[SHADER_GRADIENT2_LENGTH] = getUniform("gradient2Length"); + m_uniformLocations[SHADER_ANGLE] = getUniform("angle"); + m_uniformLocations[SHADER_ANGLE2] = getUniform("angle2"); + m_uniformLocations[SHADER_GRADIENT_LERP] = getUniform("gradientLerp"); + m_uniformLocations[SHADER_TIME] = getUniform("time"); + m_uniformLocations[SHADER_DISTORT] = getUniform("distort"); + m_uniformLocations[SHADER_WL_OUTPUT] = getUniform("wl_output"); + m_uniformLocations[SHADER_CONTRAST] = getUniform("contrast"); + m_uniformLocations[SHADER_PASSES] = getUniform("passes"); + m_uniformLocations[SHADER_VIBRANCY] = getUniform("vibrancy"); + m_uniformLocations[SHADER_VIBRANCY_DARKNESS] = getUniform("vibrancy_darkness"); + m_uniformLocations[SHADER_BRIGHTNESS] = getUniform("brightness"); + m_uniformLocations[SHADER_NOISE] = getUniform("noise"); + m_uniformLocations[SHADER_POINTER] = getUniform("pointer_position"); + m_uniformLocations[SHADER_POINTER_SHAPE] = getUniform("pointer_shape"); + m_uniformLocations[SHADER_POINTER_SWITCH_TIME] = getUniform("pointer_switch_time"); + m_uniformLocations[SHADER_POINTER_SHAPE_PREVIOUS] = getUniform("pointer_shape_previous"); + m_uniformLocations[SHADER_POINTER_PRESSED_POSITIONS] = getUniform("pointer_pressed_positions"); + m_uniformLocations[SHADER_POINTER_HIDDEN] = getUniform("pointer_hidden"); + m_uniformLocations[SHADER_POINTER_KILLING] = getUniform("pointer_killing"); + m_uniformLocations[SHADER_POINTER_PRESSED_TIMES] = getUniform("pointer_pressed_times"); + m_uniformLocations[SHADER_POINTER_PRESSED_KILLED] = getUniform("pointer_pressed_killed"); + m_uniformLocations[SHADER_POINTER_PRESSED_TOUCHED] = getUniform("pointer_pressed_touched"); + m_uniformLocations[SHADER_POINTER_INACTIVE_TIMEOUT] = getUniform("pointer_inactive_timeout"); + m_uniformLocations[SHADER_POINTER_LAST_ACTIVE] = getUniform("pointer_last_active"); + m_uniformLocations[SHADER_POINTER_SIZE] = getUniform("pointer_size"); +} + +void CShader::createVao() { GLuint shaderVao = 0, shaderVbo = 0, shaderVboUv = 0; glGenVertexArrays(1, &shaderVao); glBindVertexArray(shaderVao); - if (uniformLocations[SHADER_POS_ATTRIB] != -1) { + if (m_uniformLocations[SHADER_POS_ATTRIB] != -1) { glGenBuffers(1, &shaderVbo); glBindBuffer(GL_ARRAY_BUFFER, shaderVbo); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW); - glEnableVertexAttribArray(uniformLocations[SHADER_POS_ATTRIB]); - glVertexAttribPointer(uniformLocations[SHADER_POS_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_uniformLocations[SHADER_POS_ATTRIB]); + glVertexAttribPointer(m_uniformLocations[SHADER_POS_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); } // UV VBO (dynamic, may be updated per frame) - if (uniformLocations[SHADER_TEX_ATTRIB] != -1) { + if (m_uniformLocations[SHADER_TEX_ATTRIB] != -1) { glGenBuffers(1, &shaderVboUv); glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_DYNAMIC_DRAW); // Initial dummy UVs - glEnableVertexAttribArray(uniformLocations[SHADER_TEX_ATTRIB]); - glVertexAttribPointer(uniformLocations[SHADER_TEX_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_uniformLocations[SHADER_TEX_ATTRIB]); + glVertexAttribPointer(m_uniformLocations[SHADER_TEX_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); - uniformLocations[SHADER_SHADER_VAO] = shaderVao; - uniformLocations[SHADER_SHADER_VBO_POS] = shaderVbo; - uniformLocations[SHADER_SHADER_VBO_UV] = shaderVboUv; + m_uniformLocations[SHADER_SHADER_VAO] = shaderVao; + m_uniformLocations[SHADER_SHADER_VBO_POS] = shaderVbo; + m_uniformLocations[SHADER_SHADER_VBO_UV] = shaderVboUv; - RASSERT(uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created"); - RASSERT(uniformLocations[SHADER_SHADER_VBO_POS] >= 0, "SHADER_SHADER_VBO_POS could not be created"); - RASSERT(uniformLocations[SHADER_SHADER_VBO_UV] >= 0, "SHADER_SHADER_VBO_UV could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VBO_POS] >= 0, "SHADER_SHADER_VBO_POS could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VBO_UV] >= 0, "SHADER_SHADER_VBO_UV could not be created"); } -void SShader::setUniformInt(eShaderUniform location, GLint v0) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformInt(eShaderUniform location, GLint v0) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -67,11 +252,11 @@ void SShader::setUniformInt(eShaderUniform location, GLint v0) { return; cached = v0; - glUniform1i(uniformLocations[location], v0); + glUniform1i(m_uniformLocations[location], v0); } -void SShader::setUniformFloat(eShaderUniform location, GLfloat v0) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat(eShaderUniform location, GLfloat v0) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -83,11 +268,11 @@ void SShader::setUniformFloat(eShaderUniform location, GLfloat v0) { } cached = v0; - glUniform1f(uniformLocations[location], v0); + glUniform1f(m_uniformLocations[location], v0); } -void SShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -99,11 +284,11 @@ void SShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) } cached = std::array{v0, v1}; - glUniform2f(uniformLocations[location], v0, v1); + glUniform2f(m_uniformLocations[location], v0, v1); } -void SShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -115,11 +300,11 @@ void SShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, } cached = std::array{v0, v1, v2}; - glUniform3f(uniformLocations[location], v0, v1, v2); + glUniform3f(m_uniformLocations[location], v0, v1, v2); } -void SShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -131,11 +316,11 @@ void SShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, } cached = std::array{v0, v1, v2, v3}; - glUniform4f(uniformLocations[location], v0, v1, v2, v3); + glUniform4f(m_uniformLocations[location], v0, v1, v2, v3); } -void SShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -147,11 +332,11 @@ void SShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLbool } cached = SUniformMatrix3Data{.count = count, .transpose = transpose, .value = value}; - glUniformMatrix3fv(uniformLocations[location], count, transpose, value.data()); + glUniformMatrix3fv(m_uniformLocations[location], count, transpose, value.data()); } -void SShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -163,11 +348,11 @@ void SShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLbo } cached = SUniformMatrix4Data{.count = count, .transpose = transpose, .value = value}; - glUniformMatrix4x2fv(uniformLocations[location], count, transpose, value.data()); + glUniformMatrix4x2fv(m_uniformLocations[location], count, transpose, value.data()); } -void SShader::setUniformfv(eShaderUniform location, GLsizei count, const std::vector& value, GLsizei vec_size) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformfv(eShaderUniform location, GLsizei count, const std::vector& value, GLsizei vec_size) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -180,36 +365,36 @@ void SShader::setUniformfv(eShaderUniform location, GLsizei count, const std::ve cached = SUniformVData{.count = count, .value = value}; switch (vec_size) { - case 1: glUniform1fv(uniformLocations[location], count, value.data()); break; - case 2: glUniform2fv(uniformLocations[location], count, value.data()); break; - case 4: glUniform4fv(uniformLocations[location], count, value.data()); break; + case 1: glUniform1fv(m_uniformLocations[location], count, value.data()); break; + case 2: glUniform2fv(m_uniformLocations[location], count, value.data()); break; + case 4: glUniform4fv(m_uniformLocations[location], count, value.data()); break; default: UNREACHABLE(); } } -void SShader::setUniform1fv(eShaderUniform location, GLsizei count, const std::vector& value) { +void CShader::setUniform1fv(eShaderUniform location, GLsizei count, const std::vector& value) { setUniformfv(location, count, value, 1); } -void SShader::setUniform2fv(eShaderUniform location, GLsizei count, const std::vector& value) { +void CShader::setUniform2fv(eShaderUniform location, GLsizei count, const std::vector& value) { setUniformfv(location, count, value, 2); } -void SShader::setUniform4fv(eShaderUniform location, GLsizei count, const std::vector& value) { +void CShader::setUniform4fv(eShaderUniform location, GLsizei count, const std::vector& value) { setUniformfv(location, count, value, 4); } -void SShader::destroy() { +void CShader::destroy() { uniformStatus.fill(std::monostate()); - if (program == 0) + if (m_program == 0) return; GLuint shaderVao, shaderVbo, shaderVboUv; - shaderVao = uniformLocations[SHADER_SHADER_VAO] == -1 ? 0 : uniformLocations[SHADER_SHADER_VAO]; - shaderVbo = uniformLocations[SHADER_SHADER_VBO_POS] == -1 ? 0 : uniformLocations[SHADER_SHADER_VBO_POS]; - shaderVboUv = uniformLocations[SHADER_SHADER_VBO_UV] == -1 ? 0 : uniformLocations[SHADER_SHADER_VBO_UV]; + shaderVao = m_uniformLocations[SHADER_SHADER_VAO] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VAO]; + shaderVbo = m_uniformLocations[SHADER_SHADER_VBO_POS] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VBO_POS]; + shaderVboUv = m_uniformLocations[SHADER_SHADER_VBO_UV] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VBO_UV]; if (shaderVao) glDeleteVertexArrays(1, &shaderVao); @@ -220,6 +405,22 @@ void SShader::destroy() { if (shaderVboUv) glDeleteBuffers(1, &shaderVboUv); - glDeleteProgram(program); - program = 0; + glDeleteProgram(m_program); + m_program = 0; +} + +GLint CShader::getUniformLocation(eShaderUniform location) const { + return m_uniformLocations[location]; +} + +GLuint CShader::program() const { + return m_program; +} + +int CShader::getInitialTime() const { + return m_initialTime; +} + +void CShader::setInitialTime(int time) { + m_initialTime = time; } diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 50ff5889..6ab8248b 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -80,15 +80,32 @@ enum eShaderUniform : uint8_t { SHADER_LAST, }; -struct SShader { - SShader(); - ~SShader(); +class CShader { + public: + CShader(); + ~CShader(); - GLuint program = 0; + bool createProgram(const std::string& vert, const std::string& frag, bool dynamic = false, bool silent = false); + void setUniformInt(eShaderUniform location, GLint v0); + void setUniformFloat(eShaderUniform location, GLfloat v0); + void setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1); + void setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2); + void setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value); + void setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value); + void setUniform1fv(eShaderUniform location, GLsizei count, const std::vector& value); + void setUniform2fv(eShaderUniform location, GLsizei count, const std::vector& value); + void setUniform4fv(eShaderUniform location, GLsizei count, const std::vector& value); + void destroy(); + GLuint program() const; + GLint getUniformLocation(eShaderUniform location) const; + int getInitialTime() const; + void setInitialTime(int time); - std::array uniformLocations; - - float initialTime = 0; + private: + GLuint m_program = 0; + float m_initialTime = 0; + std::array m_uniformLocations; struct SUniformMatrix3Data { GLsizei count = 0; @@ -114,19 +131,9 @@ struct SShader { uniformStatus; // - void createVao(); - void setUniformInt(eShaderUniform location, GLint v0); - void setUniformFloat(eShaderUniform location, GLfloat v0); - void setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1); - void setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2); - void setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); - void setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value); - void setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array value); - void setUniform1fv(eShaderUniform location, GLsizei count, const std::vector& value); - void setUniform2fv(eShaderUniform location, GLsizei count, const std::vector& value); - void setUniform4fv(eShaderUniform location, GLsizei count, const std::vector& value); - void destroy(); - - private: - void setUniformfv(eShaderUniform location, GLsizei count, const std::vector& value, GLsizei vec_size); + void logShaderError(const GLuint&, bool program = false, bool silent = false); + GLuint compileShader(const GLuint&, std::string, bool dynamic = false, bool silent = false); + void getUniformLocations(); + void createVao(); + void setUniformfv(eShaderUniform location, GLsizei count, const std::vector& value, GLsizei vec_size); }; diff --git a/src/render/shaders/glsl/CMblurprepare.frag b/src/render/shaders/glsl/CMblurprepare.frag new file mode 100644 index 00000000..8ba2d3f8 --- /dev/null +++ b/src/render/shaders/glsl/CMblurprepare.frag @@ -0,0 +1,36 @@ +#version 300 es +#extension GL_ARB_shading_language_include : enable + +precision highp float; +in vec2 v_texcoord; // is in 0-1 +uniform sampler2D tex; + +uniform float contrast; +uniform float brightness; + +uniform int sourceTF; // eTransferFunction +uniform int targetTF; // eTransferFunction + +#include "CM.glsl" +#include "gain.glsl" + +layout(location = 0) out vec4 fragColor; +void main() { + vec4 pixColor = texture(tex, v_texcoord); + + if (sourceTF == CM_TRANSFER_FUNCTION_ST2084_PQ) { + pixColor.rgb /= sdrBrightnessMultiplier; + } + pixColor.rgb = convertMatrix * toLinearRGB(pixColor.rgb, sourceTF); + pixColor = toNit(pixColor, vec2(srcTFRange[0], srcRefLuminance)); + pixColor = fromLinearNit(pixColor, targetTF, dstTFRange); + + // contrast + if (contrast != 1.0) + pixColor.rgb = gain(pixColor.rgb, contrast); + + // brightness + pixColor.rgb *= max(1.0, brightness); + + fragColor = pixColor; +} diff --git a/src/render/shaders/glsl/CMborder.frag b/src/render/shaders/glsl/CMborder.frag new file mode 100644 index 00000000..3c9540a7 --- /dev/null +++ b/src/render/shaders/glsl/CMborder.frag @@ -0,0 +1,98 @@ +#version 300 es +#extension GL_ARB_shading_language_include : enable + +precision highp float; +in vec2 v_texcoord; + +uniform int sourceTF; // eTransferFunction +uniform int targetTF; // eTransferFunction +uniform mat4x2 targetPrimaries; + +uniform vec2 fullSizeUntransformed; +uniform float radiusOuter; +uniform float thick; + +// Gradients are in OkLabA!!!! {l, a, b, alpha} +uniform vec4 gradient[10]; +uniform vec4 gradient2[10]; +uniform int gradientLength; +uniform int gradient2Length; +uniform float angle; +uniform float angle2; +uniform float gradientLerp; +uniform float alpha; + +#include "rounding.glsl" +#include "CM.glsl" +#include "border.glsl" + +layout(location = 0) out vec4 fragColor; +void main() { + highp vec2 pixCoord = vec2(gl_FragCoord); + highp vec2 pixCoordOuter = pixCoord; + highp vec2 originalPixCoord = v_texcoord; + originalPixCoord *= fullSizeUntransformed; + float additionalAlpha = 1.0; + + vec4 pixColor = vec4(1.0, 1.0, 1.0, 1.0); + + bool done = false; + + pixCoord -= topLeft + fullSize * 0.5; + pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; + pixCoordOuter = pixCoord; + pixCoord -= fullSize * 0.5 - radius; + pixCoordOuter -= fullSize * 0.5 - radiusOuter; + + // center the pixes don't make it top-left + pixCoord += vec2(1.0, 1.0) / fullSize; + pixCoordOuter += vec2(1.0, 1.0) / fullSize; + + if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) { + float dist = pow(pow(pixCoord.x,roundingPower)+pow(pixCoord.y,roundingPower),1.0/roundingPower); + float distOuter = pow(pow(pixCoordOuter.x,roundingPower)+pow(pixCoordOuter.y,roundingPower),1.0/roundingPower); + float h = (thick / 2.0); + + if (dist < radius - h) { + // lower + float normalized = smoothstep(0.0, 1.0, (dist - radius + thick + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); + additionalAlpha *= normalized; + done = true; + } else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) { + // higher + float normalized = 1.0 - smoothstep(0.0, 1.0, (distOuter - radiusOuter + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); + additionalAlpha *= normalized; + done = true; + } else if (distOuter < radiusOuter - h) { + additionalAlpha = 1.0; + done = true; + } + } + + // now check for other shit + if (!done) { + // distance to all straight bb borders + float distanceT = originalPixCoord[1]; + float distanceB = fullSizeUntransformed[1] - originalPixCoord[1]; + float distanceL = originalPixCoord[0]; + float distanceR = fullSizeUntransformed[0] - originalPixCoord[0]; + + // get the smallest + float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR)); + + if (smallest > thick) + discard; + } + + if (additionalAlpha == 0.0) + discard; + + pixColor = getColorForCoord(v_texcoord); + pixColor.rgb *= pixColor[3]; + + pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); + + pixColor *= alpha * additionalAlpha; + + fragColor = pixColor; +} diff --git a/src/render/shaders/glsl/CM.frag b/src/render/shaders/glsl/CMrgba.frag similarity index 53% rename from src/render/shaders/glsl/CM.frag rename to src/render/shaders/glsl/CMrgba.frag index 7f075b82..1e4e024d 100644 --- a/src/render/shaders/glsl/CM.frag +++ b/src/render/shaders/glsl/CMrgba.frag @@ -5,19 +5,17 @@ precision highp float; in vec2 v_texcoord; uniform sampler2D tex; -uniform int texType; // eTextureType: 0 - rgba, 1 - rgbx, 2 - ext -// uniform int skipCM; uniform int sourceTF; // eTransferFunction uniform int targetTF; // eTransferFunction uniform mat4x2 targetPrimaries; uniform float alpha; -uniform int discardOpaque; -uniform int discardAlpha; +uniform bool discardOpaque; +uniform bool discardAlpha; uniform float discardAlphaValue; -uniform int applyTint; +uniform bool applyTint; uniform vec3 tint; #include "rounding.glsl" @@ -25,28 +23,22 @@ uniform vec3 tint; layout(location = 0) out vec4 fragColor; void main() { - vec4 pixColor; - if (texType == 1) - pixColor = vec4(texture(tex, v_texcoord).rgb, 1.0); - //else if (texType == 2) - // discard; // this shouldnt happen. - else // assume rgba - pixColor = texture(tex, v_texcoord); + vec4 pixColor = texture(tex, v_texcoord); - if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) + if (discardOpaque && pixColor.a * alpha == 1.0) discard; - if (discardAlpha == 1 && pixColor[3] <= discardAlphaValue) + if (discardAlpha && pixColor.a <= discardAlphaValue) discard; // this shader shouldn't be used when skipCM == 1 pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); - if (applyTint == 1) - pixColor = vec4(pixColor.rgb * tint.rgb, pixColor[3]); + if (applyTint) + pixColor.rgb *= tint; if (radius > 0.0) pixColor = rounding(pixColor); - + fragColor = pixColor * alpha; } diff --git a/src/render/shaders/glsl/CMrgbx.frag b/src/render/shaders/glsl/CMrgbx.frag new file mode 100644 index 00000000..e2b1a838 --- /dev/null +++ b/src/render/shaders/glsl/CMrgbx.frag @@ -0,0 +1,44 @@ +#version 300 es +#extension GL_ARB_shading_language_include : enable + +precision highp float; +in vec2 v_texcoord; +uniform sampler2D tex; + +uniform int sourceTF; // eTransferFunction +uniform int targetTF; // eTransferFunction +uniform mat4x2 targetPrimaries; + +uniform float alpha; + +uniform bool discardOpaque; +uniform bool discardAlpha; +uniform float discardAlphaValue; + +uniform bool applyTint; +uniform vec3 tint; + +#include "rounding.glsl" +#include "CM.glsl" + +layout(location = 0) out vec4 fragColor; +void main() { + vec4 pixColor = vec4(texture(tex, v_texcoord).rgb, 1.0); + + if (discardOpaque && pixColor.a * alpha == 1.0) + discard; + + if (discardAlpha && pixColor.a <= discardAlphaValue) + discard; + + // this shader shouldn't be used when skipCM == 1 + pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); + + if (applyTint) + pixColor.rgb *= tint; + + if (radius > 0.0) + pixColor = rounding(pixColor); + + fragColor = pixColor * alpha; +} diff --git a/src/render/shaders/glsl/blurfinish.frag b/src/render/shaders/glsl/blurfinish.frag index 6ab48337..e3c560e8 100644 --- a/src/render/shaders/glsl/blurfinish.frag +++ b/src/render/shaders/glsl/blurfinish.frag @@ -20,13 +20,11 @@ void main() { // noise float noiseHash = hash(v_texcoord); - float noiseAmount = (mod(noiseHash, 1.0) - 0.5); + float noiseAmount = noiseHash - 0.5; pixColor.rgb += noiseAmount * noise; // brightness - if (brightness < 1.0) { - pixColor.rgb *= brightness; - } + pixColor.rgb *= min(1.0, brightness); fragColor = pixColor; } diff --git a/src/render/shaders/glsl/blurprepare.frag b/src/render/shaders/glsl/blurprepare.frag index 6b9809f8..67cd9966 100644 --- a/src/render/shaders/glsl/blurprepare.frag +++ b/src/render/shaders/glsl/blurprepare.frag @@ -8,41 +8,19 @@ uniform sampler2D tex; uniform float contrast; uniform float brightness; -uniform int skipCM; -uniform int sourceTF; // eTransferFunction -uniform int targetTF; // eTransferFunction - #include "CM.glsl" - -float gain(float x, float k) { - float a = 0.5 * pow(2.0 * ((x < 0.5) ? x : 1.0 - x), k); - return (x < 0.5) ? a : 1.0 - a; -} +#include "gain.glsl" layout(location = 0) out vec4 fragColor; void main() { vec4 pixColor = texture(tex, v_texcoord); - if (skipCM == 0) { - if (sourceTF == CM_TRANSFER_FUNCTION_ST2084_PQ) { - pixColor.rgb /= sdrBrightnessMultiplier; - } - pixColor.rgb = convertMatrix * toLinearRGB(pixColor.rgb, sourceTF); - pixColor = toNit(pixColor, vec2(srcTFRange[0], srcRefLuminance)); - pixColor = fromLinearNit(pixColor, targetTF, dstTFRange); - } - // contrast - if (contrast != 1.0) { - pixColor.r = gain(pixColor.r, contrast); - pixColor.g = gain(pixColor.g, contrast); - pixColor.b = gain(pixColor.b, contrast); - } + if (contrast != 1.0) + pixColor.rgb = gain(pixColor.rgb, contrast); // brightness - if (brightness > 1.0) { - pixColor.rgb *= brightness; - } + pixColor.rgb *= max(1.0, brightness); fragColor = pixColor; } diff --git a/src/render/shaders/glsl/border.frag b/src/render/shaders/glsl/border.frag index 223b4b29..a672452b 100644 --- a/src/render/shaders/glsl/border.frag +++ b/src/render/shaders/glsl/border.frag @@ -4,11 +4,6 @@ precision highp float; in vec2 v_texcoord; -uniform int skipCM; -uniform int sourceTF; // eTransferFunction -uniform int targetTF; // eTransferFunction -uniform mat4x2 targetPrimaries; - uniform vec2 fullSizeUntransformed; uniform float radiusOuter; uniform float thick; @@ -25,89 +20,7 @@ uniform float alpha; #include "rounding.glsl" #include "CM.glsl" - -vec4 okLabAToSrgb(vec4 lab) { - float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0); - float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0); - float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0); - - return vec4(fromLinearRGB( - vec3( - l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292, - l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965), - l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010 - ), CM_TRANSFER_FUNCTION_GAMMA22 - ), lab[3]); -} - -vec4 getOkColorForCoordArray1(vec2 normalizedCoord) { - if (gradientLength < 2) - return gradient[0]; - - float finalAng = 0.0; - - if (angle > 4.71 /* 270 deg */) { - normalizedCoord[1] = 1.0 - normalizedCoord[1]; - finalAng = 6.28 - angle; - } else if (angle > 3.14 /* 180 deg */) { - normalizedCoord[0] = 1.0 - normalizedCoord[0]; - normalizedCoord[1] = 1.0 - normalizedCoord[1]; - finalAng = angle - 3.14; - } else if (angle > 1.57 /* 90 deg */) { - normalizedCoord[0] = 1.0 - normalizedCoord[0]; - finalAng = 3.14 - angle; - } else { - finalAng = angle; - } - - float sine = sin(finalAng); - - float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradientLength - 1); - int bottom = int(floor(progress)); - int top = bottom + 1; - - return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress); -} - -vec4 getOkColorForCoordArray2(vec2 normalizedCoord) { - if (gradient2Length < 2) - return gradient2[0]; - - float finalAng = 0.0; - - if (angle2 > 4.71 /* 270 deg */) { - normalizedCoord[1] = 1.0 - normalizedCoord[1]; - finalAng = 6.28 - angle; - } else if (angle2 > 3.14 /* 180 deg */) { - normalizedCoord[0] = 1.0 - normalizedCoord[0]; - normalizedCoord[1] = 1.0 - normalizedCoord[1]; - finalAng = angle - 3.14; - } else if (angle2 > 1.57 /* 90 deg */) { - normalizedCoord[0] = 1.0 - normalizedCoord[0]; - finalAng = 3.14 - angle2; - } else { - finalAng = angle2; - } - - float sine = sin(finalAng); - - float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1); - int bottom = int(floor(progress)); - int top = bottom + 1; - - return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress); -} - -vec4 getColorForCoord(vec2 normalizedCoord) { - vec4 result1 = getOkColorForCoordArray1(normalizedCoord); - - if (gradient2Length <= 0) - return okLabAToSrgb(result1); - - vec4 result2 = getOkColorForCoordArray2(normalizedCoord); - - return okLabAToSrgb(mix(result1, result2, gradientLerp)); -} +#include "border.glsl" layout(location = 0) out vec4 fragColor; void main() { @@ -173,9 +86,6 @@ void main() { pixColor = getColorForCoord(v_texcoord); pixColor.rgb *= pixColor[3]; - if (skipCM == 0) - pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); - pixColor *= alpha * additionalAlpha; fragColor = pixColor; diff --git a/src/render/shaders/glsl/border.glsl b/src/render/shaders/glsl/border.glsl new file mode 100644 index 00000000..c5ad7f3d --- /dev/null +++ b/src/render/shaders/glsl/border.glsl @@ -0,0 +1,82 @@ +vec4 okLabAToSrgb(vec4 lab) { + float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0); + float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0); + float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0); + + return vec4(fromLinearRGB( + vec3( + l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292, + l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965), + l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010 + ), CM_TRANSFER_FUNCTION_GAMMA22 + ), lab[3]); +} + +vec4 getOkColorForCoordArray1(vec2 normalizedCoord) { + if (gradientLength < 2) + return gradient[0]; + + float finalAng = 0.0; + + if (angle > 4.71 /* 270 deg */) { + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = 6.28 - angle; + } else if (angle > 3.14 /* 180 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = angle - 3.14; + } else if (angle > 1.57 /* 90 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + finalAng = 3.14 - angle; + } else { + finalAng = angle; + } + + float sine = sin(finalAng); + + float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradientLength - 1); + int bottom = int(floor(progress)); + int top = bottom + 1; + + return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress); +} + +vec4 getOkColorForCoordArray2(vec2 normalizedCoord) { + if (gradient2Length < 2) + return gradient2[0]; + + float finalAng = 0.0; + + if (angle2 > 4.71 /* 270 deg */) { + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = 6.28 - angle; + } else if (angle2 > 3.14 /* 180 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = angle - 3.14; + } else if (angle2 > 1.57 /* 90 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + finalAng = 3.14 - angle2; + } else { + finalAng = angle2; + } + + float sine = sin(finalAng); + + float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1); + int bottom = int(floor(progress)); + int top = bottom + 1; + + return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress); +} + +vec4 getColorForCoord(vec2 normalizedCoord) { + vec4 result1 = getOkColorForCoordArray1(normalizedCoord); + + if (gradient2Length <= 0) + return okLabAToSrgb(result1); + + vec4 result2 = getOkColorForCoordArray2(normalizedCoord); + + return okLabAToSrgb(mix(result1, result2, gradientLerp)); +} diff --git a/src/render/shaders/glsl/gain.glsl b/src/render/shaders/glsl/gain.glsl new file mode 100644 index 00000000..2bdc0002 --- /dev/null +++ b/src/render/shaders/glsl/gain.glsl @@ -0,0 +1,6 @@ +vec3 gain(vec3 x, float k) { + vec3 t = step(0.5, x); + vec3 y = mix(x, 1.0 - x, t); + vec3 a = 0.5 * pow(2.0 * y, vec3(k)); + return mix(a, 1.0 - a, t); +} diff --git a/src/render/shaders/glsl/glitch.frag b/src/render/shaders/glsl/glitch.frag index e399a8b1..d7259cc4 100644 --- a/src/render/shaders/glsl/glitch.frag +++ b/src/render/shaders/glsl/glitch.frag @@ -5,7 +5,7 @@ in vec2 v_texcoord; uniform sampler2D tex; uniform float time; // quirk: time is set to 0 at the beginning, should be around 10 when crash. uniform float distort; -uniform vec2 screenSize; +uniform vec2 fullSize; float rand(float co) { return fract(sin(dot(vec2(co, co), vec2(12.9898, 78.233))) * 43758.5453); @@ -31,7 +31,7 @@ void main() { float ABERR_OFFSET = 4.0 * (distort / 5.5) * time; float TEAR_AMOUNT = 9000.0 * (1.0 - (distort / 5.5)); float TEAR_BANDS = 108.0 / 2.0 * (distort / 5.5) * 2.0; - float MELT_AMOUNT = (distort * 8.0) / screenSize.y; + float MELT_AMOUNT = (distort * 8.0) / fullSize.y; float NOISE = abs(mod(noise(v_texcoord) * distort * time * 2.771, 1.0)) * time / 10.0; if (time < 2.0) @@ -44,7 +44,7 @@ void main() { if (time < 3.0) blockOffset = vec2(0,0); - float meltSeed = abs(mod(rand(floor(v_texcoord.x * screenSize.x * 17.719)) * 281.882, 1.0)); + float meltSeed = abs(mod(rand(floor(v_texcoord.x * fullSize.x * 17.719)) * 281.882, 1.0)); if (meltSeed < 0.8) { meltSeed = 0.0; } else { @@ -52,11 +52,11 @@ void main() { } float meltAmount = MELT_AMOUNT * meltSeed; - vec2 pixCoord = vec2(v_texcoord.x + offset + NOISE * 3.0 / screenSize.x + blockOffset.x, v_texcoord.y - meltAmount + 0.02 * NOISE / screenSize.x + NOISE * 3.0 / screenSize.y + blockOffset.y); + vec2 pixCoord = vec2(v_texcoord.x + offset + NOISE * 3.0 / fullSize.x + blockOffset.x, v_texcoord.y - meltAmount + 0.02 * NOISE / fullSize.x + NOISE * 3.0 / fullSize.y + blockOffset.y); vec4 pixColor = texture(tex, pixCoord); - vec4 pixColorLeft = texture(tex, pixCoord + vec2(ABERR_OFFSET / screenSize.x, 0)); - vec4 pixColorRight = texture(tex, pixCoord + vec2(-ABERR_OFFSET / screenSize.x, 0)); + vec4 pixColorLeft = texture(tex, pixCoord + vec2(ABERR_OFFSET / fullSize.x, 0)); + vec4 pixColorRight = texture(tex, pixCoord + vec2(-ABERR_OFFSET / fullSize.x, 0)); pixColor[0] = pixColorLeft[0]; pixColor[2] = pixColorRight[2];