added border gradients

This commit is contained in:
vaxerski 2022-11-26 17:56:43 +00:00
parent 52c0356900
commit 0948b078e1
13 changed files with 200 additions and 40 deletions

View file

@ -239,7 +239,9 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
m_RenderData.pCurrentMonData->m_shBORDER1.color = glGetUniformLocation(prog, "color");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle");
m_RenderData.pCurrentMonData->m_bShadersInitialized = true;
@ -804,7 +806,7 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
counter++;
}
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, int round, float a) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -819,27 +821,13 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
int scaledBorderSize = *PBORDERSIZE * m_RenderData.pMonitor->scale;
if (round < 1) {
// zero rounding, just lines
wlr_box borderbox = {box->x - scaledBorderSize, box->y - scaledBorderSize, scaledBorderSize, box->height + 2 * scaledBorderSize};
renderRect(&borderbox, col, 0); // left
borderbox = {box->x, box->y - (int)scaledBorderSize, box->width + (int)scaledBorderSize, (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // top
borderbox = {box->x + box->width, box->y, (int)scaledBorderSize, box->height + (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // right
borderbox = {box->x, box->y + box->height, box->width, (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // bottom
return;
}
// adjust box
box->x -= scaledBorderSize;
box->y -= scaledBorderSize;
box->width += 2 * scaledBorderSize;
box->height += 2 * scaledBorderSize;
round += scaledBorderSize;
round += round == 0 ? 0 : scaledBorderSize;
float matrix[9];
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
@ -858,7 +846,19 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
// TODO: make gradients already in 0 ... 1 and just pass vec.data(), alpha in shader
float* gradientValues = (float*)malloc(sizeof(float) * grad.m_vColors.size() * 4);
for (size_t i = 0; i < grad.m_vColors.size(); ++i) {
gradientValues[i * 4] = grad.m_vColors[i].r / 255.f;
gradientValues[i * 4 + 1] = grad.m_vColors[i].g / 255.f;
gradientValues[i * 4 + 2] = grad.m_vColors[i].b / 255.f;
gradientValues[i * 4 + 3] = grad.m_vColors[i].a / 255.f * a;
}
glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColors.size(), gradientValues);
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColors.size());
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, grad.m_fAngle);
wlr_box transformedBox;
wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform),
@ -906,6 +906,14 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
free(gradientValues);
// fix back box
box->x += scaledBorderSize;
box->y += scaledBorderSize;
box->width -= 2 * scaledBorderSize;
box->height -= 2 * scaledBorderSize;
}
void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFramebuffer) {

View file

@ -68,6 +68,8 @@ struct SCurrentRenderData {
wlr_box clipBox = {};
};
class CGradientValueData;
class CHyprOpenGLImpl {
public:
@ -82,7 +84,7 @@ public:
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowCustomUV = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round);
void renderBorder(wlr_box*, const CGradientValueData&, int round, float a = 1.0);
void makeWindowSnapshot(CWindow*);
void makeRawWindowSnapshot(CWindow*, CFramebuffer*);

View file

@ -300,14 +300,20 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
rounding *= pMonitor->scale;
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f;
auto grad = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor;
const bool ANIMATED = g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAnimationProgress.isBeingAnimated();
float a1 = renderdata.fadeAlpha * renderdata.alpha / 255.f * (ANIMATED ? g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAnimationProgress.fl() : 1.f);
wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
scaleBox(&windowBox, pMonitor->scale);
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
g_pHyprOpenGL->renderBorder(&windowBox, grad, rounding, a1);
if (ANIMATED) {
float a2 = 1.f - a1;
g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, rounding, a2);
}
}
}

View file

@ -32,6 +32,10 @@ public:
GLint applyTint;
GLint tint;
GLint gradient;
GLint gradientLength;
GLint angle;
GLint getUniformLocation(const std::string&);
private:

View file

@ -14,12 +14,28 @@ uniform float radius;
uniform float thick;
uniform int primitiveMultisample;
uniform vec4 gradient[10];
uniform int gradientLength;
uniform float angle;
vec4 getColorForCoord(vec2 normalizedCoord) {
if (gradientLength < 2)
return gradient[0];
float sine = sin(angle);
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);
}
void main() {
highp vec2 pixCoord = vec2(gl_FragCoord);
vec2 originalPixCoord = fullSize * v_texcoord;
vec4 pixColor = v_color;
vec4 pixColor = getColorForCoord(v_texcoord);
bool done = false;
@ -27,7 +43,7 @@ void main() {
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
pixCoord -= fullSize * 0.5 - radius;
if (min(pixCoord.x, pixCoord.y) > 0.0) {
if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) {
float dist = length(pixCoord);