Skip to content

Commit b48e20c

Browse files
committed
GUI surface shader work
1 parent 8940f69 commit b48e20c

File tree

3 files changed

+69
-68
lines changed

3 files changed

+69
-68
lines changed

arcade/gui/surface.py

+57-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
from array import array
12
from contextlib import contextmanager
23
from typing import Generator
34

45
from PIL import Image
6+
from pyglet.math import Vec2, Vec4
57
from typing_extensions import Self
68

79
import arcade
810
from arcade import Texture
911
from arcade.camera import CameraData, OrthographicProjectionData, OrthographicProjector
1012
from arcade.color import TRANSPARENT_BLACK
11-
from arcade.gl import Framebuffer
13+
from arcade.gl import BufferDescription, Framebuffer
1214
from arcade.gui.nine_patch import NinePatchTexture
1315
from arcade.types import LBWH, RGBA255, Point, Rect
1416

@@ -53,12 +55,17 @@ def __init__(
5355
*self.ctx.BLEND_DEFAULT,
5456
)
5557

56-
self._geometry = self.ctx.geometry()
58+
# 5 floats per vertex (pos 3f, tex 2f) with 4 vertices
59+
self._buffer = self.ctx.buffer(reserve=4 * 5 * 4)
60+
self._geometry = self.ctx.geometry(
61+
content=[BufferDescription(self._buffer, "3f 2f", ["in_pos", "in_uv"])],
62+
mode=self.ctx.TRIANGLE_STRIP,
63+
)
5764
self._program = self.ctx.load_program(
5865
vertex_shader=":system:shaders/gui/surface_vs.glsl",
59-
geometry_shader=":system:shaders/gui/surface_gs.glsl",
6066
fragment_shader=":system:shaders/gui/surface_fs.glsl",
6167
)
68+
self._update_geometry()
6269

6370
self._cam = OrthographicProjector(
6471
view=CameraData(),
@@ -228,6 +235,8 @@ def draw(
228235
area: Limit the area in the surface we're drawing
229236
(l, b, w, h)
230237
"""
238+
self._update_geometry(area=area)
239+
231240
# Set blend function
232241
blend_func = self.ctx.blend_func
233242
self.ctx.blend_func = self.blend_func_render
@@ -239,10 +248,7 @@ def draw(
239248
self.texture.filter = self.ctx.LINEAR, self.ctx.LINEAR
240249

241250
self.texture.use(0)
242-
self._program["pos"] = self._pos
243-
self._program["size"] = self._size
244-
self._program["area"] = (0, 0, *self._size) if not area else area.lbwh
245-
self._geometry.render(self._program, vertices=1)
251+
self._geometry.render(self._program)
246252

247253
# Restore blend function
248254
self.ctx.blend_func = blend_func
@@ -267,3 +273,47 @@ def resize(self, *, size: tuple[int, int], pixel_ratio: float) -> None:
267273
def to_image(self) -> Image.Image:
268274
"""Convert the surface to an PIL image"""
269275
return self.ctx.get_framebuffer_image(self.fbo)
276+
277+
def _update_geometry(self, area: Rect | None = None) -> None:
278+
"""
279+
Update the internal geometry of the surface mesh.
280+
281+
The geometry is a triangle strip with 4 verties.
282+
"""
283+
if area is None:
284+
area = LBWH(0, 0, *self.size)
285+
286+
# Clamp the area inside the surface
287+
# This is the local area inside the surface
288+
_size = Vec2(*self.size)
289+
_pos = Vec2(area.left, area.bottom)
290+
_area_size = Vec2(area.width, area.height)
291+
292+
b1 = _pos.clamp(Vec2(0.0), _size)
293+
end_point = _pos + _area_size
294+
b2 = end_point.clamp(Vec2(0.0), _size)
295+
b = b2 - b1
296+
l_area = Vec4(b1.x, b1.y, b.x, b.y)
297+
298+
# Create the 4 corners of the rectangle
299+
# These are the final/global coordinates rendered
300+
p_ll = _pos + l_area.xy # type: ignore
301+
p_lr = _pos + l_area.xy + Vec2(l_area.z, 0.0) # type: ignore
302+
p_ul = _pos + l_area.xy + Vec2(0.0, l_area.w) # type: ignore
303+
p_ur = _pos + l_area.xy + l_area.zw # type: ignore
304+
305+
# Calculate the UV coordinates
306+
bottom = l_area.y / _size.y
307+
left = l_area.x / _size.x
308+
top = (l_area.y + l_area.w) / _size.y
309+
right = (l_area.x + l_area.z) / _size.x
310+
311+
# fmt: off
312+
vertices = array("f", (
313+
p_ll.x, p_ll.y, 0.0, left, bottom,
314+
p_lr.x, p_lr.y, 0.0, right, bottom,
315+
p_ul.x, p_ul.y, 0.0, left, top,
316+
p_ur.x, p_ur.y, 0.0, right, top,
317+
))
318+
# fmt: on
319+
self._buffer.write(vertices)

arcade/resources/system/shaders/gui/surface_gs.glsl

-60
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
#version 330
22

3+
uniform WindowBlock {
4+
mat4 projection;
5+
mat4 view;
6+
} window;
7+
8+
in vec3 in_pos;
9+
in vec2 in_uv;
10+
11+
out vec2 uv;
12+
313
void main() {
4-
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
14+
gl_Position = window.projection * window.view * vec4(in_pos, 1.0);
15+
uv = in_uv;
516
}

0 commit comments

Comments
 (0)