将GLSL现代OpenGL 3.2转换

3
我正在跟随Wikibooks上的freetype教程,在运行着Xcode 5的Mac系统10.9上进行。我已经成功使用120版本的着色器,但我希望能够使用一些现代化的特性,因此我将SDL提示设置为OpenGL 3.2,并将我的着色器转换为150版本。问题在于,150版本中使用texture2D会导致着色器无法编译。
以下是120版本的着色器:
const GLchar* vTextSource =
"#version 120\n"
"attribute vec4 coord;"
"varying vec2 texcoord;"
"void main(void) {"
"  gl_Position = vec4(coord.xy, 0, 1);"
"  texcoord = coord.zw;"
"}";

const GLchar* fTextSource =
"#version 120\n"
"varying vec2 texcoord;"
"uniform sampler2D tex;"
"uniform vec4 color;"
"void main(void) {"
"  gl_FragColor = vec4(1,1,0, texture2D(tex, texcoord).a) * color;"
"}";

以下是版本150的内容。顶点着色器可以构建,但是片段着色器失败,除非我删除所有使用texture2D的内容。在两者之间,所有的CPU代码都是相同的。

const GLchar* vTextSource =
"#version 150 \n"
"in vec4 coord;"
"out vec2 texcoord;"
"void main(void) {"
"  gl_Position = vec4(coord.xy, 0, 1);"
"  texcoord = coord.zw;"
"}";

const GLchar* fTextSource =
"#version 150\n"
"uniform sampler2D tex;"
"in vec2 texcoord;"
"uniform vec4 color;"
"out vec4 outColor;"
"void main(void) {"
"  outColor = vec4(1,1,1, texture2D(tex, texcoord).a) * color;"
"}";

我是否漏掉了什么?在核心模式和兼容模式下设置纹理采样器有所不同吗?

编辑:我已经将fragment shader中的texture2D(...)更改为texture(...)。现在编译通过了,但是没有显示任何内容。 我不确定如何调试此问题。 我已包含纹理初始化例程:

void SdlApplication::render_text(const char *text, float x, float y, float sx, float sy) {
    const char *p;
    FT_GlyphSlot g = face->glyph;

    /* Create a texture that will be used to hold one "glyph" */
    GLuint tex;

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glUniform1i(ogl.uniform_tex, 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);

    /* Set up the VBO for our vertex data */
    glEnableVertexAttribArray(ogl.attribute_coord);
    glBindBuffer(GL_ARRAY_BUFFER, vboText);
    glVertexAttribPointer(ogl.attribute_coord, 4, GL_FLOAT, GL_FALSE, 0, 0);

    /* Loop through all characters */
    for (p = text; *p; p++) {
        /* Try to load and render the character */
        if (FT_Load_Char(face, *p, FT_LOAD_RENDER))
            continue;

        /* Upload the "bitmap", which contains an 8-bit grayscale image, as an alpha texture */
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);

        /* Calculate the vertex and texture coordinates */
        float x2 = x + g->bitmap_left * sx;
        float y2 = -y - g->bitmap_top * sy;
        float w = g->bitmap.width * sx;
        float h = g->bitmap.rows * sy;

        point box[4] = {
            {x2, -y2, 0, 0},
            {x2 + w, -y2, 1, 0},
            {x2, -y2 - h, 0, 1},
            {x2 + w, -y2 - h, 1, 1},
        };

        /* Draw the character on the screen */
        glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        /* Advance the cursor to the start of the next character */
        x += (g->advance.x >> 6) * sx;
        y += (g->advance.y >> 6) * sy;
    }

    glDisableVertexAttribArray(ogl.attribute_coord);
    glDeleteTextures(1, &tex);
}

编辑2:在我的顶点设置中添加了vao。现在,我得到的是实心颜色的正方形,而不是文字。所以看起来纹理坐标再次出问题了。

我在每次调用后添加了检查,并发现在glewInit之后,我获得了1280代码,但在此之前没有...


1
你的顶点状态设置是怎样的?你创建了VAO(顶点数组对象)吗?由于你正在使用核心配置文件,这是必需的。如果你还没有尝试过,我建议你添加调用glGetError(),查看是否报告了错误以及在哪里报告了。 - Reto Koradi
我创建了VAO,现在我得到了实心的颜色块!在各处放置glGetError后,我发现glewInit是原因,但仅当我设置为核心配置文件和3.2兼容性时才会出现。尽管如此,在glTexImage2D之后我又得到了另一个1280错误。这是否与使用alpha或byte而不是浮点数有关? - omikun
GL_ALPHA 纹理格式在核心配置文件中已经被移除。我整理了一个答案,并总结了其余部分。 - Reto Koradi
2个回答

6

您的GLSL代码更新到最新标准看起来很好,除了texture2D()的问题。正如已经指出的那样,纹理采样函数现在已经重载,需要使用texture()而不是texture2D()

其余问题主要是将代码更新为使用核心配置文件,这个配置文件淘汰了许多旧特性。从发布的代码中可以看出,这包括:

  • Using VAOs (Vertex Array Objects) is mandatory for setting up vertex state. Use functions like glGenVertexArrays() and glBindVertexArray() to set up a VAO, and make sure that you have it bound while using vertex state setup functions like glVertexAttribPointer() and glEnableVertexAttribArray().

  • The GL_ALPHA texture format is not supported anymore. For using a texture format with a single 8-bit component, use GL_R8 for the internal format, and GL_RED for the format:

    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, g->bitmap.width, g->bitmap.rows, 0,
                 GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
    

    This will also require a minor change in the shader code, since the sampling value for the 1-component texture is now in the red component:

    outColor = vec4(1,1,1, texture2D(tex, texcoord).r) * color;
    

3

在片段着色器中,您应该使用texture而不是texture2D

void main(void) {
  outColor = vec4(1, 1, 1, texture(tex, texcoord).a) * color;
}

谢谢!这解决了着色器编译错误。不幸的是,着色器没有任何输出,我看不到任何东西。 - omikun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接