Skip to content

Commit 4ca1981

Browse files
authored
Merge branch 'master' into samplers
2 parents 9c721c0 + fa87d73 commit 4ca1981

File tree

12 files changed

+208
-98
lines changed

12 files changed

+208
-98
lines changed

demosys/context/base.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
import moderngl
55
from demosys.conf import settings
6-
from demosys.opengl.fbo import WindowFBO
7-
from demosys import context
86

97
GLVersion = namedtuple('GLVersion', ['major', 'minor'])
108

@@ -38,41 +36,41 @@ def __init__(self):
3836
self.vsync = settings.WINDOW.get('vsync')
3937
self.cursor = settings.WINDOW.get('cursor')
4038

41-
self._calc_viewport()
39+
self.clear_color = (0.0, 0.0, 0.0, 0.0)
40+
self.clear_depth = (1.0)
4241

4342
# ModernGL context
4443
self.ctx = None
4544

46-
WindowFBO.window = self
47-
self.fbo = WindowFBO
48-
context.WINDOW = self
49-
5045
def draw(self, current_time, frame_time):
51-
self.manager.draw(current_time, frame_time, WindowFBO)
46+
self.set_default_viewport()
47+
self.manager.draw(current_time, frame_time, self.fbo)
5248

5349
def clear(self):
5450
"""Clear the scren"""
55-
self.ctx.clear(
56-
red=0.0, blue=0.0, green=0.0, alpha=0.0, depth=1.0,
57-
viewport=self._viewport,
51+
self.ctx.screen.clear(
52+
red=self.clear_color[0],
53+
green=self.clear_color[1],
54+
blue=self.clear_color[2],
55+
alpha=self.clear_color[3],
56+
depth=self.clear_depth,
5857
)
5958

59+
def clear_values(self, red=0.0, green=0.0, blue=0.0, alpha=0.0, depth=1.0):
60+
self.clear_color = (red, green, blue, alpha)
61+
self.clear_depth = depth
62+
6063
def use(self):
6164
"""Render to this window"""
6265
raise NotImplementedError()
6366

64-
def viewport(self):
65-
self.ctx.viewport = self._viewport
66-
6767
def swap_buffers(self):
6868
"""Swap frame buffer"""
6969
raise NotImplementedError()
7070

7171
def resize(self, width, height):
7272
"""Resize window"""
73-
self.width = width
74-
self.height = height
75-
self._calc_viewport()
73+
self.set_default_viewport()
7674

7775
def close(self):
7876
"""Set the close state"""
@@ -87,8 +85,7 @@ def terminate(self):
8785
raise NotImplementedError()
8886

8987
def mgl_fbo(self):
90-
"""Returns the ModernGL fbo used by this window"""
91-
raise NotImplementedError()
88+
return self.ctx.screen
9289

9390
def print_context_info(self):
9491
"""Prints out context info"""
@@ -101,11 +98,11 @@ def print_context_info(self):
10198
print('platform:', sys.platform)
10299
print('code:', self.ctx.version_code)
103100

104-
def _calc_viewport(self):
101+
def set_default_viewport(self):
105102
"""Calculate viewport with correct aspect ratio"""
106103
# The expected height with the current viewport width
107104
expected_height = int(self.buffer_width / self.aspect_ratio)
108105

109106
# How much positive or negative y padding
110107
blank_space = self.buffer_height - expected_height
111-
self._viewport = (0, blank_space // 2, self.buffer_width, expected_height)
108+
self.ctx.screen.viewport = (0, blank_space // 2, self.buffer_width, expected_height)

demosys/context/glfw.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import moderngl
44
from demosys.scene import camera
55
from demosys.view import screenshot
6-
6+
from demosys.opengl import FBO
7+
from demosys import context
78
from .base import Window
89

910

@@ -50,7 +51,6 @@ def __init__(self):
5051
self.buffer_width, self.buffer_height = glfw.get_framebuffer_size(self.window)
5152
print("Frame buffer size:", self.buffer_width, self.buffer_height)
5253
print("Actual window size:", glfw.get_window_size(self.window))
53-
self._calc_viewport()
5454

5555
glfw.make_context_current(self.window)
5656

@@ -65,6 +65,11 @@ def __init__(self):
6565

6666
# Create mederngl context from existing context
6767
self.ctx = moderngl.create_context()
68+
self.fbo = FBO()
69+
self.fbo.fbo = self.ctx.screen
70+
self.fbo.default_framebuffer = True
71+
context.WINDOW = self
72+
self.set_default_viewport()
6873

6974
def use(self):
7075
self.ctx.screen.use()
@@ -90,9 +95,6 @@ def resize(self, width, height):
9095
def terminate(self):
9196
glfw.terminate()
9297

93-
def mgl_fbo(self):
94-
return self.ctx.screen
95-
9698
def poll_events(self):
9799
"""Poll events from glfw"""
98100
glfw.poll_events()
@@ -106,7 +108,7 @@ def check_glfw_version(self):
106108
def key_event_callback(self, window, key, scancode, action, mods):
107109
"""
108110
Key event callback for glfw
109-
s
111+
110112
:param window: Window event origin
111113
:param key: The keyboard key that was pressed or released.
112114
:param scancode: The system-specific scancode of the key.

demosys/opengl/fbo.py

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,6 @@
44
from demosys.opengl import DepthTexture, Texture2D
55

66

7-
class WindowFBO:
8-
window = None
9-
10-
@classmethod
11-
def use(cls):
12-
"""Sets the viewport back to the buffer size of the screen/window"""
13-
cls.window.use()
14-
cls.window.viewport()
15-
16-
@classmethod
17-
def release(cls):
18-
"""Dummy release method"""
19-
pass
20-
21-
@classmethod
22-
def clear(cls):
23-
"""Dummy clear method"""
24-
cls.window.clear()
25-
26-
@property
27-
@classmethod
28-
def mglo(cls):
29-
"""Internal ModernGL fbo"""
30-
return cls.window.mgl_fbo()
31-
32-
337
class FBO:
348
"""
359
A framebuffer object is a collection of buffers that can be used as the destination for rendering.
@@ -41,9 +15,11 @@ class FBO:
4115
_stack = []
4216

4317
def __init__(self):
18+
self._window = context.window()
4419
self.color_buffers = []
4520
self.depth_buffer = None
4621
self.fbo = None
22+
self.default_framebuffer = False
4723

4824
@staticmethod
4925
def create_from_textures(color_buffers: List[Texture2D], depth_buffer: DepthTexture = None) -> 'FBO':
@@ -169,7 +145,8 @@ def use(self, stack=True):
169145
if not stack:
170146
return
171147

172-
FBO._stack.append(self)
148+
if not self.default_framebuffer:
149+
FBO._stack.append(self)
173150

174151
if len(FBO._stack) > 8:
175152
raise FBOError("FBO stack overflow. You probably forgot to release a bind somewhere.")
@@ -180,8 +157,11 @@ def release(self, stack=True):
180157
181158
:param stack: (bool) If the bind should be popped form the FBO stack.
182159
"""
160+
if self.default_framebuffer:
161+
return
162+
183163
if not stack:
184-
WindowFBO.use()
164+
self._window.fbo.use()
185165
return
186166

187167
# Are we trying to release an FBO that is not bound?
@@ -198,7 +178,7 @@ def release(self, stack=True):
198178
if FBO._stack:
199179
parent = FBO._stack[-1]
200180
else:
201-
parent = WindowFBO
181+
parent = self._window.fbo
202182

203183
# Bind the parent FBO
204184
if parent:
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#version 330
2+
3+
#if defined VERTEX_SHADER
4+
5+
in vec3 in_position;
6+
in uint in_char_id;
7+
8+
uniform vec2 char_size;
9+
10+
out uint vs_char_id;
11+
12+
void main() {
13+
gl_Position = vec4(in_position + vec3(gl_InstanceID * char_size.x, 0.0, 0.0), 1.0);
14+
vs_char_id = in_char_id;
15+
}
16+
17+
#elif defined GEOMETRY_SHADER
18+
19+
layout (points) in;
20+
layout (triangle_strip, max_vertices = 4) out;
21+
22+
uniform mat4 m_proj;
23+
uniform vec2 text_pos;
24+
uniform vec2 char_size;
25+
26+
in uint vs_char_id[1];
27+
out vec2 uv;
28+
flat out uint gs_char_id;
29+
30+
void main() {
31+
vec3 pos = gl_in[0].gl_Position.xyz + vec3(text_pos, 0.0);
32+
33+
vec3 right = vec3(1.0, 0.0, 0.0) * char_size.x / 2.0;
34+
vec3 up = vec3(0.0, 1.0, 0.0) * char_size.y / 2.0;
35+
36+
// upper right
37+
uv = vec2(1.0, 1.0);
38+
gs_char_id = vs_char_id[0];
39+
gl_Position = m_proj * vec4(pos + (right + up), 1.0);
40+
EmitVertex();
41+
42+
// upper left
43+
uv = vec2(0.0, 1.0);
44+
gs_char_id = vs_char_id[0];
45+
gl_Position = m_proj * vec4(pos + (-right + up), 1.0);
46+
EmitVertex();
47+
48+
// lower right
49+
uv = vec2(1.0, 0.0);
50+
gs_char_id = vs_char_id[0];
51+
gl_Position = m_proj * vec4(pos + (right - up), 1.0);
52+
EmitVertex();
53+
54+
// lower left
55+
uv = vec2(0.0, 0.0);
56+
gs_char_id = vs_char_id[0];
57+
gl_Position = m_proj * vec4(pos + (-right - up), 1.0);
58+
EmitVertex();
59+
60+
EndPrimitive();
61+
}
62+
63+
#elif defined FRAGMENT_SHADER
64+
65+
out vec4 fragColor;
66+
uniform sampler2DArray font_texture;
67+
in vec2 uv;
68+
flat in uint gs_char_id;
69+
70+
void main()
71+
{
72+
fragColor = texture(font_texture, vec3(uv, gs_char_id));
73+
}
74+
#endif

demosys/text/resources/shaders/demosys/text/textwriter.glsl renamed to demosys/text/resources/shaders/demosys/text/textwriter3d.glsl

File renamed without changes.

demosys/text/writer2d.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
import numpy
2+
23
import moderngl
3-
from demosys.opengl import VAO
4+
from demosys.opengl import VAO, TextureArray
45
from demosys.resources import data, shaders, textures
5-
from demosys.opengl import TextureArray
6+
from pyrr import matrix44
67

78
from .base import BaseText, Meta
89

910

1011
class TextWriter2D(BaseText):
1112

12-
def __init__(self, area, size=0.1, text=""):
13+
def __init__(self, area, text="", aspect_ratio=1.0):
1314
"""
1415
:param area: (x, y) Text area size (number of characters)
1516
:param size: Text size
1617
:param text: Initial text
1718
"""
1819
super().__init__()
1920
self.area = area
20-
self.size = size
2121
self._text = text.encode('latin1')
2222

23+
self.projection_bytes = None
24+
self._aspect_ratio = 1.0
25+
self.aspect_ratio = aspect_ratio
26+
2327
self._vao = None
2428
self._texture = textures.get('demosys/text/VeraMono.png', cls=TextureArray, layers=190, create=True)
25-
self._shader = shaders.get('demosys/text/textwriter.glsl', create=True)
29+
self._shader = shaders.get('demosys/text/textwriter2d.glsl', create=True)
2630
self._config = data.get('demosys/text/meta.json', create=True)
2731

2832
data.on_loaded(self._post_load)
@@ -49,11 +53,36 @@ def text(self):
4953
def text(self, value):
5054
self._text = value
5155

52-
def draw(self, proj_matrix, view_matrix):
53-
# print(self._text, self._string_data)
56+
@property
57+
def aspect_ratio(self):
58+
return self._aspect_ratio
59+
60+
@aspect_ratio.setter
61+
def aspect_ratio(self, value):
62+
self._aspect_ratio = value
63+
self.projection_bytes = matrix44.create_orthogonal_projection_matrix(
64+
-self.aspect_ratio, # left
65+
self.aspect_ratio, # right
66+
-1.0, # bottom
67+
1.0, # top
68+
-100.0, # near
69+
100.0, # far
70+
dtype=numpy.float32,
71+
).tobytes()
72+
73+
def draw(self, pos, size=1.0):
74+
csize = (
75+
self._meta.character_width / self._meta.character_height * size,
76+
1.0 * size,
77+
)
78+
cpos = (
79+
pos[0] - self._aspect_ratio + csize[0] / 2,
80+
-pos[1] + 1.0 - csize[1] / 2,
81+
)
82+
5483
self._texture.use(location=0)
55-
self._shader.uniform("m_proj", proj_matrix.astype('f4').tobytes())
56-
self._shader.uniform("m_mv", view_matrix.astype('f4').tobytes())
84+
self._shader.uniform("m_proj", self.projection_bytes)
85+
self._shader.uniform("text_pos", cpos)
5786
self._shader.uniform("font_texture", 0)
58-
self._shader.uniform("char_size", (self._meta.character_width / self._meta.character_height, 1.0))
87+
self._shader.uniform("char_size", csize)
5988
self._vao.draw(self._shader, instances=len(self._string_data))

0 commit comments

Comments
 (0)