History

Refactoring and reformatting

Tom Szilagyi committed 6 years ago

Commit fa685731 parent 57c433a5 files · +599 −530Browse files

Showing the changes to src/charvdev.cc (1 of 5 files). Show all

Unified · Split

src/charvdev.cc+316−0
@@ -0,0 +1,316 @@
1+/* This file is part of Zutty.
2+ * Copyright (C) 2020 Tom Szilagyi
3+ *
4+ * This program is free software: you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation, either version 3 of the License, or
7+ * (at your option) any later version.
8+ *
9+ * See the file LICENSE for the full license.
10+ */
11+
12+#include "charvdev.h"
13+
14+#include <iostream>
15+
16+namespace {
17+
18+ static const char *computeShaderSource = R"(#version 310 es
19+
20+layout (local_size_x = 1, local_size_y = 1) in;
21+layout (rgba32f, binding = 0) writeonly lowp uniform image2D imgOut;
22+layout (binding = 1) uniform lowp sampler2D atlas;
23+layout (binding = 2) uniform lowp sampler2D text;
24+uniform lowp ivec2 glyphPixels;
25+
26+void main () {
27+ vec3 color = vec3 (0.85, 0.85, 0.85);
28+
29+ ivec2 charPos = ivec2 (gl_GlobalInvocationID.xy);
30+ ivec4 charData = ivec4 (texelFetch (text, charPos, 0) * 256.0);
31+ ivec2 charCode = charData.xy; // .zw: attrs, colors
32+ ivec2 atlasPos = charCode; // TODO lookup in atlas mapping
33+
34+ for (int j = 0; j < glyphPixels.x; j++) {
35+ for (int k = 0; k < glyphPixels.y; k++) {
36+ ivec2 txCoords = atlasPos * glyphPixels + ivec2 (j, k);
37+ vec4 pixel = vec4 (color * texelFetch (atlas, txCoords, 0).r, 1.0);
38+ ivec2 pxCoords = charPos * glyphPixels + ivec2 (j, k);
39+ imageStore (imgOut, pxCoords, pixel);
40+ }
41+ }
42+}
43+)";
44+
45+ static const char *vertexShaderSource = R"(#version 310 es
46+
47+layout (location = 0) in vec2 pos;
48+layout (location = 1) in lowp vec2 vertexTexCoord;
49+
50+out vec2 texCoord;
51+
52+void main () {
53+ texCoord = vertexTexCoord;
54+ gl_Position = vec4 (pos, 0.0, 1.0);
55+}
56+)";
57+
58+ static const char *fragmentShaderSource = R"(#version 310 es
59+
60+in highp vec2 texCoord;
61+
62+layout (rgba32f, binding = 0) readonly lowp uniform image2D imgOut;
63+
64+uniform highp vec2 viewPixels;
65+
66+layout (location = 0) out lowp vec4 outColor;
67+
68+void main () {
69+ outColor = imageLoad (imgOut, ivec2 (texCoord * viewPixels));
70+}
71+)";
72+
73+
74+ GLuint
75+ createShader (GLuint type, const char* src, const char* name)
76+ {
77+ GLint stat;
78+ GLuint shader = glCreateShader (type);
79+ glShaderSource (shader, 1, &src, nullptr);
80+ glCompileShader (shader);
81+ glGetShaderiv (shader, GL_COMPILE_STATUS, &stat);
82+ if (!stat) {
83+ char log[1000];
84+ GLsizei len;
85+ glGetShaderInfoLog (shader, 1000, &len, log);
86+ std::cerr << "Error compiling " << name << " shader:\n"
87+ << log << std::endl;
88+ exit (1);
89+ }
90+ return shader;
91+ }
92+
93+ void
94+ linkProgram (GLuint program, const char* name)
95+ {
96+ GLint stat;
97+ glLinkProgram (program);
98+ glGetProgramiv (program, GL_LINK_STATUS, &stat);
99+ if (!stat) {
100+ char log[1000];
101+ GLsizei len;
102+ glGetProgramInfoLog (program, 1000, &len, log);
103+ std::cerr << "Error: linking " << name << " program:\n"
104+ << log << std::endl;
105+ exit (1);
106+ }
107+ }
108+
109+ void
110+ setupTexture (GLuint target, GLuint& texture)
111+ {
112+ if (texture)
113+ {
114+ glDeleteTextures (1, &texture);
115+ }
116+ glGenTextures (1, &texture);
117+ glActiveTexture (target);
118+ glBindTexture (GL_TEXTURE_2D, texture);
119+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
120+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
121+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
122+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
123+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
124+ }
125+}
126+
127+namespace zutty {
128+
129+ CharVdev::CharVdev (const std::string& priFontPath,
130+ const std::string& altFontPath)
131+ : fnt (priFontPath)
132+ {
133+ createShaders ();
134+
135+ /*
136+ * Setup draw program
137+ */
138+ glUseProgram (P_draw);
139+
140+ glDisable (GL_CULL_FACE);
141+ glDisable (GL_DEPTH_TEST);
142+ glEnable (GL_BLEND);
143+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
144+ glCheckError ();
145+
146+ static const GLfloat verts[4][2] = {
147+ { -1, 1 },
148+ { 1, 1 },
149+ { -1, -1 },
150+ { 1, -1 }
151+ };
152+ static const GLfloat texCoords[4][2] = {
153+ { 0, 0 },
154+ { 1, 0 },
155+ { 0, 1 },
156+ { 1, 1 }
157+ };
158+ glVertexAttribPointer (A_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
159+ glVertexAttribPointer (A_vertexTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
160+ texCoords);
161+ glCheckError ();
162+
163+ /*
164+ * Setup compute program
165+ */
166+ glUseProgram (P_compute);
167+ glUniform2i (compU_glyphPixels, fnt.getPx (), fnt.getPy ());
168+ glCheckError ();
169+
170+ setupTexture (GL_TEXTURE1, T_atlas);
171+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RED,
172+ fnt.getPx () * fnt.getNx (), fnt.getPy () * fnt.getNy (),
173+ 0, GL_RED, GL_UNSIGNED_BYTE, fnt.getAtlas ());
174+ glCheckError ();
175+ }
176+
177+ CharVdev::~CharVdev ()
178+ {
179+ }
180+
181+ void
182+ CharVdev::resize (uint16_t pxWidth_, uint16_t pxHeight_)
183+ {
184+ if (pxWidth == pxWidth_ && pxHeight == pxHeight_)
185+ return;
186+
187+ pxWidth = pxWidth_;
188+ pxHeight = pxHeight_;
189+ nCols = pxWidth / fnt.getPx ();
190+ nRows = pxHeight / fnt.getPy ();
191+
192+ text_data = std::unique_ptr <uint8_t []> (new uint8_t [4 * nCols * nRows]);
193+ memset (text_data.get (), 0, 4 * nCols * nRows);
194+ for (uint16_t j = 0; j < nRows; ++j)
195+ {
196+ for (uint16_t k = 0; k < nCols; ++k)
197+ {
198+ text_data[4 * (j * nCols + k)] = k > 255 ? 0 : k;
199+ text_data[4 * (j * nCols + k) + 1] = k > 255 ? 0 : j;
200+ text_data[4 * (j * nCols + k) + 2] = 0; // color and
201+ text_data[4 * (j * nCols + k) + 3] = 0; // attributes
202+ }
203+ }
204+
205+ std::cout << "resize to " << pxWidth << " x " << pxHeight
206+ << " pixels, " << nCols << " x " << nRows << " chars"
207+ << std::endl;
208+
209+ GLint viewWidth = nCols * fnt.getPx ();
210+ GLint viewHeight = nRows * fnt.getPy ();
211+ glViewport (0, pxHeight - viewHeight, viewWidth, viewHeight);
212+
213+ glUseProgram (P_draw);
214+
215+ glUniform2f (drawU_viewPixels, (GLfloat)viewWidth, (GLfloat)viewHeight);
216+
217+ glUseProgram (P_compute);
218+
219+ setupTexture (GL_TEXTURE0, T_output);
220+ glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGBA32F, viewWidth, viewHeight);
221+ glBindImageTexture (0, T_output, 0, GL_FALSE, 0, GL_WRITE_ONLY,
222+ GL_RGBA32F);
223+ glCheckError ();
224+
225+ setupTexture (GL_TEXTURE2, T_text);
226+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, nCols, nRows, 0, GL_RGBA,
227+ GL_UNSIGNED_BYTE, text_data.get ());
228+ glCheckError ();
229+ }
230+
231+ void
232+ CharVdev::draw ()
233+ {
234+ {
235+ uint16_t cRow = nRows - 1;
236+ uint16_t cCol = nCols - 1;
237+ uint32_t cnt = ++draw_count;
238+ while (cnt)
239+ {
240+ uint32_t digit = (cnt % 10) + 18;
241+ text_data[4 * (cRow * nCols + cCol)] = digit;
242+ text_data[4 * (cRow * nCols + cCol) + 1] = 0;
243+ cnt /= 10;
244+ --cCol;
245+ }
246+ }
247+
248+ glUseProgram (P_compute);
249+ glActiveTexture (GL_TEXTURE0);
250+ glBindTexture (GL_TEXTURE_2D, T_output);
251+ glActiveTexture (GL_TEXTURE1);
252+ glBindTexture (GL_TEXTURE_2D, T_atlas);
253+ glActiveTexture (GL_TEXTURE2);
254+ glBindTexture (GL_TEXTURE_2D, T_text);
255+ glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, nCols, nRows, GL_RGBA,
256+ GL_UNSIGNED_BYTE, text_data.get ());
257+ glCheckError ();
258+
259+ glDispatchCompute (nCols, nRows, 1);
260+ glMemoryBarrier (GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
261+ glCheckError ();
262+
263+ glUseProgram (P_draw);
264+ glClear (GL_COLOR_BUFFER_BIT);
265+
266+ glActiveTexture (GL_TEXTURE0);
267+ glBindTexture (GL_TEXTURE_2D, T_output);
268+
269+ glEnableVertexAttribArray (A_pos);
270+ glEnableVertexAttribArray (A_vertexTexCoord);
271+ glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
272+ }
273+
274+ // private methods
275+
276+ void
277+ CharVdev::createShaders ()
278+ {
279+ GLuint S_compute, S_fragment, S_vertex;
280+
281+ S_compute = createShader (GL_COMPUTE_SHADER, computeShaderSource,
282+ "compute");
283+ S_fragment = createShader (GL_FRAGMENT_SHADER, fragmentShaderSource,
284+ "fragment");
285+ S_vertex = createShader (GL_VERTEX_SHADER, vertexShaderSource,
286+ "vertex");
287+
288+ P_compute = glCreateProgram ();
289+ glAttachShader (P_compute, S_compute);
290+ linkProgram (P_compute, "compute");
291+ glUseProgram (P_compute);
292+
293+ compU_glyphPixels = glGetUniformLocation (P_compute, "glyphPixels");
294+
295+ std::cout << "compute program:"
296+ << "\n uniform glyphPixels at " << compU_glyphPixels
297+ << std::endl;
298+
299+ P_draw = glCreateProgram ();
300+ glAttachShader (P_draw, S_fragment);
301+ glAttachShader (P_draw, S_vertex);
302+ linkProgram (P_draw, "draw");
303+ glUseProgram (P_draw);
304+
305+ A_pos = glGetAttribLocation (P_draw, "pos");
306+ A_vertexTexCoord = glGetAttribLocation (P_draw, "vertexTexCoord");
307+ drawU_viewPixels = glGetUniformLocation (P_draw, "viewPixels");
308+
309+ std::cout << "draw program:"
310+ << "\n attrib pos at " << A_pos
311+ << "\n attrib vertexTexCoord at " << A_vertexTexCoord
312+ << "\n uniform viewPixels at " << drawU_viewPixels
313+ << std::endl;
314+ }
315+
316+} // namespace zutty

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t