OpenGL 纹理绘制为一种颜色

OpenGL Texture drawing as one color

我在这里找到了类似的帖子,但是 none 帮助我解决了我的问题。我只是在使用基本的 OpenGL,并尝试绘制一个应用了纹理的三角形。但出于某种原因,三角形是一种纯色。这个颜色刚好和贴图的背景颜色一样

这是我要绘制的纹理

这是我运行程序

的结果

我尝试通过编辑纹理使左下角(原点)有一些蓝色,结果是这样的

我猜它是对红色和蓝色进行插值得到紫色。但我不知道为什么它会首先插入颜色而不是像我想要的那样只绘制纹理。

这是我的代码相关部分的一些零碎内容:

在主循环之前启用东西

glClearColor(0, 0, 0, 1);

glEnable(GL_BLEND);
glEnable(GL_TEXTURE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

加载着色器

auto vertString = getSource("test.vert");
auto vertSource = vertString.c_str();
GLint vertLength = vertString.length();

auto fragString= getSource("test.frag");
auto fragSource = fragString.c_str();
GLint fragLength = fragString.length();

auto vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &vertSource, &vertLength);

auto fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragSource, &fragLength);

//compile shaders
glCompileShader(vertShader);
checkShaderCompilation(vertShader, "vertex shader");

glCompileShader(fragShader);
checkShaderCompilation(fragShader, "fragment shader");

auto program = glCreateProgram();

glAttachShader(program, vertShader);
glAttachShader(program, fragShader);

glBindAttribLocation(program, 0, "i_position");
glBindAttribLocation(program, 1, "i_texCoord");

//link program
glLinkProgram(program);
checkProgramLinkage(program, "vertex shader", "fragment shader");

glDetachShader(program, vertShader);
glDetachShader(program, fragShader);

glDeleteShader(vertShader);
glDeleteShader(fragShader);

加载纹理

SDL_Surface* surface = IMG_Load("Numel.png");

if (!surface)
{
    std::cout << "Unable to load texture." << std::endl;
    return 0;
}

auto width = surface->w;
auto height = surface->h;
GLuint texture = 0;

//generate the id
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

auto mode = surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB;

glTexImage2D(GL_TEXTURE_2D, 0, mode, surface->w, surface->h, false, mode, GL_UNSIGNED_BYTE, surface->pixels);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

SDL_FreeSurface(surface);

glBindTexture(GL_TEXTURE_2D, 0);

顶点结构

struct Vertex
{
    Vector2 position;
    Vector2 texCoord;
};

生成顶点数组

Vertex data[] = {
    -0.5, -0.5, 0, 0,
    0.5, -0.5, 1, 0,
    0.5, 0.5, 1, 1
};

GLuint vertexBuffer = 0, vertexArray = 0;

glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*3, data, GL_STATIC_DRAW);

glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(Vertex), (char*)offsetof(Vertex, position));

glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(Vertex), (char*)offsetof(Vertex, texCoord));

并且binding/drawing主循环中的所有内容

glClear(GL_COLOR_BUFFER_BIT);

//texture
glBindTexture(GL_TEXTURE_2D, texture);

//shader
auto colorLoc = glGetUniformLocation(program, "u_color");
glUniform3f(colorLoc, 0, 0, 1);

auto useTextureLoc = glGetUniformLocation(program, "u_usingTexture");
glUniform1i(useTextureLoc, 1);

auto textureLoc = glGetUniformLocation(program, "u_sampler");
glUniform1i(textureLoc, 0);

glUseProgram(program);

//vertex array
glBindVertexArray(vertexArray);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);

SDL_GL_SwapWindow(window);

这是我的顶点着色器

#version 420

in vec2 i_position;
in vec2 i_texCoord;

out vec2 o_texCoord;

void main()
{
    o_texCoord=i_texCoord;
    gl_Position=vec4(i_position, 0, 1);
}

还有我的片段着色器

#version 420

uniform vec3 u_color;
uniform sampler2D u_sampler;
uniform bool u_usingTexture;

in vec2 i_texCoord;

out vec4 o_color;

void main()
{
    if(u_usingTexture)
        o_color=texture(u_sampler, i_texCoord);
    else
        o_color=vec4(u_color, 1);
}

几天来我一直在努力解决这个问题,但我不知道。如果有人能弄清楚为什么它使用一种颜色而不是纹理进行渲染,我们将不胜感激。

您没有使用纹理坐标:

This is my vertex shader

[...]
out vec2 o_texCoord;

And my fragment shader

[...]
in vec2 i_texCoord;

顶点着色器输出的名称必须匹配片段着色器输入的名称。因为它们没有,你的片段着色器看到一个输入值,根据规范,它只是 undefined

在 linking 期间没有出现错误的唯一原因是您以某种条件方式 ("dynamic use") 在片段着色器中使用了 i_texCoord。如果您在片段着色器中静态使用 i_texCoord,您实际上会收到 link 错误。但是,由于 comipler/linker 不能排除您永远不会访问该变量,因此根据规范允许使用此代码,并且不得导致编译错误。但是,如果您实际访问这些值,它们是未定义的。