summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2022-06-25 20:28:40 +0200
committervaxerski <43317083+vaxerski@users.noreply.github.com>2022-06-25 20:28:40 +0200
commit747ff3369d6377628e3e27e3b108c8d61cbc5733 (patch)
treef4b1e1bbc12c6ff162a18bcf94d96b9c932f1baf /src/render
parentb46f45befab6e2aa6daba76ec04cec4286eec56b (diff)
added drop shadows
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp68
-rw-r--r--src/render/OpenGL.hpp2
-rw-r--r--src/render/Renderer.cpp5
-rw-r--r--src/render/Shaders.hpp341
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.cpp66
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.hpp27
-rw-r--r--src/render/decorations/IHyprWindowDecoration.hpp3
-rw-r--r--src/render/shaders/Shadow.hpp83
-rw-r--r--src/render/shaders/Textures.hpp341
9 files changed, 593 insertions, 343 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 92c9d9c9..9951939d 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -75,6 +75,12 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
+ prog = createProgram(QUADVERTSRC, FRAGSHADOW);
+ m_shSHADOW.program = prog;
+ m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
+ m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
+ m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
+
Debug::log(LOG, "Shaders initialized successfully.");
// End shaders
@@ -858,6 +864,68 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
pixman_region32_fini(&fakeDamage);
}
+void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range) {
+ RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
+ RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
+
+ static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
+ static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
+ static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
+
+ const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
+
+ const auto col = CColor(*PSHADOWCOL);
+
+ 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
+
+ float glMatrix[9];
+ wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
+ wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
+
+ wlr_matrix_transpose(glMatrix, glMatrix);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glUseProgram(m_shSHADOW.program);
+
+ glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
+ glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
+
+ const auto TOPLEFT = Vector2D(range + round, range + round);
+ const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
+ const auto FULLSIZE = Vector2D(box->width, box->height);
+
+ // Rounded corners
+ glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
+ glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
+ glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
+ glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
+
+ glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+ glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+
+ glEnableVertexAttribArray(m_shSHADOW.posAttrib);
+ glEnableVertexAttribArray(m_shSHADOW.texAttrib);
+
+ if (pixman_region32_not_empty(m_RenderData.pDamage)) {
+ PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
+ const auto RECT = RECTSARR[i];
+ scissor(&RECT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+ }
+
+ glDisableVertexAttribArray(m_shSHADOW.posAttrib);
+ glDisableVertexAttribArray(m_shSHADOW.texAttrib);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+}
+
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 0648e73a..5cae6486 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -61,6 +61,7 @@ public:
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
+ void renderRoundedShadow(wlr_box*, int round, int range);
void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*);
@@ -106,6 +107,7 @@ private:
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
+ CShader m_shSHADOW;
//
GLuint createProgram(const std::string&, const std::string&);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index a917a1cc..5d99565b 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -569,7 +569,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
// damage by size & pos
// TODO TEMP: revise when added shadows/etc
- wlr_box damageBox = {pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y};
+ wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
@@ -584,8 +584,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} else {
// damage by real size & pos + border size * 2 (JIC)
- static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
- wlr_box damageBox = { pWindow->m_vRealPosition.vec().x - *PBORDERSIZE - 1, pWindow->m_vRealPosition.vec().y - *PBORDERSIZE - 1, pWindow->m_vRealSize.vec().x + 2 * *PBORDERSIZE + 2, pWindow->m_vRealSize.vec().y + 2 * *PBORDERSIZE + 2};
+ wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
diff --git a/src/render/Shaders.hpp b/src/render/Shaders.hpp
index d01e7775..ac7f9424 100644
--- a/src/render/Shaders.hpp
+++ b/src/render/Shaders.hpp
@@ -1,341 +1,4 @@
#pragma once
-#include <string>
-
-inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
- return R"#(
- if (pixCoord[0] < topLeft[0]) {
- // we're close left
- if (pixCoord[1] < topLeft[1]) {
- // top
-
- if (ignoreCorners == 1) {
- discard;
- return;
- }
-
- float topLeftDistance = distance(topLeft, pixCoord);
-
- if (topLeftDistance > radius - 1.0) {
- if (primitiveMultisample == 0 && topLeftDistance > radius) {
- discard;
- return;
- } else if (primitiveMultisample == 1) {
- float distances = 0.0;
- if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
- if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
-
- if (distances == 0.0) {
- discard;
- return;
- }
-
- distances = distances / 4.0;
-
- gl_FragColor = )#" + colorVarName + R"#( * distances;
- return;
- }
- }
- } else if (pixCoord[1] > bottomRight[1]) {
- // bottom
-
- if (ignoreCorners == 1) {
- discard;
- return;
- }
-
- float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
-
- if (topLeftDistance > radius - 1.0) {
- if (primitiveMultisample == 0 && topLeftDistance > radius) {
- discard;
- return;
- } else if (primitiveMultisample == 1) {
- float distances = 0.0;
- if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
-
- if (distances == 0.0) {
- discard;
- return;
- }
-
- distances = distances / 4.0;
-
- gl_FragColor = )#" + colorVarName + R"#( * distances;
- return;
- }
- }
- }
- }
- else if (pixCoord[0] > bottomRight[0]) {
- // we're close right
- if (pixCoord[1] < topLeft[1]) {
- // top
-
- if (ignoreCorners == 1) {
- discard;
- return;
- }
-
- float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
-
- if (topLeftDistance > radius - 1.0) {
- if (primitiveMultisample == 0 && topLeftDistance > radius) {
- discard;
- return;
- } else if (primitiveMultisample == 1) {
- float distances = 0.0;
- if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
- if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
-
- if (distances == 0.0) {
- discard;
- return;
- }
-
- distances = distances / 4.0;
-
- gl_FragColor = )#" + colorVarName + R"#( * distances;
- return;
- }
- }
- } else if (pixCoord[1] > bottomRight[1]) {
- // bottom
-
- if (ignoreCorners == 1) {
- discard;
- return;
- }
-
- float topLeftDistance = distance(bottomRight, pixCoord);
-
- if (topLeftDistance > radius - 1.0) {
- if (primitiveMultisample == 0 && topLeftDistance > radius) {
- discard;
- return;
- } else if (primitiveMultisample == 1) {
- float distances = 0.0;
- if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
- if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
- if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
-
- if (distances == 0.0) {
- discard;
- return;
- }
-
- distances = distances / 4.0;
-
- gl_FragColor = )#" + colorVarName + R"#( * distances;
- return;
- }
- }
- }
- }
- )#";
-};
-
-inline const std::string QUADVERTSRC = R"#(
-uniform mat3 proj;
-uniform vec4 color;
-attribute vec2 pos;
-attribute vec2 texcoord;
-varying vec4 v_color;
-varying vec2 v_texcoord;
-
-void main() {
- gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
- v_color = color;
- v_texcoord = texcoord;
-})#";
-
-inline const std::string QUADFRAGSRC = R"#(
-precision mediump float;
-varying vec4 v_color;
-varying vec2 v_texcoord;
-
-uniform vec2 topLeft;
-uniform vec2 bottomRight;
-uniform vec2 fullSize;
-uniform float radius;
-
-uniform int primitiveMultisample;
-uniform int ignoreCorners;
-
-void main() {
- if (radius == 0.0) {
- gl_FragColor = v_color;
- return;
- }
-
- vec2 pixCoord = fullSize * v_texcoord;
-
- )#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
-
- gl_FragColor = v_color;
-})#";
-
-inline const std::string TEXVERTSRC = R"#(
-uniform mat3 proj;
-attribute vec2 pos;
-attribute vec2 texcoord;
-varying vec2 v_texcoord;
-
-void main() {
- gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
- v_texcoord = texcoord;
-})#";
-
-inline const std::string TEXFRAGSRCRGBA = R"#(
-precision mediump float;
-varying vec2 v_texcoord; // is in 0-1
-uniform sampler2D tex;
-uniform float alpha;
-
-uniform vec2 topLeft;
-uniform vec2 bottomRight;
-uniform vec2 fullSize;
-uniform float radius;
-
-uniform int discardOpaque;
-
-uniform int primitiveMultisample;
-uniform int ignoreCorners;
-
-void main() {
-
- vec4 pixColor = texture2D(tex, v_texcoord);
-
- if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
- discard;
- return;
- }
-
- vec2 pixCoord = fullSize * v_texcoord;
-
- )#" + ROUNDED_SHADER_FUNC("pixColor") +
- R"#(
-
- gl_FragColor = pixColor * alpha;
-})#";
-
-inline const std::string TEXFRAGSRCRGBX = R"#(
-precision mediump float;
-varying vec2 v_texcoord;
-uniform sampler2D tex;
-uniform float alpha;
-
-uniform vec2 topLeft;
-uniform vec2 bottomRight;
-uniform vec2 fullSize;
-uniform float radius;
-
-uniform int discardOpaque;
-
-uniform int primitiveMultisample;
-uniform int ignoreCorners;
-
-void main() {
-
- if (discardOpaque == 1 && alpha == 1.0) {
- discard;
- return;
- }
-
- vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
-
- vec2 pixCoord = fullSize * v_texcoord;
-
- )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
-
- gl_FragColor = pixColor * alpha;
-})#";
-
-inline const std::string FRAGBLUR1 = R"#(
-#version 100
-precision mediump float;
-varying mediump vec2 v_texcoord; // is in 0-1
-uniform sampler2D tex;
-
-uniform float radius;
-uniform vec2 halfpixel;
-
-void main() {
- vec2 uv = v_texcoord * 2.0;
-
- vec4 sum = texture2D(tex, uv) * 4.0;
- sum += texture2D(tex, uv - halfpixel.xy * radius);
- sum += texture2D(tex, uv + halfpixel.xy * radius);
- sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
- sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
- gl_FragColor = sum / 8.0;
-}
-)#";
-
-inline const std::string FRAGBLUR2 = R"#(
-#version 100
-precision mediump float;
-varying mediump vec2 v_texcoord; // is in 0-1
-uniform sampler2D tex;
-
-uniform float radius;
-uniform vec2 halfpixel;
-
-void main() {
- vec2 uv = v_texcoord / 2.0;
-
- vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
-
- sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
- sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
- sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
- sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
- sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
- sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
- sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
-
- gl_FragColor = sum / 12.0;
-}
-)#";
-
-inline const std::string TEXFRAGSRCEXT = R"#(
-#extension GL_OES_EGL_image_external : require
-
-precision mediump float;
-varying vec2 v_texcoord;
-uniform samplerExternalOES texture0;
-uniform float alpha;
-
-uniform vec2 topLeft;
-uniform vec2 bottomRight;
-uniform vec2 fullSize;
-uniform float radius;
-
-uniform int discardOpaque;
-
-uniform int primitiveMultisample;
-uniform int ignoreCorners;
-
-void main() {
-
- vec4 pixColor = texture2D(texture0, v_texcoord);
-
- if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
- discard;
- return;
- }
-
- vec2 pixCoord = fullSize * v_texcoord;
-
- )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
-
- gl_FragColor = pixColor * alpha;
-})#";
+#include "shaders/Textures.hpp"
+#include "shaders/Shadow.hpp" \ No newline at end of file
diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp
new file mode 100644
index 00000000..528e00cf
--- /dev/null
+++ b/src/render/decorations/CHyprDropShadowDecoration.cpp
@@ -0,0 +1,66 @@
+#include "CHyprDropShadowDecoration.hpp"
+
+#include "../../Compositor.hpp"
+
+CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) {
+ m_pWindow = pWindow;
+}
+
+CHyprDropShadowDecoration::~CHyprDropShadowDecoration() {
+ updateWindow(m_pWindow);
+}
+
+SWindowDecorationExtents CHyprDropShadowDecoration::getWindowDecorationExtents() {
+ static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
+
+ if (*PSHADOWS != 1)
+ return {{}, {}};
+
+ return m_seExtents;
+}
+
+eDecorationType CHyprDropShadowDecoration::getDecorationType() {
+ return DECORATION_SHADOW;
+}
+
+void CHyprDropShadowDecoration::damageEntire() {
+ static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
+
+ if (*PSHADOWS != 1)
+ return; // disabled
+
+ wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
+ g_pHyprRenderer->damageBox(&dm);
+}
+
+void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
+ damageEntire();
+}
+
+void CHyprDropShadowDecoration::draw(SMonitor* pMonitor) {
+
+ if (!g_pCompositor->windowValidMapped(m_pWindow))
+ return;
+
+ static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
+ static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
+ static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
+
+ if (*PSHADOWS != 1)
+ return; // disabled
+
+ // update the extents if needed
+ if (*PSHADOWSIZE != m_seExtents.topLeft.x)
+ m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}};
+
+ m_vLastWindowPos = m_pWindow->m_vRealPosition.vec();
+ m_vLastWindowSize = m_pWindow->m_vRealSize.vec();
+
+ // draw the shadow
+ wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
+
+ fullBox.x -= pMonitor->vecPosition.x;
+ fullBox.y -= pMonitor->vecPosition.y;
+
+ g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE);
+}
diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp
new file mode 100644
index 00000000..2a248a2f
--- /dev/null
+++ b/src/render/decorations/CHyprDropShadowDecoration.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "IHyprWindowDecoration.hpp"
+
+class CHyprDropShadowDecoration : public IHyprWindowDecoration {
+public:
+ CHyprDropShadowDecoration(CWindow*);
+ virtual ~CHyprDropShadowDecoration();
+
+ virtual SWindowDecorationExtents getWindowDecorationExtents();
+
+ virtual void draw(SMonitor*);
+
+ virtual eDecorationType getDecorationType();
+
+ virtual void updateWindow(CWindow*);
+
+ virtual void damageEntire();
+
+private:
+ SWindowDecorationExtents m_seExtents;
+
+ CWindow* m_pWindow = nullptr;
+
+ Vector2D m_vLastWindowPos;
+ Vector2D m_vLastWindowSize;
+}; \ No newline at end of file
diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp
index 0815273d..e9011a29 100644
--- a/src/render/decorations/IHyprWindowDecoration.hpp
+++ b/src/render/decorations/IHyprWindowDecoration.hpp
@@ -4,7 +4,8 @@
enum eDecorationType {
DECORATION_NONE = -1,
- DECORATION_GROUPBAR
+ DECORATION_GROUPBAR,
+ DECORATION_SHADOW
};
struct SWindowDecorationExtents {
diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp
new file mode 100644
index 00000000..f54124fa
--- /dev/null
+++ b/src/render/shaders/Shadow.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <string>
+
+inline const std::string FRAGSHADOW = R"#(
+precision mediump float;
+varying vec4 v_color;
+varying vec2 v_texcoord;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+uniform float range;
+uniform float shadowPower;
+uniform int ignoreWindow;
+
+float pixAlphaRoundedDistance(float distanceToCorner) {
+ if (distanceToCorner > radius) {
+ return 0.0;
+ }
+
+ if (distanceToCorner > radius - range) {
+ return pow((range - (distanceToCorner - radius + range)) / range, shadowPower); // i think?
+ }
+
+ return 1.0;
+}
+
+void main() {
+
+ vec4 pixColor = v_color;
+ float originalAlpha = pixColor[3];
+
+ bool done = false;
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ // ok, now we check the distance to a border.
+
+ if (pixCoord[0] < topLeft[0]) {
+ if (pixCoord[1] < topLeft[1]) {
+ // top left
+ pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft));
+ done = true;
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom left
+ pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1])));
+ done = true;
+ }
+ } else if (pixCoord[0] > bottomRight[0]) {
+ if (pixCoord[1] < topLeft[1]) {
+ // top right
+ pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1])));
+ done = true;
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom right
+ pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight));
+ done = true;
+ }
+ }
+
+ if (!done) {
+ // distance to all straight bb borders
+ float distanceT = pixCoord[1];
+ float distanceB = fullSize[1] - pixCoord[1];
+ float distanceL = pixCoord[0];
+ float distanceR = fullSize[0] - pixCoord[0];
+
+ // get the smallest
+ float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
+
+ if (smallest < range) {
+ pixColor[3] = pixColor[3] * pow((smallest / range), shadowPower);
+ }
+ }
+
+ if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) {
+ discard; return;
+ }
+
+ gl_FragColor = pixColor;
+})#"; \ No newline at end of file
diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp
new file mode 100644
index 00000000..d01e7775
--- /dev/null
+++ b/src/render/shaders/Textures.hpp
@@ -0,0 +1,341 @@
+#pragma once
+
+#include <string>
+
+inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
+ return R"#(
+ if (pixCoord[0] < topLeft[0]) {
+ // we're close left
+ if (pixCoord[1] < topLeft[1]) {
+ // top
+
+ if (ignoreCorners == 1) {
+ discard;
+ return;
+ }
+
+ float topLeftDistance = distance(topLeft, pixCoord);
+
+ if (topLeftDistance > radius - 1.0) {
+ if (primitiveMultisample == 0 && topLeftDistance > radius) {
+ discard;
+ return;
+ } else if (primitiveMultisample == 1) {
+ float distances = 0.0;
+ if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
+ if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
+
+ if (distances == 0.0) {
+ discard;
+ return;
+ }
+
+ distances = distances / 4.0;
+
+ gl_FragColor = )#" + colorVarName + R"#( * distances;
+ return;
+ }
+ }
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom
+
+ if (ignoreCorners == 1) {
+ discard;
+ return;
+ }
+
+ float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
+
+ if (topLeftDistance > radius - 1.0) {
+ if (primitiveMultisample == 0 && topLeftDistance > radius) {
+ discard;
+ return;
+ } else if (primitiveMultisample == 1) {
+ float distances = 0.0;
+ if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
+
+ if (distances == 0.0) {
+ discard;
+ return;
+ }
+
+ distances = distances / 4.0;
+
+ gl_FragColor = )#" + colorVarName + R"#( * distances;
+ return;
+ }
+ }
+ }
+ }
+ else if (pixCoord[0] > bottomRight[0]) {
+ // we're close right
+ if (pixCoord[1] < topLeft[1]) {
+ // top
+
+ if (ignoreCorners == 1) {
+ discard;
+ return;
+ }
+
+ float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
+
+ if (topLeftDistance > radius - 1.0) {
+ if (primitiveMultisample == 0 && topLeftDistance > radius) {
+ discard;
+ return;
+ } else if (primitiveMultisample == 1) {
+ float distances = 0.0;
+ if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
+ if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
+
+ if (distances == 0.0) {
+ discard;
+ return;
+ }
+
+ distances = distances / 4.0;
+
+ gl_FragColor = )#" + colorVarName + R"#( * distances;
+ return;
+ }
+ }
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom
+
+ if (ignoreCorners == 1) {
+ discard;
+ return;
+ }
+
+ float topLeftDistance = distance(bottomRight, pixCoord);
+
+ if (topLeftDistance > radius - 1.0) {
+ if (primitiveMultisample == 0 && topLeftDistance > radius) {
+ discard;
+ return;
+ } else if (primitiveMultisample == 1) {
+ float distances = 0.0;
+ if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
+ if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
+ if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
+
+ if (distances == 0.0) {
+ discard;
+ return;
+ }
+
+ distances = distances / 4.0;
+
+ gl_FragColor = )#" + colorVarName + R"#( * distances;
+ return;
+ }
+ }
+ }
+ }
+ )#";
+};
+
+inline const std::string QUADVERTSRC = R"#(
+uniform mat3 proj;
+uniform vec4 color;
+attribute vec2 pos;
+attribute vec2 texcoord;
+varying vec4 v_color;
+varying vec2 v_texcoord;
+
+void main() {
+ gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
+ v_color = color;
+ v_texcoord = texcoord;
+})#";
+
+inline const std::string QUADFRAGSRC = R"#(
+precision mediump float;
+varying vec4 v_color;
+varying vec2 v_texcoord;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+
+uniform int primitiveMultisample;
+uniform int ignoreCorners;
+
+void main() {
+ if (radius == 0.0) {
+ gl_FragColor = v_color;
+ return;
+ }
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ )#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
+
+ gl_FragColor = v_color;
+})#";
+
+inline const std::string TEXVERTSRC = R"#(
+uniform mat3 proj;
+attribute vec2 pos;
+attribute vec2 texcoord;
+varying vec2 v_texcoord;
+
+void main() {
+ gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
+ v_texcoord = texcoord;
+})#";
+
+inline const std::string TEXFRAGSRCRGBA = R"#(
+precision mediump float;
+varying vec2 v_texcoord; // is in 0-1
+uniform sampler2D tex;
+uniform float alpha;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+
+uniform int discardOpaque;
+
+uniform int primitiveMultisample;
+uniform int ignoreCorners;
+
+void main() {
+
+ vec4 pixColor = texture2D(tex, v_texcoord);
+
+ if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
+ discard;
+ return;
+ }
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ )#" + ROUNDED_SHADER_FUNC("pixColor") +
+ R"#(
+
+ gl_FragColor = pixColor * alpha;
+})#";
+
+inline const std::string TEXFRAGSRCRGBX = R"#(
+precision mediump float;
+varying vec2 v_texcoord;
+uniform sampler2D tex;
+uniform float alpha;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+
+uniform int discardOpaque;
+
+uniform int primitiveMultisample;
+uniform int ignoreCorners;
+
+void main() {
+
+ if (discardOpaque == 1 && alpha == 1.0) {
+ discard;
+ return;
+ }
+
+ vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
+
+ gl_FragColor = pixColor * alpha;
+})#";
+
+inline const std::string FRAGBLUR1 = R"#(
+#version 100
+precision mediump float;
+varying mediump vec2 v_texcoord; // is in 0-1
+uniform sampler2D tex;
+
+uniform float radius;
+uniform vec2 halfpixel;
+
+void main() {
+ vec2 uv = v_texcoord * 2.0;
+
+ vec4 sum = texture2D(tex, uv) * 4.0;
+ sum += texture2D(tex, uv - halfpixel.xy * radius);
+ sum += texture2D(tex, uv + halfpixel.xy * radius);
+ sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
+ sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
+ gl_FragColor = sum / 8.0;
+}
+)#";
+
+inline const std::string FRAGBLUR2 = R"#(
+#version 100
+precision mediump float;
+varying mediump vec2 v_texcoord; // is in 0-1
+uniform sampler2D tex;
+
+uniform float radius;
+uniform vec2 halfpixel;
+
+void main() {
+ vec2 uv = v_texcoord / 2.0;
+
+ vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
+
+ sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
+ sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
+ sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
+ sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
+ sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
+ sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
+ sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
+
+ gl_FragColor = sum / 12.0;
+}
+)#";
+
+inline const std::string TEXFRAGSRCEXT = R"#(
+#extension GL_OES_EGL_image_external : require
+
+precision mediump float;
+varying vec2 v_texcoord;
+uniform samplerExternalOES texture0;
+uniform float alpha;
+
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+
+uniform int discardOpaque;
+
+uniform int primitiveMultisample;
+uniform int ignoreCorners;
+
+void main() {
+
+ vec4 pixColor = texture2D(texture0, v_texcoord);
+
+ if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
+ discard;
+ return;
+ }
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
+
+ gl_FragColor = pixColor * alpha;
+})#";