Skip to content

Commit f11b09c

Browse files
committed
Texture renderer (render to texture version)
1 parent 86670e8 commit f11b09c

File tree

7 files changed

+435
-17
lines changed

7 files changed

+435
-17
lines changed

demosys/text/base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,10 @@ def __init__(self, meta):
5555
self.character_width = self._meta['character_width']
5656
self.atlas_height = self._meta['atlas_height']
5757
self.atlas_width = self._meta['atlas_width']
58+
59+
@property
60+
def char_aspect_wh(self):
61+
return self.character_width / self.character_height
62+
63+
def char_aspect_hw(self):
64+
return self.character_height / self.character_width

demosys/text/renderer2d.py

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,65 @@
1+
import numpy
2+
3+
import moderngl
4+
from demosys.opengl import FBO, VAO
15
from demosys.resources import shaders
2-
from .base import BaseText
6+
7+
from .writer2d import TextWriter2D
38

49

5-
class TextRenderer2D(BaseText):
10+
class TextRenderer2D(TextWriter2D):
611

7-
def __init__(self, area, size=0.1, text=""):
12+
def __init__(self, area, text_lines=None, texture_height=64):
813
"""
914
:param area: (x, y) Text area size (number of characters)
1015
:param size: Text size
1116
:param text: Initial text
1217
"""
13-
super().__init__(text)
14-
self.area = area
15-
self.size = size
16-
self._text = text
18+
super().__init__(area, text_lines=text_lines)
19+
self._texture_height = texture_height
20+
self._texture_width = 0
21+
22+
self._quad = self._create_vao()
23+
# self._quad = geometry.quad_fs()
24+
self._quad_shader = shaders.get('demosys/text/view_renderer_texture.glsl', create=True)
25+
self._fbo = None
1726

18-
self.fbo = None
19-
self.vao = None
20-
self.shader = shaders.get('demosys/text/textwriter.glsl', create=True)
27+
def _post_load(self):
28+
super()._post_load()
29+
self._texture_width = int(
30+
round(self._meta.char_aspect_wh * self._texture_height * self.area[0] / self.area[1], 0)
31+
)
32+
33+
self.aspect_ratio = self._texture_width / self._texture_height
34+
self._fbo = FBO.create((self._texture_width, self._texture_height))
2135

2236
@property
23-
def text(self):
24-
return self._text
37+
def texture(self):
38+
return self._fbo.color_buffers[0]
39+
40+
def render(self):
41+
self._fbo.clear()
42+
with self._fbo:
43+
super().draw((0.0, 0.0), size=2.0 / self.area[1])
44+
45+
def draw(self, pos, size=1.0):
46+
self._fbo.color_buffers[0].use(location=0)
47+
self._quad_shader.uniform("texture0", 0)
48+
self._quad_shader.uniform("yscale", self._texture_height / self._texture_width)
49+
self._quad_shader.uniform("pos", pos)
50+
self._quad_shader.uniform("size", size)
51+
self._quad.draw(self._quad_shader)
2552

26-
@text.setter
27-
def text(self, value):
28-
self._text = value
53+
def _create_vao(self):
54+
data = numpy.array([
55+
0.0, -2.0, 0.0, 0.0, 0.0,
56+
0.0, 0.0, 0.0, 0.0, 1.0,
57+
2.0, 0.0, 0.0, 1.0, 1.0,
58+
0.0, -2.0, 0.0, 0.0, 0.0,
59+
2.0, 0.0, 0.0, 1.0, 1.0,
60+
2.0, -2.0, 0.0, 1.0, 0.0,
61+
], dtype=numpy.float32)
2962

30-
def draw(self):
31-
pass
63+
vao = VAO("textrenderer", mode=moderngl.TRIANGLES)
64+
vao.buffer(data, '3f 2f', ['in_position', 'in_uv'])
65+
return vao
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#version 330
2+
3+
#if defined VERTEX_SHADER
4+
5+
in vec3 in_position;
6+
in vec2 in_uv;
7+
8+
uniform vec2 pos;
9+
uniform float size;
10+
uniform float yscale;
11+
12+
out vec2 uv;
13+
//
14+
void main() {
15+
vec3 p = vec3(
16+
(in_position.x * size) - 1.0 + pos[0],
17+
(in_position.y * size) * yscale * 2.0 + 1.0 + pos[1],
18+
0.0
19+
);
20+
gl_Position = vec4(p, 1.0);
21+
uv = in_uv;
22+
}
23+
24+
#elif defined FRAGMENT_SHADER
25+
26+
out vec4 fragColor;
27+
uniform sampler2D texture0;
28+
in vec2 uv;
29+
30+
void main() {
31+
fragColor = texture(texture0, uv);
32+
}
33+
34+
#endif

examples/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,16 @@ python manage.py runeffect examples.textwriter
5858
```
5959

6060
![screenshot](https://raw.githubusercontent.com/Contraz/demosys-py/master/examples/images/textwriter.png)
61+
62+
Text Renderer
63+
-------------
64+
65+
Example loading a text file displaying it on the screen. The text is rendered to a texture at initialization.
66+
We simply display the texture each frame. We are limiting the texture height to 8k in this example.
67+
68+
```bash
69+
python manage.py runeffect examples.textrenderer
70+
```
71+
72+
![screenshot](https://raw.githubusercontent.com/Contraz/demosys-py/master/examples/images/textrenderer.png)
73+

examples/images/textrenderer.png

743 KB
Loading

examples/textrenderer/effect.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import math
2+
import os
3+
4+
from demosys.effects import effect
5+
from demosys.text import TextRenderer2D
6+
7+
8+
class TextEffect(effect.Effect):
9+
10+
def __init__(self):
11+
super().__init__()
12+
13+
with open(os.path.join(os.path.dirname(__file__), 'sample.txt'), 'r') as fd:
14+
lines = fd.readlines()
15+
16+
self.renderer = TextRenderer2D(
17+
(105, len(lines)),
18+
text_lines=lines,
19+
texture_height=8192,
20+
)
21+
22+
def post_load(self):
23+
self.renderer.render()
24+
25+
@effect.bind_target
26+
def draw(self, time, frametime, target):
27+
self.renderer.draw(
28+
(0.05, math.fmod(time, 75.0) / 5.0),
29+
size=0.75,
30+
)

0 commit comments

Comments
 (0)