Skip to content

Commit

Permalink
Merge pull request #194 from p5py/openglrenderer
Browse files Browse the repository at this point in the history
Abstract common rendering logic in OpenGLRenderer
  • Loading branch information
arihantparsoya authored Jul 11, 2020
2 parents d9ab604 + b892491 commit baac189
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 264 deletions.
139 changes: 139 additions & 0 deletions p5/sketch/openglrenderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
from abc import ABC
import numpy as np

from vispy.gloo import Program, VertexBuffer, FrameBuffer, IndexBuffer
from .shaders2d import src_default, src_fbuffer


# Abstract class that contains common code for OpenGL renderers
class OpenGLRenderer(ABC):
def __init__(self):
self.default_prog = None
self.fbuffer_prog = None

self.fbuffer = None
self.fbuffer_tex_front = None
self.fbuffer_tex_back = None

self.vertex_buffer = None
self.index_buffer = None

# Renderer Globals: USEFUL CONSTANTS
self.COLOR_WHITE = (1, 1, 1, 1)
self.COLOR_BLACK = (0, 0, 0, 1)
self.COLOR_DEFAULT_BG = (0.8, 0.8, 0.8, 1.0)

# Renderer Globals: STYLE/MATERIAL PROPERTIES
#
self.background_color = self.COLOR_DEFAULT_BG

self.fill_color = self.COLOR_WHITE
self.fill_enabled = True

self.stroke_color = self.COLOR_BLACK
self.stroke_enabled = True

self.tint_color = self.COLOR_BLACK
self.tint_enabled = False

# Renderer Globals: Curves
self.stroke_weight = 1
self.stroke_cap = 2
self.stroke_join = 0

# Renderer Globals
# VIEW MATRICES, ETC
#
self.viewport = None
self.texture_viewport = None
self.transform_matrix = np.identity(4)
self.projection_matrix = np.identity(4)

# Renderer Globals: RENDERING
self.draw_queue = []

def initialize_renderer(self):
self.fbuffer = FrameBuffer()

vertices = np.array([[-1.0, -1.0],
[+1.0, -1.0],
[-1.0, +1.0],
[+1.0, +1.0]],
np.float32)
texcoords = np.array([[0.0, 0.0],
[1.0, 0.0],
[0.0, 1.0],
[1.0, 1.0]],
dtype=np.float32)

self.fbuf_vertices = VertexBuffer(data=vertices)
self.fbuf_texcoords = VertexBuffer(data=texcoords)

self.fbuffer_prog = Program(src_fbuffer.vert, src_fbuffer.frag)
self.fbuffer_prog['texcoord'] = self.fbuf_texcoords
self.fbuffer_prog['position'] = self.fbuf_vertices

self.vertex_buffer = VertexBuffer()
self.index_buffer = IndexBuffer()

self.default_prog = Program(src_default.vert, src_default.frag)

def render_default(self, draw_type, draw_queue):
# 1. Get the maximum number of vertices persent in the shapes
# in the draw queue.
#
if len(draw_queue) == 0:
return

num_vertices = 0
for vertices, _, _ in draw_queue:
num_vertices = num_vertices + len(vertices)

# 2. Create empty buffers based on the number of vertices.
#
data = np.zeros(num_vertices,
dtype=[('position', np.float32, 3),
('color', np.float32, 4)])

# 3. Loop through all the shapes in the geometry queue adding
# it's information to the buffer.
#
sidx = 0
draw_indices = []
for vertices, idx, color in draw_queue:
num_shape_verts = len(vertices)

data['position'][sidx:(sidx + num_shape_verts), ] = np.array(vertices)

color_array = np.array([color] * num_shape_verts)
data['color'][sidx:sidx + num_shape_verts, :] = color_array

draw_indices.append(sidx + idx)

sidx += num_shape_verts

self.vertex_buffer.set_data(data)
self.index_buffer.set_data(np.hstack(draw_indices))

# 4. Bind the buffer to the shader.
#
self.default_prog.bind(self.vertex_buffer)

# 5. Draw the shape using the proper shape type and get rid of
# the buffers.
#
self.default_prog.draw(draw_type, indices=self.index_buffer)

def cleanup(self):
"""Run the clean-up routine for the renderer.
This method is called when all drawing has been completed and the
program is about to exit.
"""
self.default_prog.delete()
self.fbuffer_prog.delete()
self.fbuffer.delete()

def _transform_vertices(self, vertices, local_matrix, global_matrix):
return np.dot(np.dot(vertices, local_matrix.T), global_matrix.T)[:, :3]
132 changes: 5 additions & 127 deletions p5/sketch/renderer2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,14 @@
import builtins

from vispy import gloo
from vispy.gloo import FrameBuffer
from vispy.gloo import IndexBuffer
from vispy.gloo import Program
from vispy.gloo import Texture2D
from vispy.gloo import VertexBuffer

from contextlib import contextmanager

from .shaders2d import src_default
from .shaders2d import src_fbuffer
from .shaders2d import src_texture
from .shaders2d import src_line
from .openglrenderer import OpenGLRenderer

from OpenGL.GLU import gluTessBeginPolygon, gluTessBeginContour, gluTessEndPolygon, gluTessEndContour, gluTessVertex

