我遇到了Opengl和Opengl ES的问题。我想用png图像纹理制作正方形并在这些正方形前面渲染文本。
我可以使用png图像中的纹理制作正方形,我可以像this example一样从ttf渲染文本,但只有在不同时执行的情况下它才有效。我将尝试更好地解释(示例代码太脏了,因为我从一个软件获得的代码更结构化,更大,而且这个代码只是一个例子):
我有一个带有一个顶点着色器的GLProgram和一个用于纹理方块的片段着色器。我有另一个GLProgram与另一个顶点着色器和另一个片段着色器来制作渲染器文本。
如果我加载所有GL程序并且只绘制每一帧纹理方块,我可以完美地看到它。
如果我在纹理正方形之前或之后绘制渲染器文本(使用他的GL程序)(在绘制正方形之前执行他的glUseProgram)我只能看到屏幕上的纹理文本和用它创建的背景颜色( glClearColor(x.xf,x.xf,x.xf,x.xf)),我看不到纹理方块。
有谁知道代码中的错误在哪里?
现在我将发布着色器和示例源代码:
back.v.glsl:
attribute vec4 g_vPosition;
attribute vec3 g_vColor;
attribute vec2 g_vTexCoord;
varying vec3 g_vVSColor;
varying vec2 g_vVSTexCoord;
void main()
{
gl_Position = g_vPosition;
g_vVSColor = g_vColor;
g_vVSTexCoord = g_vTexCoord;
}
back.f.glsl:
uniform sampler2D s_texture;
varying vec3 g_vVSColor;
varying vec2 g_vVSTexCoord;
void main()
{
gl_FragColor = texture2D(s_texture,g_vVSTexCoord);
}
text.v.glsl:
attribute vec4 coord;
varying vec2 texpos;
void main(void) {
gl_Position = vec4(coord.xy, 0, 1);
texpos = coord.zw;
}
text.f.glsl:
varying vec2 texpos;
uniform sampler2D tex;
uniform vec4 color;
void main(void) {
//gl_FragColor = vec4(1, 1, 1, texture2D(tex, texpos).a) * color;
gl_FragColor = vec4(color.rgb, texture2D(tex, texpos).a);
}
源代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <math.h>
#include <signal.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <unistd.h>
#include <sys/time.h>
#include <png.h>
EGLDisplay egldisplay;
EGLConfig eglconfig;
EGLSurface eglsurface;
EGLContext eglcontext;
EGLNativeWindowType eglNativeWindow;
EGLNativeDisplayType eglNativeDisplayType;
#include <ft2build.h>
#include FT_FREETYPE_H
GLuint program;
GLint attribute_coord;
GLint uniform_tex;
GLint uniform_color;
GLuint programBack;
GLint coordBack = 0;
GLint texBack = 2;
GLint colorBack = 1;
struct point {
GLfloat x;
GLfloat y;
GLfloat s;
GLfloat t;
};
GLuint vbo;
FT_Library ft;
FT_Face face;
// Maximum texture width
#define MAXWIDTH 800
const char *fontfilename;
float VertexColors[] = {
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Red */
1.0f, 0.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
/* Green */
0.0f, 1.0f, 0.0f, 1.0f,
};
float VertexTexCoords[] = {
/* Front Face */
0.0f,0.0f,
1.0f,0.0f,
0.0f,1.0f,
1.0f,1.0f,
};
float fBackgroundPosition[12] = {
/* Bottom Left Of The Quad (Front) */
-1.0f,-1.0f,1.0f,
/* Bottom Right Of The Quad (Front) */
1.0f,-1.0f,1.0f,
/* Top Left Of The Quad (Front) */
-1.0f,1.0f,1.0f,
/* Top Right Of The Quad (Front) */
1.0f,1.0f,1.0f,
};
GLuint glTextures[4];
/**
* The atlas struct holds a texture that contains the visible US-ASCII characters
* of a certain font rendered with a certain character height.
* It also contains an array that contains all the information necessary to
* generate the appropriate vertex and texture coordinates for each character.
*
* After the constructor is run, you don't need to use any FreeType functions anymore.
*/
struct atlas {
GLuint tex; // texture object
unsigned int w; // width of texture in pixels
unsigned int h; // height of texture in pixels
struct {
float ax; // advance.x
float ay; // advance.y
float bw; // bitmap.width;
float bh; // bitmap.height;
float bl; // bitmap_left;
float bt; // bitmap_top;
float tx; // x offset of glyph in texture coordinates
float ty; // y offset of glyph in texture coordinates
} c[256]; // character information
atlas(FT_Face face, int height) {
FT_Set_Pixel_Sizes(face, 0, height);
FT_GlyphSlot g = face->glyph;
unsigned int roww = 0;
unsigned int rowh = 0;
w = 0;
h = 0;
memset(c, 0, sizeof c);
/* Find minimum size for a texture holding all visible ASCII characters */
//for (int i = 32; i < 128; i++) {
for (int i = 32; i < 254; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed!\n", i);
continue;
}
if (roww + g->bitmap.width + 1 >= MAXWIDTH) {
w = std::max(w, roww);
h += rowh;
roww = 0;
rowh = 0;
}
roww += g->bitmap.width + 1;
rowh = std::max(rowh, g->bitmap.rows);
}
w = std::max(w, roww);
h += rowh;
/* Create a texture that will be used to hold all ASCII glyphs */
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_tex, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Paste all glyph bitmaps into the texture, remembering the offset */
int ox = 0;
int oy = 0;
rowh = 0;
//for (int i = 32; i < 128; i++) {
for (int i = 32; i < 254; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed!\n", i);
continue;
}
if (ox + g->bitmap.width + 1 >= MAXWIDTH) {
oy += rowh;
rowh = 0;
ox = 0;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
c[i].ax = g->advance.x >> 6;
c[i].ay = g->advance.y >> 6;
c[i].bw = g->bitmap.width;
c[i].bh = g->bitmap.rows;
c[i].bl = g->bitmap_left;
c[i].bt = g->bitmap_top;
c[i].tx = ox / (float)w;
c[i].ty = oy / (float)h;
rowh = std::max(rowh, g->bitmap.rows);
ox += g->bitmap.width + 1;
}
fprintf(stderr, "Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024);
}
~atlas() {
glDeleteTextures(1, &tex);
}
};
atlas *a48;
atlas *a24;
atlas *a12;
//#define GL_ES_VERSION_2_0
/**
* Store all the file's contents in memory, useful to pass shaders
* source code to OpenGL
*/
char* file_read(const char* filename)
{
FILE* in = fopen(filename, "rb");
if (in == NULL) return NULL;
int res_size = BUFSIZ;
char* res = (char*)malloc(res_size);
int nb_read_total = 0;
while (!feof(in) && !ferror(in)) {
if (nb_read_total + BUFSIZ > res_size) {
if (res_size > 10 * 1024 * 1024) break;
res_size = res_size * 2;
res = (char*)realloc(res, res_size);
}
char* p_res = res + nb_read_total;
nb_read_total += fread(p_res, 1, BUFSIZ, in);
}
fclose(in);
res = (char*)realloc(res, nb_read_total + 1);
res[nb_read_total] = '\0';
return res;
}
/**
* Compile the shader from file 'filename', with error handling
*/
GLuint create_shader(const char* filename, GLenum type)
{
const GLchar* source = file_read(filename);
if (source == NULL) {
fprintf(stderr, "Error opening %s: ", filename); perror("");
return 0;
}
else {
printf("Load shader correctly %s\n", filename);
}
GLuint res = glCreateShader(type);
const GLchar* sources[] = {
// Define GLSL version
#ifdef GL_ES_VERSION_2_0
"#version 100\n" // OpenGL ES 2.0
#else
"#version 120\n" // OpenGL 2.1
#endif
,
// GLES2 precision specifiers
#ifdef GL_ES_VERSION_2_0
// Define default float precision for fragment shaders:
(type == GL_FRAGMENT_SHADER) ?
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float; \n"
"#else \n"
"precision mediump float; \n"
"#endif \n"
: ""
// Note: OpenGL ES automatically defines this:
// #define GL_ES
#else
// Ignore GLES 2 precision specifiers:
"#define lowp \n"
"#define mediump\n"
"#define highp \n"
#endif
,
source };
glShaderSource(res, 3, sources, NULL);
free((void*)source);
glCompileShader(res);
GLint compile_ok = GL_FALSE;
glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
if (compile_ok == GL_FALSE) {
fprintf(stderr, "%s:", filename);
//print_log(res);
glDeleteShader(res);
return 0;
}
return res;
}
GLuint create_program(const char *vertexfile, const char *fragmentfile) {
printf("Creating program\n");
GLuint program = glCreateProgram();
GLuint shader;
printf("Loading program\n");
if (vertexfile) {
shader = create_shader(vertexfile, GL_VERTEX_SHADER);
if (!shader)
return 0;
glAttachShader(program, shader);
}
if (fragmentfile) {
shader = create_shader(fragmentfile, GL_FRAGMENT_SHADER);
if (!shader)
return 0;
glAttachShader(program, shader);
}
glLinkProgram(program);
GLint link_ok = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok) {
fprintf(stderr, "glLinkProgram:");
//print_log(program);
glDeleteProgram(program);
return 0;
}
return program;
}
GLint get_attrib(GLuint program, const char *name) {
GLint attribute = glGetAttribLocation(program, name);
if (attribute == -1)
fprintf(stderr, "Could not bind attribute %s\n", name);
return attribute;
}
GLint get_uniform(GLuint program, const char *name) {
GLint uniform = glGetUniformLocation(program, name);
if (uniform == -1)
fprintf(stderr, "Could not bind uniform %s\n", name);
return uniform;
}
bool bLoadPngImage(char *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
png_structp png_ptr;
png_infop info_ptr;
unsigned int sig_read = 0;
int color_type, interlace_type;
FILE *fp;
if ((fp = fopen(name, "rb")) == NULL)
return false;
/* Create and initialize the png_struct
* with the desired error handler
* functions. If you want to use the
* default stderr and longjump method,
* you can supply NULL for the last
* three parameters. We also supply the
* the compiler header file version, so
* that we know if the application
* was compiled with a compatible version
* of the library. REQUIRED
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return false;
}
/* Allocate/initialize the memory
* for image information. REQUIRED. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(fp);
png_destroy_read_struct(&png_ptr, NULL, NULL);
return false;
}
/* Set error handling if you are
* using the setjmp/longjmp method
* (this is the normal method of
* doing things with libpng).
* REQUIRED unless you set up
* your own error handlers in
* the png_create_read_struct()
* earlier.
*/
if (setjmp(png_jmpbuf(png_ptr))) {
/* Free all of the memory associated
* with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
/* If we get here, we had a
* problem reading the file */
return false;
}
/* Set up the output control if
* you are using standard C streams */
png_init_io(png_ptr, fp);
/* If we have already
* read some of the signature */
png_set_sig_bytes(png_ptr, sig_read);
/*
* If you have enough memory to read
* in the entire image at once, and
* you need to specify only
* transforms that can be controlled
* with one of the PNG_TRANSFORM_*
* bits (this presently excludes
* dithering, filling, setting
* background, and doing gamma
* adjustment), then you can read the
* entire image (including pixels)
* into the info structure with this
* call
*
* PNG_TRANSFORM_STRIP_16 |
* PNG_TRANSFORM_PACKING forces 8 bit
* PNG_TRANSFORM_EXPAND forces to
* expand a palette into RGB
*/
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
png_uint_32 width, height;
int bit_depth;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
outWidth = width;
outHeight = height;
unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
*outData = (unsigned char*)malloc(row_bytes * outHeight);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
for (int i = 0; i < outHeight; i++) {
// note that png is ordered top to
// bottom, but OpenGL expect it bottom to top
// so the order or swapped
memcpy(*outData + (row_bytes * (outHeight - 1 - i)), row_pointers[i], row_bytes);
}
/* Clean up after the read,
* and free any memory allocated */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* Close the file */
fclose(fp);
/* That's it */
return true;
}
void vLoadPngToTexture(std::string sFilename, int iTexture) {
GLubyte *glTextureImage;
int iWidth, iHeight;
bool bHasAlpha;
//char filename[] = "/home/root/res/drawable/disclaimerantamina.png";
//bool success = bLoadPngImage((char *)sFilename.c_str(), iWidth, iHeight, bHasAlpha, &glTextureImage);
//if (!success) {
if (!bLoadPngImage((char *)sFilename.c_str(), iWidth, iHeight, bHasAlpha, &glTextureImage)) {
std::cout << "Unable to load png file" << std::endl;
exit(0);
}
std::cout << "Image loaded " << sFilename << " " << iWidth << " " << iHeight << " alpha " << bHasAlpha << std::endl;
glBindTexture(GL_TEXTURE_2D, glTextures[iTexture]);
/* Generate The Texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iWidth,
iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
glTextureImage);
/* Linear Filtering */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
std::cout << "Texture loaded " << iTexture << " - " << sFilename << std::endl;
}
int init_resources() {
/* Initialize the FreeType2 library */
if (FT_Init_FreeType(&ft)) {
fprintf(stderr, "Could not init freetype library\n");
return 0;
}
/* Load a font */
if (FT_New_Face(ft, fontfilename, 0, &face)) {
fprintf(stderr, "Could not open font %s\n", fontfilename);
return 0;
}
printf("Load Font Correctly\n");
program = create_program("text.v.glsl", "text.f.glsl");
if (program == 0)
return 0;
printf("Create program Correctly\n");
attribute_coord = get_attrib(program, "coord");
uniform_tex = get_uniform(program, "tex");
uniform_color = get_uniform(program, "color");
if (attribute_coord == -1 || uniform_tex == -1 || uniform_color == -1)
return 0;
printf("Create attributes Correctly\n");
programBack = create_program("back.v.glsl", "back.f.glsl");
printf("Create program Background Correctly\n");
coordBack = get_attrib(programBack, "g_vPosition");
//colorBack = get_attrib(programBack, "g_vColor");
texBack = get_attrib(programBack, "g_vTexCoord");
if (coordBack == -1 || colorBack == -1 || texBack == -1)
return 0;
// Create the vertex buffer object
glGenBuffers(1, &vbo);
///* Create texture atlasses for several font sizes */
a48 = new atlas(face, 48);
a24 = new atlas(face, 24);
a12 = new atlas(face, 12);
return 1;
}
/**
* Render text using the currently loaded font and currently set font size.
* Rendering starts at coordinates (x, y), z is always 0.
* The pixel coordinates that the FreeType2 library uses are scaled by (sx, sy).
*/
void render_text(const char *text, atlas * a, float x, float y, float sx, float sy) {
const uint8_t *p;
/* Use the texture containing the atlas */
glBindTexture(GL_TEXTURE_2D, a->tex);
glUniform1i(uniform_tex, 0);
/* Set up the VBO for our vertex data */
glEnableVertexAttribArray(attribute_coord);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(attribute_coord, 4, GL_FLOAT, GL_FALSE, 0, 0);
point coords[6 * strlen(text)];
int c = 0;
/* Loop through all characters */
for (p = (const uint8_t *)text; *p; p++) {
/* Calculate the vertex and texture coordinates */
float x2 = x + a->c[*p].bl * sx;
float y2 = -y - a->c[*p].bt * sy;
float w = a->c[*p].bw * sx;
float h = a->c[*p].bh * sy;
/* Advance the cursor to the start of the next character */
x += a->c[*p].ax * sx;
y += a->c[*p].ay * sy;
/* Skip glyphs that have no pixels */
if (!w || !h)
continue;
coords[c++] = (point) {
x2, -y2, a->c[*p].tx, a->c[*p].ty
};
coords[c++] = (point) {
x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty
};
coords[c++] = (point) {
x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h
};
coords[c++] = (point) {
x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty
};
coords[c++] = (point) {
x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h
};
coords[c++] = (point) {
x2 + w, -y2 - h, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty + a->c[*p].bh / a->h
};
}
/* Draw all the character on the screen in one go */
glBufferData(GL_ARRAY_BUFFER, sizeof coords, coords, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, c);
glDisableVertexAttribArray(attribute_coord);
}
void display() {
//float sx = 2.0 / glutGet(GLUT_WINDOW_WIDTH);
//float sy = 2.0 / glutGet(GLUT_WINDOW_HEIGHT);
float sx = 2.0 / 800;
float sy = 2.0 / 480;
glViewport(0, 0, 800, 480);
glUseProgram(programBack);
/* White background */
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Enable blending, necessary for our alpha texture */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glVertexAttribPointer(coordBack, 3, GL_FLOAT, 0, 0, fBackgroundPosition);
glEnableVertexAttribArray(coordBack);
//glVertexAttribPointer(colorBack, 4, GL_FLOAT, 0, 0, VertexColors);
//glEnableVertexAttribArray(colorBack);
glVertexAttribPointer(texBack, 2, GL_FLOAT, 0, 0, VertexTexCoords);
glEnableVertexAttribArray(texBack);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, glTextures[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Cleanup
glDisableVertexAttribArray(coordBack);
glDisableVertexAttribArray(colorBack);
glDisableVertexAttribArray(texBack);
glUseProgram(program);
GLfloat black[4] = { 0, 0, 0, 1 };
GLfloat red[4] = { 1, 0, 0, 1 };
GLfloat transparent_green[4] = { 0, 1, 0, 0.5 };
/* Set color to black */
//glUniform4fv(uniform_color, 1, black);
/* Effects of alignment */
render_text("The ñ Ñ Quick Brown Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 50 * sy, sx, sy);
//render_text("The , . - + { } & % Misaligned Fox Jumps Over The Lazy Dog", a48, -1 + 8.5 * sx, 1 - 100.5 * sy, sx, sy);
///* Scaling the texture versus changing the font size */
//render_text("The ç ó Small Texture Scaled Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 175 * sy, sx * 0.5, sy * 0.5);
//render_text("The Small Font Sized Fox Jumps Over The Lazy Dog", a24, -1 + 8 * sx, 1 - 200 * sy, sx, sy);
//render_text("The Tiny Texture Scaled Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 235 * sy, sx * 0.25, sy * 0.25);
//render_text("The Tiny Font Sized Fox Jumps Over The Lazy Dog", a12, -1 + 8 * sx, 1 - 250 * sy, sx, sy);
///* Colors and transparency */
//render_text("The Solid Black Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 430 * sy, sx, sy);
//glUniform4fv(uniform_color, 1, red);
//render_text("The Solid Red Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 330 * sy, sx, sy);
//render_text("The Solid Red Fox Jumps Over The Lazy Dog", a48, -1 + 28 * sx, 1 - 450 * sy, sx, sy);
//glUniform4fv(uniform_color, 1, transparent_green);
//render_text("The Transparent Green Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 380 * sy, sx, sy);
//render_text("The Transparent Green Fox Jumps Over The Lazy Dog", a48, -1 + 18 * sx, 1 - 440 * sy, sx, sy);
eglSwapBuffers(egldisplay, eglsurface);
}
void free_resources() {
glDeleteProgram(program);
}
int init(void)
{
Display *x_display;
Window win;
x_display = XOpenDisplay(":0"); // open the standard display (the primary screen)
if (x_display == NULL) {
std::cout << "cannot connect to X server" << std::endl;
return 1;
}
Window root = DefaultRootWindow(x_display); // get the root window (usually the whole screen)
XSetWindowAttributes swa;
swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
win = XCreateWindow( // create a window with the provided parameters
x_display, root,
0, 0, 800, 480, 0,
CopyFromParent, InputOutput,
CopyFromParent, CWEventMask,
&swa);
XMapWindow(x_display, win); // make the window visible on the screen
XStoreName(x_display, win, "GL test"); // give the window a name
static const EGLint s_configAttribs[] =
{
EGL_RENDERABLE_TYPE, 4,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 0,
EGL_SAMPLES, 0,
EGL_SAMPLE_BUFFERS, 1,
EGL_SAMPLES, 4, // This is for 4x MSAA.
EGL_NONE
};
EGLint numconfigs;
egldisplay = eglGetDisplay((EGLNativeDisplayType)x_display);
eglInitialize(egldisplay, NULL, NULL);
assert(eglGetError() == EGL_SUCCESS);
eglBindAPI(EGL_OPENGL_ES_API);
eglChooseConfig(egldisplay, s_configAttribs, &eglconfig, 1, &numconfigs);
assert(eglGetError() == EGL_SUCCESS);
assert(numconfigs == 1);
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, win, NULL);
assert(eglGetError() == EGL_SUCCESS);
EGLint ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
eglcontext = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, ContextAttribList);
assert(eglGetError() == EGL_SUCCESS);
eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext);
assert(eglGetError() == EGL_SUCCESS);
printf("VENDOR = %s\n", glGetString(GL_VENDOR));
printf("RENDERER = %s\n", glGetString(GL_RENDERER));
printf("VERSION = %s\n", glGetString(GL_VERSION));
}
int main(int argc, char *argv[]) {
if (argc > 1)
fontfilename = argv[1];
else
fontfilename = "FreeSans.ttf";
init();
init_resources();
std::string sBackground = "back2.png";
vLoadPngToTexture(sBackground, 0);
//// this is needed for time measuring --> frames per second
struct timezone tz;
timeval t1, t2;
gettimeofday(&t1, &tz);
int num_frames = 0;
while (1) {
display();
if (++num_frames % 30 == 0) {
//if (++num_frames % 100 == 0) {
gettimeofday(&t2, &tz);
float dt = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
std::cout << "fps: " << num_frames / dt << std::endl;
num_frames = 0;
t1 = t2;
}
usleep(32000);
}
return 0;
}
如果我对render_text("The ñ Ñ Quick Brown Fox Jumps Over The Lazy Dog", a48, -1 + 8 * sx, 1 - 50 * sy, sx, sy);
行进行评论,我可以完美地看到纹理正方形。
答案 0 :(得分:1)
glUniform
通过调用glUseProgram
对作为当前状态一部分的程序对象进行操作。因此,函数glUniform1i
中atlas
的调用是无用的,因为此时根本没有当前的程序。您可以删除此通话,因为您稍后会设置制服。
glTextures[iTexture]
中绑定的纹理vLoadPngToTexture
。以某种方式改变你的代码:
glGenTextures(1, glTextures+iTexture);
glBindTexture(GL_TEXTURE_2D, glTextures[iTexture]);
render_text
中绑定glBindBuffer(GL_ARRAY_BUFFER, vbo);
但您永远不会释放它。这会导致在下一个周期中绘制背景时仍然绑定数组缓冲区vbo
。因此,glVertexAttribPointer
在函数display
中不会按照您的预期执行。您可以通过添加
来解决此问题glBindBuffer(GL_ARRAY_BUFFER, 0)
到函数render_text
的末尾。