OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Text.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "Text.h"
22 #include "Skybox.h"
23 
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 
28 namespace Skybox
29 {
30  const char Text::textureFilename[] = "font.raw";
31 
32  const float Text::scale = 1.0f;
33 
34  const int Text::textureCharacterWidth = 8;
35  const int Text::textureCharacterHeight = 16;
36 
37  /* Please see header for specification. */
38  void loadData(const char* filename, unsigned char** textureData)
39  {
40  LOGI("Texture loadData started for %s...\n", filename);
41 
42  FILE* file = fopen(filename, "rb");
43 
44  if (file == NULL)
45  {
46  LOGE("Failed to open '%s'\n", filename);
47  exit(EXIT_FAILURE);
48  }
49 
50  fseek(file, 0, SEEK_END);
51 
52  unsigned int length = ftell(file);
53  unsigned char* loadedTexture = NULL;
54 
55  MALLOC_CHECK(unsigned char*, loadedTexture, length);
56 
57  fseek(file, 0, SEEK_SET);
58 
59  size_t read = fread(loadedTexture, sizeof(unsigned char), length, file);
60 
61  if (read != length)
62  {
63  LOGE("Failed to read in '%s'\n", filename);
64  exit(EXIT_FAILURE);
65  }
66 
67  fclose(file);
68 
69  *textureData = loadedTexture;
70  }
71 
72  /* Please see header for specification. */
73  GLint get_and_check_attrib_location(GLuint program, const GLchar* attrib_name)
74  {
75  GLint attrib_location = GL_CHECK(glGetAttribLocation(program, attrib_name));
76 
77  if (attrib_location == -1)
78  {
79  LOGE("Cannot retrieve location of %s attribute.\n", attrib_name);
80  exit(EXIT_FAILURE);
81  }
82 
83  return attrib_location;
84  }
85 
86  /* Please see header for specification. */
87  GLint get_and_check_uniform_location(GLuint program, const GLchar* uniform_name)
88  {
89  GLint uniform_location = GL_CHECK(glGetUniformLocation(program, uniform_name));
90 
91  if (uniform_location == -1)
92  {
93  LOGE("Cannot retrieve location of %s uniform.\n", uniform_name);
94  exit(EXIT_FAILURE);
95  }
96 
97  return uniform_location;
98  }
99 
100  /* Please see header for specification. */
102  {
103  vertexShaderID = 0;
104  fragmentShaderID = 0;
105  programID = 0;
106  numberOfCharacters = 0;
107 
108  textVertex = NULL;
109  textTextureCoordinates = NULL;
110  color = NULL;
111  textIndex = NULL;
112 
113  /* Create an orthographic projection. */
114  projectionMatrix = Matrix::matrixOrthographic(0, (float)windowWidth, 0, (float)windowHeight, 0, 1);
115 
116  /* Set up shaders. */
118 
119  GL_CHECK(glUseProgram(programID));
120 
121  /* Vertex positions. */
123 
124  /* Text colors. */
126 
127  /* TexCoords. */
129 
130  /* Projection matrix. */
132 
133  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
134 
135  /* Set the sampler to point at the 0th texture unit. */
137 
138  GL_CHECK(glUniform1i(m_iLocTexture, 0));
139 
140  /* Load texture. */
141  GL_CHECK(glActiveTexture(GL_TEXTURE0));
142  GL_CHECK(glGenTextures(1, &textureID));
143  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
144 
145  /* Set filtering. */
146  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
147  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
148  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
149  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
150 
151  const int textureLength = strlen(resourceDirectory) + strlen(textureFilename);
152  char* texture = NULL;
153 
154  MALLOC_CHECK(char*, texture, textureLength);
155  strcpy(texture, resourceDirectory);
156  strcat(texture, textureFilename);
157 
158  unsigned char* textureData = NULL;
159 
160  loadData(texture, &textureData);
161 
162  FREE_CHECK(texture);
163 
164  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 48, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData));
165 
166  FREE_CHECK(textureData);
167  }
168 
169  /* Please see header for specification. */
170  void Text::clear(void)
171  {
172  numberOfCharacters = 0;
173 
176  FREE_CHECK(color);
178  }
179 
180  /* Please see header for specification. */
181  void Text::addString(int xPosition, int yPosition, const char* string, int red, int green, int blue, int alpha)
182  {
183  int length = (int)strlen(string);
184  int iTexCoordPos = 4 * 2 * numberOfCharacters;
185  int iVertexPos = 4 * 3 * numberOfCharacters;
186  int iColorPos = 4 * 4 * numberOfCharacters;
187  int iIndex = 0;
188  int iIndexPos = 0;
189 
191 
192  /* Realloc memory. */
193  REALLOC_CHECK(float*, textVertex, numberOfCharacters * 4 * 3 * sizeof(float));
194  REALLOC_CHECK(float*, textTextureCoordinates, numberOfCharacters * 4 * 2 * sizeof(float));
195  REALLOC_CHECK(float*, color, numberOfCharacters * 4 * 4 * sizeof(float));
196  REALLOC_CHECK(GLshort*, textIndex, (numberOfCharacters * 6 - 2) * sizeof(GLshort));
197 
198  /* Re-init entire index array. */
199  textIndex[iIndex++] = 0;
200  textIndex[iIndex++] = 1;
201  textIndex[iIndex++] = 2;
202  textIndex[iIndex++] = 3;
203 
204  iIndexPos = 4;
205  for (int cIndex = 1; cIndex < numberOfCharacters; cIndex ++)
206  {
207  textIndex[iIndexPos++] = iIndex - 1;
208  textIndex[iIndexPos++] = iIndex;
209  textIndex[iIndexPos++] = iIndex++;
210  textIndex[iIndexPos++] = iIndex++;
211  textIndex[iIndexPos++] = iIndex++;
212  textIndex[iIndexPos++] = iIndex++;
213  }
214 
215  for (int iChar = 0; iChar < (signed int)strlen(string); iChar ++)
216  {
217  char cChar = string[iChar];
218  int iCharX = 0;
219  int iCharY = 0;
220  Vec2 sBottom_left;
221  Vec2 sBottom_right;
222  Vec2 sTop_left;
223  Vec2 sTop_right;
224 
225  /* Calculate tex coord for char here. */
226  cChar -= 32;
227  iCharX = cChar % 32;
228  iCharY = cChar / 32;
229  iCharX *= textureCharacterWidth;
230  iCharY *= textureCharacterHeight;
231  sBottom_left.x = iCharX;
232  sBottom_left.y = iCharY;
233  sBottom_right.x = iCharX + textureCharacterWidth;
234  sBottom_right.y = iCharY;
235  sTop_left.x = iCharX;
236  sTop_left.y = iCharY + textureCharacterHeight;
237  sTop_right.x = iCharX + textureCharacterWidth;
238  sTop_right.y = iCharY + textureCharacterHeight;
239 
240  /* Add vertex position data here. */
241  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
242  textVertex[iVertexPos++] = (float)yPosition;
243  textVertex[iVertexPos++] = 0;
244 
245  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
246  textVertex[iVertexPos++] = (float)yPosition;
247  textVertex[iVertexPos++] = 0;
248 
249  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
250  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
251  textVertex[iVertexPos++] = 0;
252 
253  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
254  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
255  textVertex[iVertexPos++] = 0;
256 
257  /* Texture coords here. Because textures are read in upside down, flip Y coords here. */
258  textTextureCoordinates[iTexCoordPos++] = sBottom_left.x / 256.0f;
259  textTextureCoordinates[iTexCoordPos++] = sTop_left.y / 48.0f;
260 
261  textTextureCoordinates[iTexCoordPos++] = sBottom_right.x / 256.0f;
262  textTextureCoordinates[iTexCoordPos++] = sTop_right.y / 48.0f;
263 
264  textTextureCoordinates[iTexCoordPos++] = sTop_left.x / 256.0f;
265  textTextureCoordinates[iTexCoordPos++] = sBottom_left.y / 48.0f;
266 
267  textTextureCoordinates[iTexCoordPos++] = sTop_right.x / 256.0f;
268  textTextureCoordinates[iTexCoordPos++] = sBottom_right.y / 48.0f;
269 
270  /* Color data. */
271  color[iColorPos++] = red / 255.0f;
272  color[iColorPos++] = green / 255.0f;
273  color[iColorPos++] = blue / 255.0f;
274  color[iColorPos++] = alpha / 255.0f;
275 
276  /* Copy to the other 3 vertices. */
277  memcpy(&color[iColorPos], &color[iColorPos - 4], 4 * sizeof(float));
278  memcpy(&color[iColorPos + 4], &color[iColorPos], 4 * sizeof(float));
279  memcpy(&color[iColorPos + 8], &color[iColorPos + 4], 4 * sizeof(float));
280  iColorPos += 3 * 4;
281  }
282  }
283 
284  /* Please see header for specification. */
285  void Text::draw(void)
286  {
287  /* Push currently bound vertex array object. */
288  GLint vertexArray = 0;
289 
290  GL_CHECK(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vertexArray));
291  GL_CHECK(glBindVertexArray(0));
292  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
293 
294  /* Push currently used program object. */
295  GLint currentProgram = 0;
296 
297  GL_CHECK(glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram));
298 
299  GL_CHECK(glUseProgram(programID));
300 
301  if (m_iLocPosition == -1 || m_iLocTextColor == -1 || m_iLocTexCoord == -1 || m_iLocProjection == -1)
302  {
303  LOGI("At least one of the attributes and/or uniforms is missing. Have you invoked Text(const char*, int, int) constructor?");
304  exit(EXIT_FAILURE);
305  }
306 
307  if (numberOfCharacters == 0)
308  {
309  return;
310  }
311 
312  GL_CHECK(glEnableVertexAttribArray(m_iLocPosition));
313  GL_CHECK(glEnableVertexAttribArray(m_iLocTextColor));
314  GL_CHECK(glEnableVertexAttribArray(m_iLocTexCoord));
315 
316  GL_CHECK(glVertexAttribPointer(m_iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, textVertex));
317  GL_CHECK(glVertexAttribPointer(m_iLocTextColor, 4, GL_FLOAT, GL_FALSE, 0, color));
318  GL_CHECK(glVertexAttribPointer(m_iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, textTextureCoordinates));
319  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
320 
321  GL_CHECK(glActiveTexture(GL_TEXTURE0));
322  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
323 
324  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, numberOfCharacters * 6 - 2, GL_UNSIGNED_SHORT, textIndex));
325 
326  GL_CHECK(glDisableVertexAttribArray(m_iLocTextColor));
327  GL_CHECK(glDisableVertexAttribArray(m_iLocTexCoord));
328  GL_CHECK(glDisableVertexAttribArray(m_iLocPosition));
329 
330  /* Pop previously used program object. */
331  GL_CHECK(glUseProgram(currentProgram));
332 
333  /* Pop previously bound vertex array object. */
334  GL_CHECK(glBindVertexArray(vertexArray));
335  }
336 
337  /* Please see header for specification. */
339  m_iLocPosition(-1),
340  m_iLocProjection(-1),
341  m_iLocTextColor(-1),
342  m_iLocTexCoord(-1),
343  m_iLocTexture(-1),
344  vertexShaderID(0),
345  fragmentShaderID(0),
346  programID(0),
347  textureID(0)
348  {
349  clear();
350  }
351 
352  /* Please see header for specification. */
354  {
355  clear();
356 
357  GL_CHECK(glDeleteTextures(1, &textureID));
358  }
359 }
GLuint create_program(const char *vertex_source, const char *fragment_source)
Create program object, attach vertex and fragment shader to it. Link program object and check whether...
void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Text.cpp:38
#define MALLOC_CHECK(ptr_type, ptr, size)
Definition: AstcTextures.h:33
int windowWidth
Definition: Cube.cpp:56
GLuint textureID
#define LOGI(...)
Definition: AstcTextures.h:29
Matrix projectionMatrix
Definition: Text.h:122
GLint get_and_check_attrib_location(GLuint program, const GLchar *attrib_name)
Invoke glGetAttribLocation(), if it has returned a positive value. Otherwise, print a message and exi...
Definition: Text.cpp:73
static const int textureCharacterHeight
The height (in pixels) of the characters in the text texture.
Definition: Text.h:149
float * textTextureCoordinates
Definition: Text.h:125
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:170
GLuint vertexShaderID
Definition: Text.h:133
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:285
int m_iLocTexCoord
Definition: Text.h:131
int m_iLocProjection
Definition: Text.h:129
GLint get_and_check_uniform_location(GLuint program, const GLchar *uniform_name)
Invoke glGetUniformLocation, if it has returned a positive value. Otherwise, print a message and exit...
Definition: Text.cpp:87
const char fontFragmentShaderSource[]
Fragment shader source code for text rendering.
Definition: Text.h:52
GLuint fragmentShaderID
precision highp int
Definition: hiz_cull.cs:38
~Text(void)
Overloaded default destructor.
Definition: Text.cpp:353
float * color
Definition: Text.h:126
int windowHeight
Definition: Cube.cpp:57
const char fontVertexShaderSource[]
Vertex shader source code for text rendering.
Definition: Text.h:33
int m_iLocTexture
Definition: Text.h:132
int x
Definition: Text.h:97
int m_iLocTextColor
Definition: Text.h:130
int y
Definition: Text.h:98
int m_iLocPosition
Definition: Text.h:128
int numberOfCharacters
Definition: Text.h:123
GLuint fragmentShaderID
Definition: Text.h:134
GLuint programID
Definition: AntiAlias.cpp:60
static const int textureCharacterWidth
The width (in pixels) of the characters in the text texture.
Definition: Text.h:143
static Matrix matrixOrthographic(float left, float right, float bottom, float top, float zNear, float zFar)
Create and return an orthographic projection matrix.
Definition: Matrix.cpp:69
#define GL_CHECK(x)
Definition: AstcTextures.h:59
static const char textureFilename[]
Definition: Text.h:110
unsigned char * textureData
Definition: ThreadSync.cpp:109
GLenum GLuint texture
Definition: gl2ext.h:385
string resourceDirectory
Definition: AntiAlias.cpp:55
#define REALLOC_CHECK(ptr_type, ptr, size)
Definition: AstcTextures.h:43
float * textVertex
Definition: Text.h:124
Type representing texture coordinates.
Definition: Text.h:95
Text(void)
Overloaded default constructor.
Definition: Text.cpp:338
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
GLuint vertexShaderID
static const float scale
Scaling factor to use when rendering the text.
Definition: Text.h:120
#define LOGE(...)
Definition: AstcTextures.h:30
precision highp float
Definition: hiz_cull.cs:37
#define FREE_CHECK(ptr)
Definition: AstcTextures.h:53
GLuint program
Definition: gl2ext.h:1475
GLuint textureID
Definition: Text.h:136
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:52
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
GLuint programID
Definition: Text.h:135
GLshort * textIndex
Definition: Text.h:127
void addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
Add a std::string to be drawn to the screen.
Definition: Text.cpp:181