Skip to content

Commit

Permalink
Introduce Context instance
Browse files Browse the repository at this point in the history
All creation of OpenGL objects must now be done through the Context instance in the active window.
  • Loading branch information
einarf committed Apr 8, 2020
1 parent 9a99909 commit 4133188
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 233 deletions.
1 change: 0 additions & 1 deletion arcade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
from .buffered_draw_commands import TShape
from .buffered_draw_commands import Shape
from .buffered_draw_commands import ShapeElementList
from .buffered_draw_commands import VertexBuffer
from .buffered_draw_commands import create_ellipse
from .buffered_draw_commands import create_ellipse_filled
from .buffered_draw_commands import create_ellipse_filled_with_colors
Expand Down
8 changes: 8 additions & 0 deletions arcade/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,17 @@ def __init__(self, width: int = 800, height: int = 600,
self.textbox_time = 0.0
self.key: Optional[int] = None

# Representation of the OpenGL context for this window
self._ctx = shader.Context(self)

# Tell shaders the window is the current render target
shader.Framebuffer.active = self

@property
def ctx(self) -> shader.Context:
"""The OpenGL context for this window"""
return self._ctx

def update(self, delta_time: float):
"""
Move everything. For better consistency in naming, use ``on_update`` instead.
Expand Down
48 changes: 15 additions & 33 deletions arcade/buffered_draw_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,11 @@
from arcade import Point, PointList
from arcade import get_four_byte_color
from arcade import get_projection
from arcade import get_window
from arcade import get_points_for_thick_line
from arcade import shader


class VertexBuffer:
"""
This class represents a `vertex buffer object`_ for internal library use. Clients
of the library probably don't need to use this.
Attributes:
:vbo_id: ID of the vertex buffer as assigned by OpenGL
:size:
:width:
:height:
:color:
.. _vertex buffer object:
https://en.wikipedia.org/wiki/Vertex_Buffer_Object
"""
def __init__(self, vbo_vertex_id: gl.GLuint, size: float, draw_mode: int, vbo_color_id: gl.GLuint = None):
self.vbo_vertex_id = vbo_vertex_id
self.vbo_color_id = vbo_color_id
self.size = size
self.draw_mode = draw_mode
self.color = None
self.line_width = 0


class Shape:
def __init__(self):
self.vao = None
Expand Down Expand Up @@ -116,7 +91,13 @@ def create_line_generic_with_colors(point_list: PointList,
:Returns Shape:
"""
program = shader.program(
window = get_window()
if window is None:
raise RuntimeError("Cannot create Shape without a Window")

ctx = window.ctx

program = ctx.program(
vertex_shader='''
#version 330
uniform mat4 Projection;
Expand All @@ -143,7 +124,7 @@ def create_line_generic_with_colors(point_list: PointList,
data['vertex'] = point_list
data['color'] = [get_four_byte_color(color) for color in color_list]

vbo = shader.buffer(data.tobytes())
vbo = ctx.buffer(data.tobytes())
vao_content = [
shader.BufferDescription(
vbo,
Expand All @@ -153,7 +134,7 @@ def create_line_generic_with_colors(point_list: PointList,
)
]

vao = shader.vertex_array(program, vao_content)
vao = ctx.vertex_array(program, vao_content)
program['Projection'] = get_projection().flatten()

shape = Shape()
Expand Down Expand Up @@ -609,14 +590,15 @@ def __init__(self):
"""
Initialize the sprite list
"""
self.ctx = get_window().ctx
# List of sprites in the sprite list
self.shape_list = []
self.change_x = 0
self.change_y = 0
self._center_x = 0
self._center_y = 0
self._angle = 0
self.program = shader.program(
self.program = self.ctx.program(
vertex_shader='''
#version 330
uniform mat4 Projection;
Expand Down Expand Up @@ -672,7 +654,7 @@ def _refresh_shape(self, group):
# Create a buffer large enough to hold all the shapes buffers
batch = self.batches[group]
total_vbo_bytes = sum(s.vbo.size for s in batch.items)
vbo = shader.Buffer.create_with_size(total_vbo_bytes)
vbo = self.ctx.buffer(reserve=total_vbo_bytes)
offset = 0
gl.glBindBuffer(gl.GL_COPY_WRITE_BUFFER, vbo.buffer_id)
# Copy all the shapes buffer in our own vbo
Expand All @@ -696,7 +678,7 @@ def _refresh_shape(self, group):
indices.append(reset_idx)
del indices[-1]
indices = np.array(indices)
ibo = shader.Buffer(indices.astype('i4').tobytes())
ibo = self.ctx.buffer(data=indices.astype('i4').tobytes())

vao_content = [
shader.BufferDescription(
Expand All @@ -706,7 +688,7 @@ def _refresh_shape(self, group):
normalized=['in_color']
)
]
vao = shader.vertex_array(self.program, vao_content, ibo)
vao = self.ctx.vertex_array(self.program, vao_content, ibo)
self.program['Projection'] = get_projection().flatten()
self.program['Position'] = [self.center_x, self.center_y]
self.program['Angle'] = self.angle
Expand Down
13 changes: 9 additions & 4 deletions arcade/draw_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,16 +406,21 @@ def _generic_draw_line_strip(point_list: PointList,
"""
# Cache the program. But not on linux because it fails unit tests for some reason.
# if not _generic_draw_line_strip.program or sys.platform == "linux":
window = get_window()
if window is None:
raise RuntimeError("Cannot draw without a Window")

ctx = window.ctx

program = shader.program(
program = ctx.program(
vertex_shader=_line_vertex_shader,
fragment_shader=_line_fragment_shader,
)

c4 = get_four_byte_color(color)
c4e = c4 * len(point_list)
a = array.array('B', c4e)
color_buf = shader.buffer(a.tobytes())
color_buf = ctx.buffer(a.tobytes())
color_buf_desc = shader.BufferDescription(
color_buf,
'4B',
Expand All @@ -428,7 +433,7 @@ def gen_flatten(my_list):

vertices = array.array('f', gen_flatten(point_list))

vbo_buf = shader.buffer(vertices.tobytes())
vbo_buf = ctx.buffer(vertices.tobytes())
vbo_buf_desc = shader.BufferDescription(
vbo_buf,
'2f',
Expand All @@ -437,7 +442,7 @@ def gen_flatten(my_list):

vao_content = [vbo_buf_desc, color_buf_desc]

vao = shader.vertex_array(program, vao_content)
vao = ctx.vertex_array(program, vao_content)
program['Projection'] = get_projection().flatten()
vao.render(mode=mode)

Expand Down
154 changes: 79 additions & 75 deletions arcade/experimental/defender.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,11 @@ def __init__(self, width, height, title):
self.quad_fs = None
self.mini_map_quad = None

program = shader.load_program("simple_shader.vert", "simple_shader.frag")
self.minimap_color_attachment = shader.texture((SCREEN_WIDTH, SCREEN_HEIGHT), 4)
self.minimap_screen = shader.framebuffer(color_attachments=[self.minimap_color_attachment])
self.play_screen_color_attachment = shader.texture((SCREEN_WIDTH, SCREEN_HEIGHT), 4)
self.play_screen = shader.framebuffer(color_attachments=[self.play_screen_color_attachment])
program = self.ctx.load_program("simple_shader.vert", "simple_shader.frag")
self.minimap_color_attachment = self.ctx.texture((SCREEN_WIDTH, SCREEN_HEIGHT), 4)
self.minimap_screen = self.ctx.framebuffer(color_attachments=[self.minimap_color_attachment])
self.play_screen_color_attachment = self.ctx.texture((SCREEN_WIDTH, SCREEN_HEIGHT), 4)
self.play_screen = self.ctx.framebuffer(color_attachments=[self.play_screen_color_attachment])
self.mini_map_quad = geometry.quad_fs(program, size=(2.0, 0.5), pos=(0.0, 0.75))
self.play_screen_quad = geometry.quad_fs(program, size=(2.0, 1.5), pos=(0.0, 0.0))

Expand Down Expand Up @@ -174,76 +174,80 @@ def setup(self):

def on_draw(self):
""" Render the screen. """

# This command has to happen before we start drawing
arcade.start_render()

# Draw to the frame buffer used in the minimap
self.minimap_screen.use()
self.minimap_screen.clear()

arcade.set_viewport(0,
PLAYING_FIELD_WIDTH,
0,
SCREEN_HEIGHT)

self.enemy_sprite_list.draw()
self.bullet_sprite_list.draw()
self.player_list.draw()

# Now draw to the actual screen
self.play_screen.use()
self.play_screen.clear()

# self.use()

arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom)

# Draw all the sprites on the screen
self.star_sprite_list.draw()
self.enemy_sprite_list.draw()
self.bullet_sprite_list.draw()
self.player_list.draw()

# Draw the ground
arcade.draw_line(0, 0, PLAYING_FIELD_WIDTH, 0, arcade.color.WHITE)

self.use()

arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom)

gl.glDisable(gl.GL_BLEND)
self.glow.render(self.play_screen_color_attachment, self)
gl.glEnable(gl.GL_BLEND)

# Draw a background for the minimap
arcade.draw_rectangle_filled(SCREEN_WIDTH - SCREEN_WIDTH / 2 + self.view_left,
SCREEN_HEIGHT - SCREEN_HEIGHT / 8 + self.view_bottom,
SCREEN_WIDTH,
SCREEN_HEIGHT / 4,
arcade.color.DARK_GREEN)

# Draw the minimap
self.minimap_color_attachment.use(0)
self.mini_map_quad.render()

# Draw a rectangle showing where the screen is
width_ratio = SCREEN_WIDTH / PLAYING_FIELD_WIDTH
height_ratio = MINIMAP_HEIGHT / PLAYING_FIELD_HEIGHT
width = width_ratio * SCREEN_WIDTH
height = height_ratio * MAIN_SCREEN_HEIGHT
x = (self.view_left + SCREEN_WIDTH / 2) * width_ratio + self.view_left
y = self.view_bottom + height / 2 + (SCREEN_HEIGHT - MINIMAP_HEIGHT) + self.view_bottom * height_ratio

arcade.draw_rectangle_outline(center_x=x, center_y=y,
width=width, height=height,
color=arcade.color.WHITE)
try:
# This command has to happen before we start drawing
arcade.start_render()

# Draw to the frame buffer used in the minimap
self.minimap_screen.use()
self.minimap_screen.clear()

arcade.set_viewport(0,
PLAYING_FIELD_WIDTH,
0,
SCREEN_HEIGHT)

self.enemy_sprite_list.draw()
self.bullet_sprite_list.draw()
self.player_list.draw()

# Now draw to the actual screen
self.play_screen.use()
self.play_screen.clear()

# self.use()

arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom)

# Draw all the sprites on the screen
self.star_sprite_list.draw()
self.enemy_sprite_list.draw()
self.bullet_sprite_list.draw()
self.player_list.draw()

# Draw the ground
arcade.draw_line(0, 0, PLAYING_FIELD_WIDTH, 0, arcade.color.WHITE)

self.use()

arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom)

gl.glDisable(gl.GL_BLEND)
self.glow.render(self.play_screen_color_attachment, self)
gl.glEnable(gl.GL_BLEND)

# Draw a background for the minimap
arcade.draw_rectangle_filled(SCREEN_WIDTH - SCREEN_WIDTH / 2 + self.view_left,
SCREEN_HEIGHT - SCREEN_HEIGHT / 8 + self.view_bottom,
SCREEN_WIDTH,
SCREEN_HEIGHT / 4,
arcade.color.DARK_GREEN)

# Draw the minimap
self.minimap_color_attachment.use(0)
self.mini_map_quad.render()

# Draw a rectangle showing where the screen is
width_ratio = SCREEN_WIDTH / PLAYING_FIELD_WIDTH
height_ratio = MINIMAP_HEIGHT / PLAYING_FIELD_HEIGHT
width = width_ratio * SCREEN_WIDTH
height = height_ratio * MAIN_SCREEN_HEIGHT
x = (self.view_left + SCREEN_WIDTH / 2) * width_ratio + self.view_left
y = self.view_bottom + height / 2 + (SCREEN_HEIGHT - MINIMAP_HEIGHT) + self.view_bottom * height_ratio

arcade.draw_rectangle_outline(center_x=x, center_y=y,
width=width, height=height,
color=arcade.color.WHITE)

except Exception as e:
import traceback
traceback.print_exc()

print("Done")

Expand Down
7 changes: 4 additions & 3 deletions arcade/experimental/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Temporary module to play with shaders and geometry
"""
import numpy
from arcade import shader
from arcade import shader, get_window
import pyglet.gl as gl


Expand All @@ -18,15 +18,16 @@ def quad_fs(program, size=(1.0, 1.0), pos=(0.0, 0.0)):
xpos + width / 2.0, ypos + height / 2.0, 1.0, 1.0
], dtype=numpy.float32)

vbo = shader.buffer(data.tobytes())
ctx = get_window().ctx
vbo = ctx.buffer(data.tobytes())
vao_content = [
shader.BufferDescription(
vbo,
'2f 2f',
('in_vert', 'in_uv'),
)
]
return Thingy(shader.vertex_array(program, vao_content), program, vbo)
return Thingy(ctx.vertex_array(program, vao_content), program, vbo)


class Thingy:
Expand Down
Loading

0 comments on commit 4133188

Please sign in to comment.