Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions arcade/examples/gl/spritelist_interaction_bouncing_coins.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@

from array import array
from random import randint, uniform
from typing import cast

import arcade
from arcade.gl.types import BufferDescription
from arcade.gl import BufferDescription, Buffer
from arcade import hitbox

WINDOW_WIDTH = 1280
Expand All @@ -32,7 +33,7 @@ def __init__(self):
super().__init__(WINDOW_WIDTH, WINDOW_HEIGHT, resizable=True)

# Generate lots of coins in random positions
self.coins = arcade.SpriteList(use_spatial_hash=None)
self.coins = arcade.SpriteList(use_spatial_hash=False)
texture = arcade.load_texture(
":resources:images/items/coinGold.png",
hit_box_algorithm=hitbox.algo_bounding_box,
Expand All @@ -59,14 +60,14 @@ def __init__(self):
uniform float delta_time;
uniform vec2 size;

in vec3 in_pos;
in vec4 in_pos_angle;
in vec2 in_vel;

out vec3 out_pos;
out vec4 out_pos_angle;
out vec2 out_vel;

void main() {
vec2 pos = in_pos.xy + in_vel * 100.0 * delta_time;
vec2 pos = in_pos_angle.xy + in_vel * 100.0 * delta_time;
vec2 vel = in_vel;
if (pos.x > size.x) {
pos.x = size.x;
Expand All @@ -84,7 +85,7 @@ def __init__(self):
pos.y = 0.0;
vel.y *= -1.0;
}
out_pos = vec3(pos, in_pos.z);
out_pos_angle = vec4(pos, in_pos_angle.zw);
out_vel = vel;
}
""",
Expand All @@ -103,19 +104,20 @@ def __init__(self):
self.buffer_velocity_2 = self.ctx.buffer(reserve=self.buffer_velocity_1.size)
# Create a buffer with the same size as the position buffer in the spritelist.
# It's important that these match because we're copying that buffer into this one.
self.buffer_pos_copy = self.ctx.buffer(reserve=self.coins.buffer_positions.size)
self.buffer_pos_angle = cast(Buffer, self.coins.data.storage_positions_angle)
self.buffer_pos_angle_copy = self.ctx.buffer(reserve=self.buffer_pos_angle.size)

# Geometry input: Copied positions and first velocity buffer
self.geometry_1 = self.ctx.geometry(
[
BufferDescription(self.buffer_pos_copy, "3f", ["in_pos"]),
BufferDescription(self.buffer_pos_angle_copy, "4f", ["in_pos_angle"]),
BufferDescription(self.buffer_velocity_1, "2f", ["in_vel"]),
]
)
# Geometry input: Copied positions and second velocity buffer
self.geometry_2 = self.ctx.geometry(
[
BufferDescription(self.buffer_pos_copy, "3f", ["in_pos"]),
BufferDescription(self.buffer_pos_angle_copy, "4f", ["in_pos_angle"]),
BufferDescription(self.buffer_velocity_2, "2f", ["in_vel"]),
]
)
Expand All @@ -124,13 +126,13 @@ def on_draw(self):
self.clear()

# Copy the position buffer. This happens on the gpu side.
self.buffer_pos_copy.copy_from_buffer(self.coins.buffer_positions)
self.buffer_pos_angle_copy.copy_from_buffer(self.buffer_pos_angle)

# Run the transform writing new positions and velocities
self.geometry_1.transform(
self.program,
[
self.coins.buffer_positions,
self.buffer_pos_angle,
self.buffer_velocity_2,
],
)
Expand Down
23 changes: 17 additions & 6 deletions arcade/examples/gl/spritelist_interaction_hijack_positions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
"""

import math
from typing import cast

import arcade
from arcade import hitbox
from arcade.sprite_list.sprite_list import SpriteListBufferData
from arcade.gl import Buffer

NUM_COINS = 500

Expand Down Expand Up @@ -38,23 +42,24 @@ def __init__(self):

// The current time to add some movement
uniform float time;
// The "bendyness" value accelerating rotations
// The "bendiness" value accelerating rotations
uniform float bend;

// The current size of the screen
uniform vec2 size;

// The new positions we are writing into a new buffer
out vec3 out_pos;
out vec4 out_pos;

void main() {
// gl_VertexID is the sprite position in the spritelist.
// We can use that to value to create unique positions with
// some simple math.
float vertId = float(gl_VertexID);
out_pos = vec3(size, 0.0) / 2.0 + vec3(
out_pos = vec4(size, 0.0, 0.0) / 2.0 + vec4(
sin(vertId + time + vertId * bend),
cos(vertId + time + vertId * bend),
0.0,
0.0
) * vertId;
}
Expand All @@ -65,19 +70,25 @@ def __init__(self):
def on_draw(self):
self.clear()

if not isinstance(self.coins.data, SpriteListBufferData):
raise RuntimeError(
"The spritelist data must be of type SpriteListBufferData."
)
pos_angle_buffer = cast(Buffer, self.coins.data.storage_positions_angle)

# Write the new positions directly into the position
# buffer of the spritelist. A little bit rude, but it works.
self.coins.geometry.transform(
self.coins.data.geometry.transform(
self.position_program,
self.coins.buffer_positions,
pos_angle_buffer,
vertices=len(self.coins),
)
self.coins.draw()

def on_update(self, delta_time: float):
# Keep updating the current time to animation the movement
self.position_program["time"] = self.time / 4
# Update the "bendyness" value
# Update the "bendiness" value
self.position_program["bend"] = math.cos(self.time) / 400

def on_resize(self, width: int, height: int):
Expand Down
6 changes: 3 additions & 3 deletions arcade/examples/gl/spritelist_interaction_visualize_dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ def __init__(self):
#version 330

// Sprite positions from SpriteList
in vec3 in_pos;
in vec4 in_pos;

// Output to geometry shader
out vec3 v_position;

void main() {
// This shader just forwards info to geo shader
v_position = in_pos;
v_position = in_pos.xyz;
}
""",
geometry_shader="""
Expand Down Expand Up @@ -120,7 +120,7 @@ def on_draw(self):
# use to run our shader/gpu program. It only requires that we
# use correctly named input name(s). in_pos in this example
# what will automatically map in the position buffer to the vertex shader.
self.coins.geometry.render(self.program_visualize_dist, vertices=len(self.coins))
self.coins.data.geometry.render(self.program_visualize_dist, vertices=len(self.coins))
arcade.draw_sprite(self.player)

# Visualize the interaction radius
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ def __init__(self):
#version 330

// Sprite positions from SpriteList
in vec3 in_pos;
in vec4 in_pos;

// Output to geometry shader
out vec3 v_position;

void main() {
// This shader just forwards info to geo shader
v_position = in_pos;
v_position = in_pos.xyz;
}
""",
geometry_shader="""
Expand Down Expand Up @@ -178,7 +178,7 @@ def on_draw(self):
# use to run our shader/gpu program. It only requires that we
# use correctly named input name(s). in_pos in this example
# what will automatically map in the position buffer to the vertex shader.
self.coins.geometry.render(self.program_visualize_dist, vertices=len(self.coins))
self.coins.data.geometry.render(self.program_visualize_dist, vertices=len(self.coins))
arcade.draw_sprite(self.player)

# Visualize the interaction radius
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ def __init__(self):
#version 330

// Sprite positions from SpriteList
in vec3 in_pos;
in vec4 in_pos;

// Output to geometry shader
out vec3 v_position;

void main() {
// This shader just forwards info to geo shader
v_position = in_pos;
v_position = in_pos.xyz;
}
""",
geometry_shader="""
Expand Down Expand Up @@ -183,7 +183,7 @@ def on_draw(self):
# use to run our shader/gpu program. It only requires that we
# use correctly named input name(s). in_pos in this example
# what will automatically map in the position buffer to the vertex shader.
self.coins.geometry.transform(
self.coins.data.geometry.transform(
self.program_select_sprites,
self.result_buffer,
vertices=len(self.coins),
Expand Down
31 changes: 11 additions & 20 deletions arcade/sprite_list/sprite_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,11 @@ def _init_deferred(self) -> None:

# NOTE: Instantiate the appropriate spritelist data class here
# Desktop GL (with geo shader)
# self._data = SpriteListBufferData(
self._data = SpriteListBufferData(self.ctx, capacity=self._buf_capacity, atlas=self._atlas)
# WebGL (without geo shader)
# self._data = SpriteListTextureData(
# self.ctx, capacity=self._buf_capacity, atlas=self._atlas
# )
# WebGL (without geo shader)
self._data = SpriteListTextureData(self.ctx, capacity=self._buf_capacity, atlas=self._atlas)
self._initialized = True

# Load all the textures and write texture coordinates into buffers.
Expand Down Expand Up @@ -1260,6 +1260,7 @@ def __init__(self, ctx: ArcadeContext, capacity: int) -> None:
self.ctx = ctx
self._buf_capacity = capacity
self._idx_capacity = capacity
self._geometry: Geometry

# Generic GPU storage for sprite data
self._storage_pos_angle: Buffer | Texture2D
Expand All @@ -1268,6 +1269,13 @@ def __init__(self, ctx: ArcadeContext, capacity: int) -> None:
self._storage_texture_id: Buffer | Texture2D
self._storage_index: Buffer | Texture2D

@property
def geometry(self) -> Geometry:
"""
Returns the internal OpenGL geometry for this spritelist.
"""
return self._geometry

@property
def storage_positions_angle(self) -> Buffer | Texture2D:
"""
Expand Down Expand Up @@ -1441,23 +1449,6 @@ def __init__(self, ctx: ArcadeContext, capacity: int, atlas: TextureAtlasBase) -
index_element_size=4, # 32 bit integers
)

@property
def geometry(self) -> Geometry:
"""
Returns the internal OpenGL geometry for this spritelist.
This can be used to execute custom shaders with the
spritelist data.

One or multiple of the following inputs must be defined in your vertex shader::

in vec2 in_pos;
in float in_angle;
in vec2 in_size;
in float in_texture;
in vec4 in_color;
"""
return self._geometry

@property
def buffer_positions_angle(self) -> Buffer:
"""
Expand Down
Loading