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) 2012-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 "Texture.h"
23 #include "Shader.h"
24 #include "Platform.h"
25 #include "VectorTypes.h"
26 #include <stdlib.h>
27 
28 #include <cstring>
29 
30 using std::string;
31 
32 namespace MaliSDK
33 {
34  const string Text::textureFilename = "font.raw";
35  const string Text::vertexShaderFilename = "font.vert";
36  const string Text::fragmentShaderFilename = "font.frag";
37 
38  const float Text::scale = 1.0f;
39 
40  const int Text::textureCharacterWidth = 8;
41  const int Text::textureCharacterHeight = 16;
42 
44  {
45  vertexShaderID = 0;
46  fragmentShaderID = 0;
47  programID = 0;
48 
50  textVertex = NULL;
52  color = NULL;
53  textIndex = NULL;
54 
55  LOGD("Text initialization started...\n");
56 
57  /* Create an orthographic projection. */
58  projectionMatrix = Matrix::matrixOrthographic(0, (float)windowWidth, 0, (float)windowHeight, 0, 1);
59 
60  /* Shaders. */
61  string vertexShader = resourceDirectory + vertexShaderFilename;
62  Shader::processShader(&vertexShaderID, vertexShader.c_str(), GL_VERTEX_SHADER);
63 
64  string fragmentShader = resourceDirectory + fragmentShaderFilename;
65  Shader::processShader(&fragmentShaderID, fragmentShader.c_str(), GL_FRAGMENT_SHADER);
66 
67  /* Set up shaders. */
68  programID = GL_CHECK(glCreateProgram());
69  GL_CHECK(glAttachShader(programID, vertexShaderID));
70  GL_CHECK(glAttachShader(programID, fragmentShaderID));
71  GL_CHECK(glLinkProgram(programID));
72  GL_CHECK(glUseProgram(programID));
73 
74  /* Vertex positions. */
75  m_iLocPosition = GL_CHECK(glGetAttribLocation(programID, "a_v4Position"));
76  if(m_iLocPosition == -1)
77  {
78  LOGE("Attribute not found at %s:%i\n", __FILE__, __LINE__);
79  exit(1);
80  }
81 
82  /* Text colors. */
83  m_iLocTextColor = GL_CHECK(glGetAttribLocation(programID, "a_v4FontColor"));
84  if(m_iLocTextColor == -1)
85  {
86  LOGE("Attribute not found at %s:%i\n", __FILE__, __LINE__);
87  exit(1);
88  }
89 
90  /* TexCoords. */
91  m_iLocTexCoord = GL_CHECK(glGetAttribLocation(programID, "a_v2TexCoord"));
92  if(m_iLocTexCoord == -1)
93  {
94  LOGE("Attribute not found at %s:%i\n", __FILE__, __LINE__);
95  exit(1);
96  }
97 
98  /* Projection matrix. */
99  m_iLocProjection = GL_CHECK(glGetUniformLocation(programID, "u_m4Projection"));
100  if(m_iLocProjection == -1)
101  {
102  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
103  }
104  else
105  {
106  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
107  }
108 
109 
110  /* Set the sampler to point at the 0th texture unit. */
111  m_iLocTexture = GL_CHECK(glGetUniformLocation(programID, "u_s2dTexture"));
112  if(m_iLocTexture == -1)
113  {
114  LOGD("Warning: Uniform not found at %s:%i\n", __FILE__, __LINE__);
115  }
116  else
117  {
118  GL_CHECK(glUniform1i(m_iLocTexture, 0));
119  }
120 
121  /* Load texture. */
122  GL_CHECK(glActiveTexture(GL_TEXTURE0));
123  GL_CHECK(glGenTextures(1, &textureID));
124  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
125  /* Set filtering. */
126  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
127  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
128  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
129  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
130 
131  string texture = resourceDirectory + textureFilename;
132  unsigned char *textureData = NULL;
133  Texture::loadData(texture.c_str(), &textureData);
134 
135  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 48, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData));
136  free(textureData);
137  textureData = NULL;
138 
139  LOGD("Text initialization done.\n");
140  }
141 
142  void Text::clear(void)
143  {
144  numberOfCharacters = 0;
145 
146  free(textVertex);
148  free(color);
149  free(textIndex);
150 
151  textVertex = NULL;
152  textTextureCoordinates = NULL;
153  color = NULL;
154  textIndex = NULL;
155  }
156 
157  void Text::addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
158  {
159  int length = strlen(string);
160  int iTexCoordPos = 4 * 2 * numberOfCharacters;
161  int iVertexPos = 4 * 3 * numberOfCharacters;
162  int iColorPos = 4 * 4 * numberOfCharacters;
163  int iIndex = 0;
164  int iIndexPos = 0;
165 
167 
168  /* Realloc memory. */
169  textVertex = (float *)realloc(textVertex, numberOfCharacters * 4 * 3 * sizeof(float));
170  textTextureCoordinates = (float *)realloc(textTextureCoordinates, numberOfCharacters * 4 * 2 * sizeof(float));
171  color = (float *)realloc(color, numberOfCharacters * 4 * 4 * sizeof(float));
172  textIndex = (GLshort *)realloc(textIndex, (numberOfCharacters * 6 - 2) * sizeof(GLshort));
173  if((textVertex == NULL) || (textTextureCoordinates == NULL) || (color == NULL) || (textIndex == NULL))
174  {
175  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
176  exit(1);
177  }
178 
179  /* Re-init entire index array. */
180  textIndex[iIndex ++] = 0;
181  textIndex[iIndex ++] = 1;
182  textIndex[iIndex ++] = 2;
183  textIndex[iIndex ++] = 3;
184 
185  iIndexPos = 4;
186  for(int cIndex = 1; cIndex < numberOfCharacters; cIndex ++)
187  {
188  textIndex[iIndexPos ++] = iIndex - 1;
189  textIndex[iIndexPos ++] = iIndex;
190  textIndex[iIndexPos ++] = iIndex++;
191  textIndex[iIndexPos ++] = iIndex++;
192  textIndex[iIndexPos ++] = iIndex++;
193  textIndex[iIndexPos ++] = iIndex++;
194  }
195 
196  for(int iChar = 0; iChar < (signed int)strlen(string); iChar ++)
197  {
198  char cChar = string[iChar];
199  int iCharX = 0;
200  int iCharY = 0;
201  Vec2 sBottom_left;
202  Vec2 sBottom_right;
203  Vec2 sTop_left;
204  Vec2 sTop_right;
205 
206  /* Calculate tex coord for char here. */
207  cChar -= 32;
208  iCharX = cChar % 32;
209  iCharY = cChar / 32;
210  iCharX *= textureCharacterWidth;
211  iCharY *= textureCharacterHeight;
212  sBottom_left.x = iCharX;
213  sBottom_left.y = iCharY;
214  sBottom_right.x = iCharX + textureCharacterWidth;
215  sBottom_right.y = iCharY;
216  sTop_left.x = iCharX;
217  sTop_left.y = iCharY + textureCharacterHeight;
218  sTop_right.x = iCharX + textureCharacterWidth;
219  sTop_right.y = iCharY + textureCharacterHeight;
220 
221  /* Add vertex position data here. */
222  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
223  textVertex[iVertexPos++] = (float)yPosition;
224  textVertex[iVertexPos++] = 0;
225 
226  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
227  textVertex[iVertexPos++] = (float)yPosition;
228  textVertex[iVertexPos++] = 0;
229 
230  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
231  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
232  textVertex[iVertexPos++] = 0;
233 
234  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
235  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
236  textVertex[iVertexPos++] = 0;
237 
238  /* Texture coords here. Because textures are read in upside down, flip Y coords here. */
239  textTextureCoordinates[iTexCoordPos++] = sBottom_left.x / 256.0f;
240  textTextureCoordinates[iTexCoordPos++] = sTop_left.y / 48.0f;
241 
242  textTextureCoordinates[iTexCoordPos++] = sBottom_right.x / 256.0f;
243  textTextureCoordinates[iTexCoordPos++] = sTop_right.y / 48.0f;
244 
245  textTextureCoordinates[iTexCoordPos++] = sTop_left.x / 256.0f;
246  textTextureCoordinates[iTexCoordPos++] = sBottom_left.y / 48.0f;
247 
248  textTextureCoordinates[iTexCoordPos++] = sTop_right.x / 256.0f;
249  textTextureCoordinates[iTexCoordPos++] = sBottom_right.y / 48.0f;
250 
251  /* Color data. */
252  color[iColorPos ++] = red / 255.0f;
253  color[iColorPos ++] = green / 255.0f;
254  color[iColorPos ++] = blue / 255.0f;
255  color[iColorPos ++] = alpha / 255.0f;
256 
257  /* Copy to the other 3 vertices. */
258  memcpy(&color[iColorPos], &color[iColorPos - 4], 4 * sizeof(float));
259  memcpy(&color[iColorPos + 4], &color[iColorPos], 4 * sizeof(float));
260  memcpy(&color[iColorPos + 8], &color[iColorPos + 4], 4 * sizeof(float));
261  iColorPos += 3 * 4;
262  }
263  }
264 
265  void Text::draw(void)
266  {
267 #if GLES_VERSION == 3
268  GL_CHECK(glBindVertexArray(0));
269  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
270 #endif
271  if(numberOfCharacters == 0)
272  {
273  return;
274  }
275 
276  GL_CHECK(glUseProgram(programID));
277 
278  if(m_iLocPosition != -1)
279  {
280  GL_CHECK(glEnableVertexAttribArray(m_iLocPosition));
281  GL_CHECK(glVertexAttribPointer(m_iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, textVertex));
282  }
283 
284  if(m_iLocTextColor != -1)
285  {
286  GL_CHECK(glEnableVertexAttribArray(m_iLocTextColor));
287  GL_CHECK(glVertexAttribPointer(m_iLocTextColor, 4, GL_FLOAT, GL_FALSE, 0, color));
288  }
289 
290  if(m_iLocTexCoord != -1)
291  {
292  GL_CHECK(glEnableVertexAttribArray(m_iLocTexCoord));
293  GL_CHECK(glVertexAttribPointer(m_iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, textTextureCoordinates));
294  }
295 
296  if(m_iLocProjection != -1)
297  {
298  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
299  }
300 
301  GL_CHECK(glActiveTexture(GL_TEXTURE0));
302  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
303 
304  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, numberOfCharacters * 6 - 2, GL_UNSIGNED_SHORT, textIndex));
305 
306  if(m_iLocTextColor != -1)
307  {
308  GL_CHECK(glDisableVertexAttribArray(m_iLocTextColor));
309  }
310 
311  if(m_iLocTexCoord != -1)
312  {
313  GL_CHECK(glDisableVertexAttribArray(m_iLocTexCoord));
314  }
315 
316  if(m_iLocPosition != -1)
317  {
318  GL_CHECK(glDisableVertexAttribArray(m_iLocPosition));
319  }
320  }
321 
323  {
324  clear();
325 
326  /*
327  * NOTE FROM http://developer.android.com
328  * Note that when the EGL context is lost, all OpenGL resources associated
329  * with that context will be automatically deleted. You do not need to call
330  * the corresponding "glDelete" methods such as glDeleteTextures to manually
331  * delete these lost resources.
332  */
333  }
334 }
int m_iLocProjection
Definition: Text.h:68
float * textTextureCoordinates
Definition: Text.h:64
int windowWidth
Definition: Cube.cpp:56
int m_iLocTextColor
Definition: Text.h:69
Text(const char *resourceDirectory, int windowWidth, int windowHeight)
Constructor for Text.
Definition: Text.cpp:43
static const std::string textureFilename
Definition: Text.h:47
static const float scale
Scaling factor to use when rendering the text.
Definition: Text.h:57
precision highp int
Definition: hiz_cull.cs:38
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:142
GLshort * textIndex
Definition: Text.h:66
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:483
#define LOGD(...)
Definition: AstcTextures.h:28
int windowHeight
Definition: Cube.cpp:57
float * textVertex
Definition: Text.h:63
A 2D integer vector.
Definition: VectorTypes.h:38
static const std::string vertexShaderFilename
Definition: Text.h:48
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
int numberOfCharacters
Definition: Text.h:62
static const int textureCharacterHeight
The height (in pixels) of the characters in the text texture.
Definition: Text.h:89
virtual ~Text(void)
Default destructor.
Definition: Text.cpp:322
GLuint textureID
Definition: Text.h:75
static const int textureCharacterWidth
The width (in pixels) of the characters in the text texture.
Definition: Text.h:83
float * color
Definition: Text.h:65
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:157
int m_iLocTexCoord
Definition: Text.h:70
GLuint fragmentShaderID
Definition: Text.h:73
#define GL_CHECK(x)
Definition: AstcTextures.h:59
GLuint vertexShaderID
Definition: Text.h:72
unsigned char * textureData
Definition: ThreadSync.cpp:109
GLenum GLuint texture
Definition: gl2ext.h:385
string resourceDirectory
Definition: AntiAlias.cpp:55
static void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Texture.cpp:167
int m_iLocTexture
Definition: Text.h:71
static const std::string fragmentShaderFilename
Definition: Text.h:49
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
int m_iLocPosition
Definition: Text.h:67
#define LOGE(...)
Definition: AstcTextures.h:30
precision highp float
Definition: hiz_cull.cs:37
static void processShader(GLuint *shader, const char *filename, GLint shaderType)
Create shader, load in source, compile, and dump debug as necessary.
Definition: Shader.cpp:29
GLuint programID
Definition: Text.h:74
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:265
Matrix projectionMatrix
Definition: Text.h:61