当前位置: 首页 > 知识库问答 >
问题:

在OpenGL中应用着色器时不会渲染纹理

何聪
2023-03-14

在一个教程之后,我将尝试使用FreeType在OpenGL中渲染文本。因此,灰度8位图像用作每个字符的纹理,使图像的每个字节对应于纹理的红色分量。

为了以其他颜色呈现文本,建议您使用着色器。但是,当使用提供的着色器时,我看到的不是彩色字母,而是彩色框,好像根本没有纹理。

以下是没有着色器时的效果:

这是它在着色器中的外观:

(盒子的位置也会发生变化)

以下是顶点着色器代码:

#version 330 core
layout (location = 0) in vec4 vertex;
out vec2 TexCoords;
void main() {
    gl_Position = vec4(vertex.xy, 0.0, 1.0);
    TexCoords = vertex.zw;
}

这是片段着色器代码:

#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D text;
uniform vec4 textColor;
void main() {
    vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
    color = textColor * sampled;
}

这是屏幕上呈现的代码:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Shader here
glUseProgram(shaderProgram);
glUniform4f(
    glGetUniformLocation(shaderProgram, "textColor"),
    0.0f, 1.0f, 0.0f, 1.0f
);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texID);
glUniform1i(glGetUniformLocation(shaderProgram, "text"), 0);

// Draw here
glBegin(GL_QUADS);
glTexCoord2f(1., 0.);
glVertex2f(20. / WIDTH, 20. / HEIGHT);

glTexCoord2f(0., 0.);
glVertex2f(100. / WIDTH, 20. / HEIGHT);

glTexCoord2f(0., 1.);
glVertex2f(100. / WIDTH, 100. / HEIGHT);

glTexCoord2f(1., 1.);
glVertex2f(20. / WIDTH, 100. / HEIGHT);
glEnd();

还有,这是整个代码:

#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype2/freetype/freetype.h>

const unsigned int WIDTH = 640;
const unsigned int HEIGHT= 480;

const char *vertex_shader_src =
"#version 330 core\n"
"layout (location = 0) in vec4 vertex;\n"
"out vec2 TexCoords;\n"
"void main() {\n"
"gl_Position = vec4(vertex.xy, 0.0, 1.0);\n"
"TexCoords = vertex.zw;}\0";

const char *frag_shader_src = 
"#version 330 core\n"
"in vec2 TexCoords;\n"
"out vec4 color;\n"
"uniform sampler2D text;\n"
"uniform vec4 textColor;\n"
"void main() {\n"
"vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);\n"
"color = textColor * sampled;}\0";

int main() {

    // -------------------------------------------------------------------------
    // WINDOW INITIALIZATION

    GLFWwindow *window;

    glfwInit();
    window = glfwCreateWindow(640, 480, "SHADER", NULL, NULL);
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    glClearColor(0., 0. , 0., 1.);
    glColor4f(1., 1., 1., 1.);
    glPointSize(1.);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, (WIDTH*1.)/HEIGHT, 1., 0, 1., -1.);
    glViewport(0, 0, WIDTH, HEIGHT);
    // -------------------------------------------------------------------------
    // SHADER INITIALIZATION

    glewInit();

    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertex_shader_src, NULL);
    glCompileShader(vertexShader);

    int fragShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragShader, 1, &frag_shader_src, NULL);
    glCompileShader(fragShader);

    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragShader);
    glLinkProgram(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragShader);
    // -------------------------------------------------------------------------
    // TEXTURE FOR A SINGLE CHARACTER
    FT_Library ft;
    if (FT_Init_FreeType(&ft)) {
        printf("Error in FT_Init_FreeType\n");
        return 1;
    }

    FT_Face face;
    if (FT_New_Face(ft, "Ubuntu-R.ttf", 0, &face)) {
        printf("Error in FT_New_Face\n");
        return 1;
    }

    FT_Set_Pixel_Sizes(face, 0, 96);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    if (FT_Load_Char(face, 'A', FT_LOAD_RENDER)) {
        printf("Error in FT_Load_Char\n");
        return 1;
    }

    unsigned int texID;
    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);

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

    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);

    glBindTexture(GL_TEXTURE_2D, 0);
    FT_Done_Face(face);
    FT_Done_FreeType(ft);

    // -------------------------------------------------------------------------
    // MAIN LOOP

    while (!glfwWindowShouldClose(window)) {

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Shader here
        glUseProgram(shaderProgram);
        glUniform4f(
            glGetUniformLocation(shaderProgram, "textColor"),
            0.0f, 1.0f, 0.0f, 1.0f
        );

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texID);
        glUniform1i(glGetUniformLocation(shaderProgram, "text"), 0);

        // Draw here
        glBegin(GL_QUADS);
        glTexCoord2f(1., 0.);
        glVertex2f(20. / WIDTH, 20. / HEIGHT);

        glTexCoord2f(0., 0.);
        glVertex2f(100. / WIDTH, 20. / HEIGHT);

        glTexCoord2f(0., 1.);
        glVertex2f(100. / WIDTH, 100. / HEIGHT);

        glTexCoord2f(1., 1.);
        glVertex2f(20. / WIDTH, 100. / HEIGHT);
        glEnd();
        glUseProgram(0);

        glFlush();
        glfwSwapBuffers(window);
        glfwPollEvents();

    }

    glDeleteProgram(shaderProgram);
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;

}

