Skip to content

Commit 17921d2

Browse files
committed
More work ..
1 parent 2173d95 commit 17921d2

5 files changed

Lines changed: 147 additions & 29 deletions

File tree

arcade/context.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,18 @@ def __init__(
9999
self.sprite_list_program_cull["sprite_texture"] = 0
100100
self.sprite_list_program_cull["uv_texture"] = 1
101101

102-
# self.sprite_list_program_no_geo = self.load_program(
103-
# vertex_shader=":system:shaders/sprites/sprite_list_simple_vs.glsl",
104-
# fragment_shader=":system:shaders/sprites/sprite_list_simple_fs.glsl",
105-
# )
106-
# self.sprite_list_program_no_geo["sprite_texture"] = 0
107-
# self.sprite_list_program_no_geo["uv_texture"] = 1
108-
# # Per-instance data
109-
# self.sprite_list_program_no_geo["pos_data"] = 2
110-
# self.sprite_list_program_no_geo["size_data"] = 3
111-
# self.sprite_list_program_no_geo["color_data"] = 4
112-
# self.sprite_list_program_no_geo["texture_id_data"] = 5
113-
# self.sprite_list_program_no_geo["index_data"] = 6
102+
self.sprite_list_program_no_geo = self.load_program(
103+
vertex_shader=":system:shaders/sprites/sprite_list_simple_vs.glsl",
104+
fragment_shader=":system:shaders/sprites/sprite_list_simple_fs.glsl",
105+
)
106+
self.sprite_list_program_no_geo["sprite_texture"] = 0
107+
self.sprite_list_program_no_geo["uv_texture"] = 1
108+
# Per-instance data
109+
self.sprite_list_program_no_geo["pos_data"] = 2
110+
self.sprite_list_program_no_geo["size_data"] = 3
111+
self.sprite_list_program_no_geo["color_data"] = 4
112+
self.sprite_list_program_no_geo["texture_id_data"] = 5
113+
self.sprite_list_program_no_geo["index_data"] = 6
114114

115115
self.sprite_program_single = self.load_program(
116116
vertex_shader=":system:shaders/sprites/sprite_single_vs.glsl",

arcade/resources/system/shaders/lib/sprite.glsl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Fetch texture coordiantes from uv texture
1+
// Fetch texture coordinates from uv texture
22
void getSpriteUVs(sampler2D uvData, int texture_id, out vec2 uv0, out vec2 uv1, out vec2 uv2, out vec2 uv3) {
33
texture_id *= 2;
44
// Calculate the position in the texture. Basic "line wrapping".
@@ -14,3 +14,26 @@ void getSpriteUVs(sampler2D uvData, int texture_id, out vec2 uv0, out vec2 uv1,
1414
uv2 = data_2.xy;
1515
uv3 = data_2.zw;
1616
}
17+
18+
// Functions for fetching per-instance data from textures.
19+
// These are used with the shader program that uses instancing to render sprites
20+
// meaning there is no geo shader involved. This should work for WebGL.
21+
vec4 getInstancePosRot(sampler2D posData, int index) {
22+
return texelFetch(posData, ivec2(index, 0), 0);
23+
}
24+
25+
vec2 getInstanceSize(sampler2D sizeData, int index) {
26+
return texelFetch(sizeData, ivec2(index, 0), 0).xy;
27+
}
28+
29+
vec4 getInstanceColor(sampler2D colorData, int index) {
30+
return texelFetch(colorData, ivec2(index, 0), 0);
31+
}
32+
33+
int getInstanceTextureId(isampler2D textureIdData, int index) {
34+
return texelFetch(textureIdData, ivec2(index, 0), 0).x;
35+
}
36+
37+
int getInstanceIndex(isampler2D indexData, int index) {
38+
return texelFetch(indexData, ivec2(index, 0), 0).x;
39+
}

arcade/resources/system/shaders/sprites/sprite_list_simple_fs.glsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ void main() {
1818
if (base_color.a == 0.0) {
1919
discard;
2020
}
21-
f_color = base_color;
21+
f_color = base_color + vec4(0.5, 0.5, 0.5, 1.0);
2222
}

arcade/resources/system/shaders/sprites/sprite_list_simple_vs.glsl

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#version 330
22
// vert/frag only version of the sprite list shader
33

4+
uniform WindowBlock {
5+
mat4 projection;
6+
mat4 view;
7+
} window;
8+
49
// Texture atlas
510
uniform sampler2D sprite_texture;
611
// Texture containing UVs for the entire atlas
@@ -17,21 +22,60 @@ uniform isampler2D index_data;
1722
// 0.0 is no offset, 1.0 is half a pixel offset
1823
uniform float uv_offset_bias;
1924

20-
// Per sprite/instance data
21-
in vec3 in_instance_pos;
2225
// Instanced geometry (rectangle as triangle strip)
2326
in vec2 in_pos;
2427

28+
// Output to frag shader
2529
out vec2 uv;
2630
out vec4 color;
2731

2832
#include :system:shaders/lib/sprite.glsl
2933

3034
void main() {
35+
// Reading per-instance data from textures.
36+
// First we need take the index texture into account to get the correct rendering order.
37+
int index = getInstanceIndex(index_data, gl_InstanceID);
38+
vec4 pos_rot = getInstancePosRot(pos_data, index);
39+
vec2 size = getInstanceSize(size_data, index);
40+
vec4 color = getInstanceColor(color_data, index);
41+
int texture_id = getInstanceTextureId(texture_id_data, index);
3142
// Read texture coordinates from UV texture here
3243
vec2 uv0, uv1, uv2, uv3;
33-
getSpriteUVs(uv_texture, int(in_instance_texture), uv0, uv1, uv2, uv3);
44+
getSpriteUVs(uv_texture, texture_id, uv0, uv1, uv2, uv3);
45+
46+
vec3 center = pos_rot.xyz;
47+
float angle = radians(pos_rot.w);
48+
mat2 rot = mat2(
49+
cos(angle), -sin(angle),
50+
sin(angle), cos(angle)
51+
);
52+
53+
mat4 mvp = window.projection * window.view;
3454

3555
// TODO: Half pixel offset
36-
// TODO: Position, rotation, size, color, uvs
56+
57+
int vertex_id = gl_VertexID % 4;
58+
color = color;
59+
switch (vertex_id) {
60+
case 0:
61+
// Upper left
62+
gl_Position = mvp * vec4(rot * size + center.xy, center.z, 1.0);
63+
uv = uv0;
64+
break;
65+
case 1:
66+
// lower left
67+
gl_Position = mvp * vec4(rot * size + center.xy, center.z, 1.0);
68+
uv = uv2;
69+
break;
70+
case 2:
71+
// upper right
72+
gl_Position = mvp * vec4(rot * size + center.xy, center.z, 1.0);
73+
uv = uv1;
74+
break;
75+
case 3:
76+
// lower right
77+
gl_Position = mvp * vec4(rot * size + center.xy, center.z, 1.0);
78+
uv = uv3;
79+
break;
80+
}
3781
}

arcade/sprite_list/sprite_list.py

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121

2222
from arcade import Sprite, SpriteType, SpriteType_co, get_window, gl
23-
from arcade.gl import Program, Texture2D
23+
from arcade.gl import Program, Texture2D, BufferDescription
2424
from arcade.gl.buffer import Buffer
2525
from arcade.gl.types import BlendFunction, OpenGlFilter, PyGLenum
2626
from arcade.gl.vertex_array import Geometry
@@ -293,9 +293,17 @@ def _init_deferred(self) -> None:
293293
self.ctx = get_window().ctx
294294
if not self._atlas:
295295
self._atlas = self.ctx.default_atlas
296-
self._spritelist_data = SpriteListBufferData(
296+
297+
# NOTE: Instantiate the appropriate spritelist data class here
298+
# Desktop GL (with geo shader)
299+
# self._spritelist_data = SpriteListBufferData(
300+
# self.ctx, capacity=self._buf_capacity, atlas=self._atlas
301+
# )
302+
# WebGL (without geo shader)
303+
self._spritelist_data = SpriteListTextureData(
297304
self.ctx, capacity=self._buf_capacity, atlas=self._atlas
298305
)
306+
299307
self._initialized = True
300308

301309
# Load all the textures and write texture coordinates into buffers.
@@ -1569,19 +1577,29 @@ def __init__(self, ctx: ArcadeContext, capacity: int, atlas: TextureAtlasBase) -
15691577
self._atlas = atlas
15701578

15711579
# Program without geo shader
1572-
self.program = self.ctx.load_program(
1573-
vertex_shader=":system:shaders/sprites/sprite_list_simple_vs.glsl",
1574-
fragment_shader=":system:shaders/sprites/sprite_list_simple_fs.glsl",
1575-
)
1576-
self._geometry: Geometry | None = None
1580+
self.program = self.ctx.sprite_list_program_no_geo
15771581
self._atlas = atlas or self.ctx.default_atlas
15781582

1583+
# fmt: off
1584+
self._instance_buffer = self.ctx.buffer(
1585+
data=array("f", [
1586+
-0.5, +0.5, # Upper left
1587+
-0.5, -0.5, # lower left
1588+
+0.5, +0.5, # upper right
1589+
+0.5, -0.5, # lower right
1590+
]),
1591+
)
1592+
# fmt: on
1593+
self._geometry = self.ctx.geometry(
1594+
[BufferDescription(self._instance_buffer, "2f", ["in_pos"], instanced=True)],
1595+
)
1596+
15791597
# Texture buffers for per-sprite data. These are looked up using gl_InstanceID
15801598
self._pos_angle_texture = self.ctx.texture(size=(capacity, 4), dtype="f4")
15811599
self._size_texture = self.ctx.texture(size=(capacity, 2), dtype="f4")
15821600
self._color_texture = self.ctx.texture(size=(capacity, 4), dtype="f4")
1583-
self._texture_id_texture = self.ctx.texture(size=(capacity, 1), dtype="I4")
1584-
self._index_texture = self.ctx.texture(size=(capacity, 1), dtype="I4")
1601+
self._texture_id_texture = self.ctx.texture(size=(capacity, 1), dtype="i4")
1602+
self._index_texture = self.ctx.texture(size=(capacity, 1), dtype="i4")
15851603

15861604
def write_sprite_buffers_to_gpu(
15871605
self,
@@ -1598,7 +1616,40 @@ def write_sprite_buffers_to_gpu(
15981616
sprite_texture_changed: bool = True,
15991617
sprite_index_changed: bool = True,
16001618
) -> None:
1601-
pass
1619+
"""
1620+
Write the sprite buffers to the GPU.
1621+
1622+
Args:
1623+
sprite_pos_angle_data: Array of sprite positions.
1624+
sprite_size_data: Array of sprite sizes.
1625+
sprite_color_data: Array of sprite colors.
1626+
sprite_texture_data: Array of sprite texture IDs.
1627+
sprite_index_data: Array of sprite indices.
1628+
sprite_pos_angle_changed: Whether the position data has changed.
1629+
sprite_size_changed: Whether the size data has changed.
1630+
sprite_color_changed: Whether the color data has changed.
1631+
sprite_texture_changed: Whether the texture data has changed.
1632+
sprite_index_changed: Whether the index data has changed.
1633+
"""
1634+
if sprite_pos_angle_changed:
1635+
self._pos_angle_texture.write(sprite_pos_angle_data)
1636+
self._sprite_pos_angle_changed = False
1637+
1638+
if sprite_size_changed:
1639+
self._size_texture.write(sprite_size_data)
1640+
self._sprite_size_changed = False
1641+
1642+
if sprite_color_changed:
1643+
self._color_texture.write(sprite_color_data)
1644+
self._sprite_color_changed = False
1645+
1646+
if sprite_texture_changed:
1647+
self._texture_id_texture.write(sprite_texture_data)
1648+
self._sprite_texture_changed = False
1649+
1650+
if sprite_index_changed:
1651+
self._index_texture.write(sprite_index_data)
1652+
self._sprite_index_changed = False
16021653

16031654
def grow_sprite_buffers(self) -> None:
16041655
"""Double the internal storage"""
@@ -1687,7 +1738,7 @@ def render(
16871738
self._geometry.render(
16881739
self.program,
16891740
mode=self.ctx.POINTS,
1690-
vertices=count,
1741+
instances=count,
16911742
)
16921743

16931744
# Leave global states to default

0 commit comments

Comments
 (0)