我有以下代码可以在屏幕外 FBO 上渲染一个矩形和一些文本。然后我尝试在默认/显示帧缓冲区中绑定纹理(附加到 FBO)。我能够渲染矩形,但字体没有被渲染。我尝试调试,但到目前为止还不能。我只需要在 OpenGL ES 2.0 中执行此操作。
我的矩形是橙色的。文本/字体为红色。我使用 Freetype lib 和 glTexImage2D 调用为每种字体创建单独的纹理。当我直接在默认帧缓冲区上渲染时,我成功获得了一个橙色矩形和红色字体。但是当我首先在屏幕外 FBO 上执行此操作时,我会得到一个带红色的矩形和一些垃圾小文本(我假设)。我正在继续调试,但任何输入都会有所帮助。
注意:我是 OpenGL 的新手。
EGLSurface eglsurface;
EGLDisplay egldisplay;
EGLConfig eglconfig;
EGLContext eglcontext;
void* NativeWindow;
GLuint VBO;
FT_Face face;
unsigned int shaderProgram;
unsigned int vertexShader;
unsigned int fragmentShader;
int color_loc;
const GLuint WIDTH = 1920, HEIGHT = 1080;
EGLint Attributes[] = { EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_ALPHA_SIZE, 1,
EGL_NONE };
EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION,
2,
EGL_NONE };
void GlInit()
{
glViewport(0, 0, WIDTH, HEIGHT);
const char *vertexShaderSource =
"attribute vec4 vertex;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(vertex.xy, 0, 1);\n"
"texcoord = vertex.zw;\n"
"}\n";
const char *fragmentShaderSource =
"precision highp float;\n"
"varying vec2 texcoord;\n"
"uniform sampler2D s_texture;\n"
"uniform vec4 myColor;\n"
"void main(void) {\n"
"gl_FragColor = vec4(1, 1, 1, texture2D(s_texture, texcoord).a) * myColor;\n"
"}\n";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n");
}
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n");
}
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("ERROR::SHADER::LINKING_FAILED\n");
}
glGenBuffers(1, &VBO);
glUseProgram(shaderProgram);
//glClearDepthf(1.0f);
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// SAGAR - Blend required for texture
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Get the color location in fragment shader, will fill on need
color_loc = glGetUniformLocation(shaderProgram, "myColor");
}
void DrawRect()
{
glBindBuffer(GL_ARRAY_BUFFER, VBO);
int position_loc = glGetAttribLocation(shaderProgram, "vertex");
glEnableVertexAttribArray(position_loc);
glVertexAttribPointer(position_loc, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLfloat rectangle[4][4] = {
-0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f
};
glUniform4f(color_loc, 1.0f, 0.5f, 0.2f, 1.0f); // Orange
glBufferData(GL_ARRAY_BUFFER, sizeof rectangle, rectangle, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void render_fboTexture()
{
int TextureLocation = glGetUniformLocation(shaderProgram, "s_texture");
glUniform1i(TextureLocation, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Draw in a small quad for testing
GLfloat quad[4][4] = {
{-0.5, 0.5, 0, 0},
{0.5, 0.5, 1, 0},
{-0.5, -0.5, 0, 1},
{0.5, -0.5, 1, 1},
};
glBufferData(GL_ARRAY_BUFFER, sizeof quad, quad, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void render_captiondata(const char* caption, float x, float y, float sx, float sy);
void RenderTexture()
{
int TextureLocation = glGetUniformLocation(shaderProgram, "s_texture");
glUniform1i(TextureLocation, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Set desired text color
glUniform4f(color_loc, 0.5f, 0.0f, 0.0f, 1.0f); // Red
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
printf("SAGAR- Could not init FreeType Library\n");
}
if (FT_New_Face(ft, "./xyz.ttf", 0, &face)) {
printf("SAGAR - Failed to load font\n");
}
FT_Set_Pixel_Sizes(face, 0, 48);
GLuint texture;
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Calculate the scales both sides
float sx = 2.0 / WIDTH;
float sy = 2.0 / HEIGHT;
float x = -0.4;
float y = 0.3;
render_captiondata("-- Hello OpenGL! --", x, y, sx, sy);
}
void render_captiondata(const char* caption, float x, float y, float sx, float sy)
{
const char *p;
for(p = caption; *p; p++) {
if (FT_Load_Char(face, *p, FT_LOAD_RENDER)) {
printf("SAGAR - Failed to load Glyph\n");
}
float x2 = x + face->glyph->bitmap_left * sx;
float y2 = -y - face->glyph->bitmap_top * sy;
float w = face->glyph->bitmap.width * sx;
float h = face->glyph->bitmap.rows * sy;
GLfloat fontVertices[4][4] = {
{x2, -y2 , 0, 0},
{x2 + w, -y2 , 1, 0},
{x2, -y2 - h, 0, 1},
{x2 + w, -y2 - h, 1, 1},
};
glTexImage2D(
GL_TEXTURE_2D, 0, GL_ALPHA, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof fontVertices, fontVertices, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
x += (face->glyph->advance.x/64) * sx;
y += (face->glyph->advance.y/64) * sy;
}
}
int main()
{
EglInit();
GlInit();
// FBO experiment: SAGAR
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glBindTexture(GL_TEXTURE_2D, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
printf("Problem with OpenGL framebuffer : %x\n", status);
}
DrawRect();
RenderTexture(); // Does not work
glBindTexture(GL_TEXTURE_2D, 0);
eglSwapBuffers(egldisplay, eglsurface);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texture);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render_fboTexture();
glBindTexture(GL_TEXTURE_2D, 0);
//RenderTexture(); // Directly onto default/main framebuffer works
eglSwapBuffers(egldisplay, eglsurface);
sleep(10);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
return 0;
}
egl 相关的初始化。
void EglInit()
{
EGLint configCount;
egldisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (egldisplay == EGL_NO_DISPLAY) {
printf("eglGetDisplay() failed: %d\n", eglGetError());
}
EGLint majorVersion = 0;
EGLint minorVersion = 0;
if (!eglInitialize(egldisplay, &majorVersion, &minorVersion)) {
printf("eglInitialize() failed: %d\n", eglGetError());
}
if (!eglChooseConfig(egldisplay, Attributes, &eglconfig, 1, &configCount))
{
printf("eglChooseConfig failed : %d\n", eglGetError());
}
eglcontext = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, contextAttributes);
if (eglcontext == EGL_NO_CONTEXT) {
printf("eglCreateContext() failed\n");
}
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, NativeWindow, NULL);
if (eglsurface == EGL_NO_SURFACE) {
printf("eglCreateWindowSurface() failed\n");
}
eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext);
}