Expand Down Expand Up @@ -216,83 +212,17 @@ def get_render_primitives(shape):
render_primitives.extend(_get_borders(shape))
return render_primitives

class Renderer2D:
class Renderer2D(OpenGLRenderer):
def __init__(self):
self.default_prog = None
self.fbuffer_prog = None
super().__init__()
self.texture_prog = None
self.line_prog = None

self.fbuffer = None
self.fbuffer_tex_front = None
self.fbuffer_tex_back = None

self.vertex_buffer = None
self.index_buffer = None

## Renderer Globals: USEFUL CONSTANTS
self.COLOR_WHITE = (1, 1, 1, 1)
self.COLOR_BLACK = (0, 0, 0, 1)
self.COLOR_DEFAULT_BG = (0.8, 0.8, 0.8, 1.0)

## Renderer Globals: STYLE/MATERIAL PROPERTIES
##
self.background_color = self.COLOR_DEFAULT_BG

self.fill_color = self.COLOR_WHITE
self.fill_enabled = True

self.stroke_color = self.COLOR_BLACK
self.stroke_enabled = True

self.tint_color = self.COLOR_BLACK
self.tint_enabled = False

## Renderer Globals: Curves
self.stroke_weight = 1
self.stroke_cap = 2
self.stroke_join = 0

## Renderer Globals
## VIEW MATRICES, ETC
##
self.viewport = None
self.texture_viewport = None
self.transform_matrix = np.identity(4)
self.modelview_matrix = np.identity(4)
self.projection_matrix = np.identity(4)

## Renderer Globals: RENDERING
self.draw_queue = []

def initialize_renderer(self):
self.fbuffer = FrameBuffer()

vertices = np.array([[-1.0, -1.0],
[+1.0, -1.0],
[-1.0, +1.0],
[+1.0, +1.0]],
np.float32)
texcoords = np.array([[0.0, 0.0],
[1.0, 0.0],
[0.0, 1.0],
[1.0, 1.0]],
dtype=np.float32)

self.fbuf_vertices = VertexBuffer(data=vertices)
self.fbuf_texcoords = VertexBuffer(data=texcoords)

self.fbuffer_prog = Program(src_fbuffer.vert, src_fbuffer.frag)
self.fbuffer_prog['texcoord'] = self.fbuf_texcoords
self.fbuffer_prog['position'] = self.fbuf_vertices

self.vertex_buffer = VertexBuffer()
self.index_buffer = IndexBuffer()

self.default_prog = Program(src_default.vert, src_default.frag)
super().initialize_renderer()
self.texture_prog = Program(src_texture.vert, src_texture.frag)
self.texture_prog['texcoord'] = self.fbuf_texcoords

self.reset_view()

def reset_view(self):
Expand Down Expand Up @@ -389,10 +319,6 @@ def draw_loop(self):

self.fbuffer_tex_front, self.fbuffer_tex_back = self.fbuffer_tex_back, self.fbuffer_tex_front


def _transform_vertices(self, vertices, local_matrix, global_matrix):
return np.dot(np.dot(vertices, local_matrix.T), global_matrix.T)[:, :3]

def _add_to_draw_queue_simple(self, stype, vertices, idx, fill, stroke, stroke_weight, stroke_cap, stroke_join):
"""Adds shape of stype to draw queue
"""
Expand Down Expand Up @@ -436,52 +362,6 @@ def flush_geometry(self):

self.draw_queue = []

def render_default(self, draw_type, draw_queue):
# 1. Get the maximum number of vertices persent in the shapes
# in the draw queue.
#
if len(draw_queue) == 0:
return

num_vertices = 0
for vertices, _, _ in draw_queue:
num_vertices = num_vertices + len(vertices)

# 2. Create empty buffers based on the number of vertices.
#
data = np.zeros(num_vertices,
dtype=[('position', np.float32, 3),
('color', np.float32, 4)])

# 3. Loop through all the shapes in the geometry queue adding
# it's information to the buffer.
#
sidx = 0
draw_indices = []
for vertices, idx, color in draw_queue:
num_shape_verts = len(vertices)

data['position'][sidx:(sidx + num_shape_verts),] = vertices

color_array = np.array([color] * num_shape_verts)
data['color'][sidx:sidx + num_shape_verts, :] = color_array

draw_indices.append(sidx + idx)

sidx += num_shape_verts

self.vertex_buffer.set_data(data)
self.index_buffer.set_data(np.hstack(draw_indices))

# 4. Bind the buffer to the shader.
#
self.default_prog.bind(self.vertex_buffer)

# 5. Draw the shape using the proper shape type and get rid of
# the buffers.
#
self.default_prog.draw(draw_type, indices=self.index_buffer)

def render_line(self, queue):
'''
This rendering algorithm works by tesselating the line into
Expand Down Expand Up @@ -604,8 +484,6 @@ def cleanup(self):
program is about to exit.
"""
self.default_prog.delete()
self.fbuffer_prog.delete()
OpenGLRenderer.cleanup()
self.line_prog.delete()
self.fbuffer.delete()

Loading

0 comments on commit baac189

Please sign in to comment.