我怀疑问题可能是因为我没有将纹理发送到着色器,或者着色器是错误的。

共有1个答案

壤驷英叡
2023-03-14

您使用的是传统的OpenGL OpenGL,并通过即时模式glBegin/glEnd序列绘制几何图形。无法访问由常规顶点着色器输入设置的纹理坐标。请参见OpenGL 4.0 core profile?中固定功能管道的属性位置
必须将顶点着色器降级为GLSL版本1.20(OpenGL着色语言1.20规范),并且必须通过gl_顶点访问顶点坐标,通过gl_MultiTexCoord0访问纹理坐标:

#version 120

varying vec2 TexCoords;

void main() 
{
    gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
    TexCoords = gl_MultiTexCoord0.st;
}

如果要使用问题中的着色器,则必须通过glvertexattributepointer指定顶点属性数组(请参见顶点规范),并且必须通过glDrawArrays绘制几何体:

例如:

float vertex_attributes[] = {
     20. / WIDTH,  20. / HEIGHT, 1., 0.,
    100. / WIDTH,  20. / HEIGHT, 0., 0.,
    100. / WIDTH, 100. / HEIGHT, 0., 1.,
     20. / WIDTH, 100. / HEIGHT, 1., 1.
};

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &vertex_attributes);
glEnableVertexAttribArray(0);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(0);

请注意,glewInit()必须在glfwMakeContextNow()之后但在任何OpenGL指令之前完成。

 类似资料:
  • 我有一个非常简单的OpenGL应用程序,只渲染一个带纹理的四边形。这是我的代码,效果很好(带纹理的四边形看起来很好): 然后我想介绍一个简单的着色器。所以我稍微修改了我的代码: 顶点着色器: 片段着色器: 现在我得到的只是一个黑色的四边形:-( 我已经尝试并测试了很多东西: 着色器编译良好(无错误) 有人知道为什么我在使用着色器时看不到我的纹理吗?

  • 我想在FBO中加载两个纹理,其中一个纹理包含HDR图像,我的第一个目标是将图像从第一个纹理“复制”到第二个纹理(该纹理为空),并称为“下采样纹理”。 所以我创建FBO,加载我想用颜色_附件_0书写的纹理,并绑定它;然后初始化我的着色器程序并渲染一个四边形,其中包含我要在GL\u texture\u 0中读取的纹理。 然后我解开FBO并绑定“DownSamplingTex”,然后画一个四元组。 我不

  • 我正在渲染很多轴对齐的3D立方体。每个立方体的中心位置和/或颜色可能不同于其他立方体。这就是我现在渲染它的方式 My DrawCube()使用和存储在VBO中的顶点数据,简单地渲染立方体每一侧对应的6个四边形。glVertexPointer和glColorPointer用于设置属性元素。 这是可行的,但是我想通过使用可能是glDrawElementsInst的()来使用即时渲染。但是由于项目的一些

  • 纹理根本不渲染,几何体都是黑色的。 截图:http://i.imgur.com/ypMdQY4.png 代码:http://pastebin.com/SvB8rxxt 我也会链接到我试图渲染的纹理和transformations.py模块,但是我没有被允许放置两个以上链接的声誉。谷歌搜索“现代opengl 02”会给你前者的教程,“转换py”会给你后者。 搜索“纹理材料开始”以查找纹理材料的设置位

  • 我是OpenGL的新手,在整理如何将纹理和着色器绑定到VBOs时遇到了困难。 我正在使用Cinder的纹理和着色器类。以下是我绘制方法的一部分: 在上面的代码中,如果我注释掉对mShader的调用。bind(),我的球体VBO将显示纹理(myImage)。我的着色器适用于普通(无纹理)形状,但当我在绘制任何带有包裹纹理的形状之前绑定着色器时,它会阻止纹理显示。 这是我使用的着色器的问题,还是我不理

  • 这是代码中唯一可能有错误的部分: 你能在这段代码中看到什么错误吗?启用glEnable(GL_TEXTURE_2D)并没有什么不同。纹理坐标是正确的,片段和顶点着色器肯定是正确的。 解决了这不是问题,我仍在使用glGenerateMipmap(…)在glTexImage2D(…)之前。真正的问题是,当我的图像是GL_RGB格式时,我通过了格式GL_RGBA。另外我的t-