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