简体   繁体   中英

OpenGL Texture drawing as one color

I've found similar posts here, but none help me with my problem. I'm just using basic OpenGL, and trying to draw a triangle with a texture applied. But for some reason the triangle is one solid color. This color happens to be the same color as the background of the texture.

This is the texture I'm attempting to draw

And this is the result when I run the program

在此处输入图片说明

I've experimented by editing the texture to have some blue in the bottom left (the origin), and it came out like this

在此处输入图片说明

My guess is that it's interpolating the red and blue to give me purple. But I have no idea why it'd be interpolating the colors in the first place instead of just drawing the texture like I want.

This is some bits and pieces of the relevant parts of my code:

Enabling things before the main loop

glClearColor(0, 0, 0, 1);

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

Loading the shaders

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

Loading the Texture

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

Vertex Structure

struct Vertex
{
    Vector2 position;
    Vector2 texCoord;
};

Generating the Vertex Array

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

And binding/drawing everything in the main loop

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

This is my vertex shader

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

And my fragment shader

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

I've literally been trying to solve this for days and I have no idea. If anyone could figure out why it's rendering with one color instead of the texture, it'd be very much appreciated.

You are not using your texcoords:

This is my vertex shader

 [...] out vec2 o_texCoord; 

And my fragment shader

 [...] in vec2 i_texCoord; 

The names of your vertex shader outputs must match those of your fragment shader inputs. Since they do not, your fragment shader sees an input value which will just be undefined as per the spec.

The only reason why you don't get an error during linking is that you use i_texCoord in the fragment shader in some conditional way ("dynamic use"). If you would statically use i_texCoord in the fragment shader, you actually would get a link error. However, since the comipler/linker cannot rule out that you never ever access that variable, this code is allowed as per the spec, and must not result in a compilation error. But if you actually access those values, they are undefined.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM