aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorvaxerski <[email protected]>2022-05-17 13:16:37 +0200
committervaxerski <[email protected]>2022-05-17 13:16:37 +0200
commitcad71218c0ca67b43a1085d11077daa7398f38d5 (patch)
treee9e4bbc17a3141bb7410329c75068f4e5baa5a6a
parent48b8ab3f6538df29c4e0f50a5fbb7808fd4c475b (diff)
downloadHyprland-cad71218c0ca67b43a1085d11077daa7398f38d5.tar.gz
Hyprland-cad71218c0ca67b43a1085d11077daa7398f38d5.zip
borders are now gangsta
-rw-r--r--src/config/ConfigManager.cpp2
-rw-r--r--src/helpers/WLClasses.hpp3
-rw-r--r--src/render/OpenGL.cpp165
-rw-r--r--src/render/OpenGL.hpp14
-rw-r--r--src/render/Renderer.cpp35
-rw-r--r--src/render/Renderer.hpp1
-rw-r--r--src/render/Shader.hpp1
-rw-r--r--src/render/Shaders.hpp47
8 files changed, 129 insertions, 139 deletions
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 34cb896f..80f2b0d4 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -701,7 +701,7 @@ void CConfigManager::tick() {
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
if (!std::filesystem::exists(CONFIGPATH)) {
- loadConfigLoadVars();
+ Debug::log(ERR, "Config doesn't exist??");
return;
}
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 9d1cd6df..9fd23830 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -54,6 +54,9 @@ struct SRenderData {
// for alpha settings
float alpha = 1.f;
+
+ // for decorations (border)
+ bool decorate = false;
};
struct SKeyboard {
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index f82721b6..85cd12e9 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -30,6 +30,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_shQUAD.proj = glGetUniformLocation(prog, "proj");
m_shQUAD.color = glGetUniformLocation(prog, "color");
m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
+ m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_shRGBA.program = prog;
@@ -222,12 +223,10 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
scissor(&box);
}
-void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col) {
+void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
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()!");
- // TODO: respect damage
-
float matrix[9];
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
@@ -237,23 +236,42 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col) {
wlr_matrix_transpose(glMatrix, glMatrix);
- if (col.a == 255.f)
- glDisable(GL_BLEND);
- else
- glEnable(GL_BLEND);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shQUAD.program);
glUniformMatrix3fv(m_shQUAD.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
+ const auto TOPLEFT = Vector2D(round, round);
+ const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
+ const auto FULLSIZE = Vector2D(box->width, box->height);
+
+ // Rounded corners
+ glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
+ glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
+ glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
+ glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
+
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+ glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shQUAD.posAttrib);
+ glEnableVertexAttribArray(m_shQUAD.texAttrib);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ 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_shQUAD.posAttrib);
+ glDisableVertexAttribArray(m_shQUAD.texAttrib);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round) {
@@ -262,15 +280,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
renderTexture(CTexture(tex), pBox, alpha, round);
}
-void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque) {
+void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque);
+ renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border);
scissor((wlr_box*)nullptr);
}
-void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque) {
+void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@@ -468,11 +486,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
return currentRenderToFB;
}
-void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round) {
+void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
if (g_pConfigManager->getInt("decoration:blur") == 0) {
- renderTexture(tex, pBox, a, round);
+ renderTexture(tex, pBox, a, round, false, border);
return;
}
@@ -528,16 +546,31 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// render our great blurred FB
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, 255.f, &damage); // 255.f because we adjusted blur strength to a
- // render the window, but disable stencil for it
- // because stencil has ignoreopaque
- glDisable(GL_STENCIL_TEST);
+ // render the window, but clear stencil
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ // and write to it
+ glStencilFunc(GL_ALWAYS, 1, -1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round);
+
+ // then stop
+ glStencilFunc(GL_EQUAL, 1, -1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
- // disable the stencil, finalize everything
- glStencilMask(-1);
- glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ // disable the stencil (if no border), finalize everything
+ if (!border) {
+ glStencilMask(-1);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ } else {
+ auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
+ BORDERCOL.a *= a / 255.f;
+ renderBorder(pBox, BORDERCOL, g_pConfigManager->getInt("general:border_size"), round);
+ }
+
glDisable(GL_STENCIL_TEST);
pixman_region32_fini(&damage);
scissor((wlr_box*)nullptr);
@@ -550,95 +583,21 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
counter++;
}
-void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int radius) {
+void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int round) {
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()!");
- scaleBox(box, m_RenderData.pMonitor->scale);
-
- float matrix[9];
- wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 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);
-
- glUseProgram(m_shQUAD.program);
-
- glUniformMatrix3fv(m_shQUAD.proj, 1, GL_FALSE, glMatrix);
- glUniform4f(m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
-
- // Sides are ONLY for corners meaning they have to be divisible by 4.
- // 32 sides shouldn't be taxing at all on the performance.
- const int SIDES = 32; // sides
- const int SIDES34 = 24; // 3/4th of the sides
- float verts[(SIDES + 8 + 1) * 4]; // 8 for the connections and 1 because last is doubled (begin/end)
- int vertNo = 0;
-
- // start from 0,0 tex coord space
- float x = 0, y = 0, w = box->width, h = box->height;
-
- pushVert2D(x + radius, y + h, verts, vertNo, box);
- pushVert2D(x + w - radius, y + h, verts, vertNo, box);
-
- float x1 = x + w - radius;
- float y1 = y + h - radius;
-
- for (int i = 0; i <= SIDES / 4; i++) {
- pushVert2D(x1 + (sin((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), y1 + (cos((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), verts, vertNo, box);
- }
-
- // Right Line
- pushVert2D(x + w, y + radius, verts, vertNo, box);
-
- x1 = x + w - radius;
- y1 = y + radius;
-
- for (int i = SIDES / 4; i <= SIDES / 2; i++) {
- pushVert2D(x1 + (sin((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), y1 + (cos((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), verts, vertNo, box);
- }
-
- // Top Line
- pushVert2D(x + radius, y, verts, vertNo, box);
-
- x1 = x + radius;
- y1 = y + radius;
-
- for (int i = SIDES / 2; i <= SIDES34; i++) {
- pushVert2D(x1 + (sin((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), y1 + (cos((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), verts, vertNo, box);
- }
+ // this method assumes a set stencil and scaled box
+ box->x -= thick;
+ box->y -= thick;
+ box->width += 2 * thick;
+ box->height += 2 * thick;
- // Left Line
- pushVert2D(x, y + h - radius, verts, vertNo, box);
+ // only draw on non-stencild.
+ glStencilFunc(GL_NOTEQUAL, 1, -1);
- x1 = x + radius;
- y1 = y + h - radius;
-
- for (int i = SIDES34; i <= SIDES; i++) {
- pushVert2D(x1 + (sin((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), y1 + (cos((i * (360.f / (float)SIDES) * 3.141526f / 180)) * radius), verts, vertNo, box);
- }
-
- glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
-
- glEnableVertexAttribArray(m_shQUAD.posAttrib);
-
- glLineWidth(thick);
-
- // draw with damage
- if (pixman_region32_not_empty(m_RenderData.pDamage)) {
- PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
- const auto RECT = RECTSARR[i];
- scissor(&RECT);
-
- glDrawArrays(GL_LINE_STRIP, 0, 41);
- }
- }
-
- glDisableVertexAttribArray(m_shQUAD.posAttrib);
+ // draw a rounded rect
+ renderRect(box, col, round);
}
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 34b1a871..4209d9ac 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -53,11 +53,10 @@ public:
void begin(SMonitor*, pixman_region32_t*);
void end();
- void renderRect(wlr_box*, const CColor&);
+ void renderRect(wlr_box*, const CColor&, int round = 0);
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);
- void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
- void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
+ void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false);
+ void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*);
@@ -77,6 +76,8 @@ public:
GLint m_iCurrentOutputFb = 0;
GLint m_iWLROutputFb = 0;
+ CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
+
pixman_region32_t m_rOriginalDamageRegion; // used for storing the pre-expanded region
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
@@ -107,9 +108,8 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
- void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false);
- void renderTextureWithBlurInternal(const CTexture&, wlr_box*, float a, int round = 0);
-
+ void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false);
+ void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL; \ No newline at end of file
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index fef08429..91c882ca 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -20,9 +20,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
scaleBox(&windowBox, RDATA->output->scale);
if (RDATA->surface && surface == RDATA->surface)
- g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
+ g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), RDATA->decorate);
else
- g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
+ g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), false, RDATA->decorate);
wlr_surface_send_frame_done(surface, RDATA->when);
@@ -97,17 +97,15 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.h = pWindow->m_vRealSize.vec().y;
renderdata.dontRound = pWindow->m_bIsFullscreen;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
- renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") :
- pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
+ renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
+ renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders;
// apply window special data
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
- wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
+ g_pHyprOpenGL->m_pCurrentWindow = pWindow;
- // border
- if (decorate && !pWindow->m_bX11DoesntWantBorders)
- drawBorderForWindow(pWindow, pMonitor, renderdata.alpha * renderdata.fadeAlpha, PWORKSPACE->m_vRenderOffset.vec());
+ wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
if (pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->surface) {
@@ -118,7 +116,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.dontRound = false; // restore dontround
renderdata.pMonitor = pMonitor;
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
- }
+ }
+
+ g_pHyprOpenGL->m_pCurrentWindow = nullptr;
}
void CHyprRenderer::renderLayer(SLayerSurface* pLayer, SMonitor* pMonitor, timespec* time) {
@@ -438,23 +438,6 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
Debug::log(LOG, "Monitor %s layers arranged: reserved: %f %f %f %f", PMONITOR->szName.c_str(), PMONITOR->vecReservedTopLeft.x, PMONITOR->vecReservedTopLeft.y, PMONITOR->vecReservedBottomRight.x, PMONITOR->vecReservedBottomRight.y);
}
-void CHyprRenderer::drawBorderForWindow(CWindow* pWindow, SMonitor* pMonitor, float alpha, const Vector2D& offset) {
- const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
-
- if (BORDERSIZE < 1)
- return;
-
- auto BORDERCOL = pWindow->m_cRealBorderColor.col();
- BORDERCOL.a *= (alpha / 255.f);
-
- Vector2D correctPos = pWindow->m_vRealPosition.vec() - pMonitor->vecPosition;
- Vector2D correctSize = pWindow->m_vRealSize.vec();
-
- // top
- wlr_box border = {correctPos.x - BORDERSIZE / 2.f + offset.x, correctPos.y - BORDERSIZE / 2.f + offset.y, pWindow->m_vRealSize.vec().x + BORDERSIZE, pWindow->m_vRealSize.vec().y + BORDERSIZE};
- g_pHyprOpenGL->renderBorder(&border, BORDERCOL, BORDERSIZE, g_pConfigManager->getInt("decoration:rounding"));
-}
-
void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
if (!pSurface)
return; // wut?
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index f879702b..ba7d54b3 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -34,7 +34,6 @@ public:
private:
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
- void drawBorderForWindow(CWindow*, SMonitor*, float a = 255.f, const Vector2D& offset = Vector2D(0,0));
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp
index 49272857..4d94358e 100644
--- a/src/render/Shader.hpp
+++ b/src/render/Shader.hpp
@@ -7,6 +7,7 @@ struct SQuad {
GLint proj;
GLint color;
GLint posAttrib;
+ GLint texAttrib;
};
class CShader {
diff --git a/src/render/Shaders.hpp b/src/render/Shaders.hpp
index 3864d801..11d40913 100644
--- a/src/render/Shaders.hpp
+++ b/src/render/Shaders.hpp
@@ -21,8 +21,53 @@ precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
+uniform vec2 topLeft;
+uniform vec2 bottomRight;
+uniform vec2 fullSize;
+uniform float radius;
+
void main() {
- gl_FragColor = v_color;
+ if (radius == 0.0) {
+ gl_FragColor = v_color;
+ return;
+ }
+
+ vec2 pixCoord = fullSize * v_texcoord;
+
+ if (pixCoord[0] < topLeft[0]) {
+ // we're close left
+ if (pixCoord[1] < topLeft[1]) {
+ // top
+ if (distance(topLeft, pixCoord) > radius) {
+ discard;
+ return;
+ }
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom
+ if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
+ discard;
+ return;
+ }
+ }
+ }
+ else if (pixCoord[0] > bottomRight[0]) {
+ // we're close right
+ if (pixCoord[1] < topLeft[1]) {
+ // top
+ if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
+ discard;
+ return;
+ }
+ } else if (pixCoord[1] > bottomRight[1]) {
+ // bottom
+ if (distance(bottomRight, pixCoord) > radius) {
+ discard;
+ return;
+ }
+ }
+ }
+
+ gl_FragColor = v_color;
})#";
inline const std::string TEXVERTSRC = R"#(