Skip to content

Commit ca97ebb

Browse files
committed
drop shadow, improve font rendering when scale is used
1 parent 89304bd commit ca97ebb

File tree

1 file changed

+51
-31
lines changed
  • modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal

1 file changed

+51
-31
lines changed

modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import java.nio.FloatBuffer
2929
import kotlin.math.cos
3030
import kotlin.math.roundToInt
3131
import kotlin.math.sin
32+
import kotlin.math.sqrt
3233
import kotlin.math.tan
3334

3435
private val LOGGER = LogManager.getLogger("PolyUI/GLRenderer")
@@ -101,18 +102,17 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
101102
private var count = 0
102103
private var curTex = 0
103104
private var transformDepth = 0
104-
private var curScissor = 0
105+
private var scissorDepth = 0
105106
private var transform = IDENTITY.copyOf()
106107
private var viewportWidth = 0f
107108
private var viewportHeight = 0f
108109
private var pixelRatio = 1f
109110
private var alphaCap = 1f
110111
private var popFlushNeeded = false
111112

113+
// atlas data
112114
private var slotX = 0
113115
private var slotY = 0
114-
115-
/** current max height of the currently active row in the atlas. */
116116
private var atlasRowHeight = 0
117117

118118
private val FRAG = """
@@ -149,24 +149,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
149149
float rRight = mix(r.z, r.y, py); // bottom-right / top-right
150150
float radius = mix(rLeft, rRight, px);
151151
152-
vec2 q = abs(p) - (b - vec2(radius));
152+
vec2 q = abs(p) - (b - radius);
153153
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
154154
}
155155
156156
float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) {
157-
float outer = roundedBoxSDF(p, b + vec2(0.2), r);
158-
float inner = roundedBoxSDF(p, b - vec2(thickness), max(r - vec4(thickness), 0.0));
157+
float outer = roundedBoxSDF(p, b + 0.2, r + 0.2);
158+
float inner = roundedBoxSDF(p, b - thickness, max(r - thickness, 0.0));
159159
return max(outer, -inner);
160160
}
161161
162162
float roundBoxSDF(vec2 p, vec2 halfSize, float radius) {
163-
vec2 q = abs(p) - (halfSize - vec2(radius));
163+
vec2 q = abs(p) - (halfSize - radius);
164164
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
165165
}
166166
167167
void main() {
168-
vec2 center = vRect.xy + 0.5 * vRect.zw;
169168
vec2 halfSize = 0.5 * vRect.zw;
169+
vec2 center = vRect.xy + halfSize;
170170
vec2 p = vPos - center;
171171
172172
float d = (vThickness > 0.0) ? hollowRoundedBoxSDF(p, halfSize, vRadii, vThickness) : roundedBoxSDF(p, halfSize, vRadii);
@@ -193,6 +193,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
193193
float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0);
194194
col = mix(vColor0, vColor1, t);
195195
}
196+
else if (vThickness == -5.0) { // drop shadow, vUV.x as spread and vUV.y as blur
197+
float dShadow = roundBoxSDF(p, halfSize + vUV.x, vRadii.x);
198+
col = vec4(vColor0.rgb, vColor0.a * (1.0 - smoothstep(-vUV.y, vUV.y, dShadow)));
199+
}
196200
197201
// Proper antialiasing based on distance field
198202
float f = fwidth(d);
@@ -404,11 +408,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
404408
}
405409

406410
override fun beginFrame(width: Float, height: Float, pixelRatio: Float) {
407-
curScissor = 0
411+
scissorDepth = 0
408412
alphaCap = 1f
409413
count = 0
410414
buffer.clear()
411415
transform.set(IDENTITY)
416+
popFlushNeeded = false
412417
transformDepth = 0
413418
val prevProg = glGetInteger(GL_CURRENT_PROGRAM)
414419
glUseProgram(program)
@@ -608,6 +613,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
608613

609614
override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) {
610615
val fAtlas = getFontAtlas(font, fontSize)
616+
val s = transformScale()
617+
val fAtlasForRendering = if (s == 1f) fAtlas else getFontAtlas(font, fontSize * s)
611618
if (count >= MAX_BATCH) flush()
612619
if (count > 0 && curTex != atlas) flush()
613620
curTex = atlas
@@ -631,7 +638,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
631638
buffer.put(EMPTY_ROW) // zero radii
632639
buffer.put(r).put(g).put(b).put(a)
633640
buffer.put(EMPTY_ROW) // color1 unused
634-
buffer.put(glyph, 0, 4)
641+
buffer.put(if (s == 1f) glyph else fAtlasForRendering.get(c), 0, 4)
635642
buffer.put(-1f) // thickness = -1 for text
636643
penX += glyph.xAdvance * scaleFactor
637644
count += 1
@@ -656,7 +663,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
656663
spread: Float,
657664
radius: Float
658665
) {
659-
// rect(x, y, width, height, )
666+
if (count >= MAX_BATCH) flush()
667+
buffer.put(x).put(y).put(width).put(height)
668+
buffer.put(EMPTY_ROW) // zero radii
669+
buffer.put(0f).put(0f).put(0f).put(alphaCap) // black, alpha to alphaCap
670+
buffer.put(EMPTY_ROW) // color1 unused
671+
buffer.put(spread).put(blur).put(0f).put(0f)
672+
buffer.put(-5f) // thickness = -5 for drop shadow
673+
count += 1
660674
}
661675

662676
override fun pushScissor(x: Float, y: Float, width: Float, height: Float) {
@@ -665,24 +679,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
665679
val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt()
666680
val nw = (width * pixelRatio).roundToInt()
667681
val nh = (height * pixelRatio).roundToInt()
668-
scissorStack[curScissor++] = nx
669-
scissorStack[curScissor++] = ny
670-
scissorStack[curScissor++] = nw
671-
scissorStack[curScissor++] = nh
682+
scissorStack[scissorDepth++] = nx
683+
scissorStack[scissorDepth++] = ny
684+
scissorStack[scissorDepth++] = nw
685+
scissorStack[scissorDepth++] = nh
672686
glEnable(GL_SCISSOR_TEST)
673687
glScissor(nx, ny, nw, nh)
674688
}
675689

676690
override fun pushScissorIntersecting(x: Float, y: Float, width: Float, height: Float) {
677-
if (curScissor < 4) {
691+
if (scissorDepth < 4) {
678692
pushScissor(x, y, width, height)
679693
return
680694
}
681695
flush()
682-
val px = scissorStack[curScissor - 4]
683-
val py = scissorStack[curScissor - 3]
684-
val pw = scissorStack[curScissor - 2]
685-
val ph = scissorStack[curScissor - 1]
696+
val px = scissorStack[scissorDepth - 4]
697+
val py = scissorStack[scissorDepth - 3]
698+
val pw = scissorStack[scissorDepth - 2]
699+
val ph = scissorStack[scissorDepth - 1]
686700
val nx = (x * pixelRatio).roundToInt()
687701
val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt()
688702

@@ -691,27 +705,27 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
691705
val iw = maxOf(0, minOf(nx + (width * pixelRatio).roundToInt(), px + pw) - ix)
692706
val ih = maxOf(0, minOf(ny + (height * pixelRatio).roundToInt(), py + ph) - iy)
693707

694-
scissorStack[curScissor++] = ix
695-
scissorStack[curScissor++] = iy
696-
scissorStack[curScissor++] = iw
697-
scissorStack[curScissor++] = ih
708+
scissorStack[scissorDepth++] = ix
709+
scissorStack[scissorDepth++] = iy
710+
scissorStack[scissorDepth++] = iw
711+
scissorStack[scissorDepth++] = ih
698712

699713
glEnable(GL_SCISSOR_TEST)
700714
glScissor(ix, iy, iw, ih)
701715
}
702716

703717
override fun popScissor() {
704718
flush()
705-
if (curScissor <= 4) {
706-
curScissor = 0
719+
if (scissorDepth <= 4) {
720+
scissorDepth = 0
707721
glDisable(GL_SCISSOR_TEST)
708722
return
709723
}
710-
curScissor -= 4
711-
val x = scissorStack[curScissor - 4]
712-
val y = scissorStack[curScissor - 3]
713-
val width = scissorStack[curScissor - 2]
714-
val height = scissorStack[curScissor - 1]
724+
scissorDepth -= 4
725+
val x = scissorStack[scissorDepth - 4]
726+
val y = scissorStack[scissorDepth - 3]
727+
val width = scissorStack[scissorDepth - 2]
728+
val height = scissorStack[scissorDepth - 1]
715729
glEnable(GL_SCISSOR_TEST)
716730
glScissor(x, y, width, height)
717731
}
@@ -740,6 +754,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re
740754
popFlushNeeded = true
741755
}
742756

757+
private fun transformScale(): Float {
758+
val sx = sqrt(transform[0] * transform[0] + transform[3] * transform[3])
759+
val sy = sqrt(transform[1] * transform[1] + transform[4] * transform[4])
760+
return (sx + sy) * 0.5f
761+
}
762+
743763
override fun translate(x: Float, y: Float) {
744764
flush()
745765
transform[6] += transform[0] * x + transform[3] * y

0 commit comments

Comments
 (0)