c++ - 当我传递纹理坐标 (OpenGL) 时没有任何显示

标签 c++ opengl textures shader mesh

我正在按照教程为现代 OpenGL 设置一些 VBO。我设法让网格和着色器运行(着色器设置为使每个像素都变成红色)。

问题是,一旦我推回纹理坐标。我什么也没看见!将它们注释掉后,我在屏幕中央看到一个深青色三角形。 有了纹理,我希望在那个三角形上出现白砖纹理,但是没有...

我真的不知道这里出了什么问题!希望有经验的大侠指教。 ;)

这是我的网格代码(或 VBO 代码):

Mesh::Mesh() {
    //Generate vertex array
    glGenVertexArrays(1, &arrayObject);

    //Generate buffers
    glGenBuffers(VBO_COUNT, buffers);
}

Mesh::Mesh(ObjectData *obj) {
    //Initialize first
    Mesh();

    //Set object to parameter
    setObject(obj);
}

Mesh::~Mesh() {
    //Delete buffer
    glDeleteBuffers(VBO_COUNT, buffers);

    //Delete array
    glDeleteVertexArrays(1, &arrayObject);
}

void Mesh::draw() {
    //Tell OpenGL which array to use
    glBindVertexArray(arrayObject);

    glDrawArrays(GL_TRIANGLES, 0, object->vertices.size());

    glBindVertexArray(NULL);
}

void Mesh::updateVBO() {
    //Tell OpenGL which vertex array to use from now
    glBindVertexArray(arrayObject);

    //Set buffer data
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);

    //Set shader attribute data
    glEnableVertexAttribArray(VBO_VERTEX);
    glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);

    if (object->texCoords.size()) {
        //Set buffer data
        glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);

        //Set shader attribute data
        glEnableVertexAttribArray(VBO_TEXCORD);
        glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
    }

    //Unbind vertex array
    glBindVertexArray(NULL);
}

void Mesh::setObject(ObjectData *obj) {
    object = obj;
    updateVBO();
}

这是我的着色器代码:

Shader::Shader(string fileName) {
    m_program = glCreateProgram();
    m_shaders[SHA_VERTEX] = createShader(loadShader(fileName + ".vs"), GL_VERTEX_SHADER);
    m_shaders[SHA_FRAGMENT] = createShader(loadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);

    for (int i = 0; i < SHA_COUNT; i++) {
        glAttachShader(m_program, m_shaders[i]);
    }

    glBindAttribLocation(m_program, VBO_VERTEX, "vertices");
    glBindAttribLocation(m_program, VBO_TEXCORD, "texCoords");

    glLinkProgram(m_program);
    checkShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");

    glValidateProgram(m_program);
    checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
}

Shader::~Shader() {
    for (int i = 0; i < SHA_COUNT; i++) {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);
}

string Shader::loadShader(string filePath) {
    ifstream file;
    file.open((filePath).c_str());

    string output;
    string line;

    if(file.is_open()) {
        while(file.good()) {
            getline(file, line);
            output.append(line + "\n");
        }
    }
    else {
        printf("Unable to load shader: %s\n", filePath.c_str());
    }

    return output;
}

void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, string errorMessage) {
    GLint success = 0;
    GLchar error[1024] = {0};

    if (isProgram) {
        glGetProgramiv(shader, flag, &success);
    }
    else {
        glGetShaderiv(shader, flag, &success);
    }

    if (success == GL_FALSE) {
        if(isProgram) {
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        }
        else {
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);
        }

        printf("%s: '%s'\n", errorMessage.c_str(), error);
    }
}

GLuint Shader::createShader(string text, unsigned int type) {
    GLuint shader = glCreateShader(type);
    if (shader == 0) {
        printf("Error compiling shader type %i\n", type);
    }

    const GLchar *p[1];
    p[0] = text.c_str();
    GLint lengths[1];
    lengths[0] = text.length();

    glShaderSource(shader, 1, p, lengths);
    glCompileShader(shader);

    checkShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");

    return shader;
}

void Shader::bind() {
    glUseProgram(m_program);
}

这是我的顶点和纹理坐标:

//Create test objects
ObjectData *obj = new ObjectData();

obj->vertices.push_back(glm::vec3(-0.5, -0.5, 0));
obj->vertices.push_back(glm::vec3(0, 0.5, 0));
obj->vertices.push_back(glm::vec3(0.5, -0.5, 0));
//obj->texCoords.push_back(glm::vec2(0, 0));
//obj->texCoords.push_back(glm::vec2(0.5, 1));
//obj->texCoords.push_back(glm::vec2(1, 0));

这是我的对象数据:

struct ObjectData {
    vector <glm::vec3> vertices;
    vector <glm::vec2> texCoords;

    ObjectData();
};

顶点着色器:

#version 120

attribute vec3 vertices;
attribute vec2 texCoords;

varying vec2 shared_texCoords;

void main() {
    gl_Position = vec4(vertices, 1.0);
    shared_texCoords = texCoords;
}

片段着色器:

#version 120

uniform sampler2D diffuse;

varying vec2 shared_texCoords;

void main() {
    gl_FragColor = texture2D(diffuse, shared_texCoords); //vec4(1.0, 0.0, 0.0, 1.0);
}

编辑: 纹理加载:

Texture::Texture(string fileName) {
    SDL_Surface *rawImage = IMG_Load(fileName.c_str());

    if (rawImage == NULL) {
        printf("Unable to load texture: %s\n", fileName.c_str());
    }
    else {
        //Convert to a texture of pure color pixels for OpenGL
        SDL_Surface *image = SDL_CreateRGBSurface(0, rawImage->w, rawImage->h, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0);
        SDL_BlitSurface(rawImage, NULL, image, NULL);

        glGenTextures(1, &m_texture);
        glBindTexture(GL_TEXTURE_2D, m_texture);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

        SDL_FreeSurface(rawImage);
        SDL_FreeSurface(image);
    }
}

Texture::~Texture() {
    glDeleteTextures(1, &m_texture);
}

void Texture::bind() {
    glBindTexture(GL_TEXTURE_2D, m_texture);
}

最佳答案

看来你没有加载纹理。

加载后,您需要在渲染期间绑定(bind)它,使用创建 GL 纹理时收到的纹理 ID,如下所示:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);

关于如何加载纹理,网上有很多教程,比如:http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/

注意:

这可能是 OpenGL Texture Sampling not working 的重复项

编辑: 问题在于您的纹理加载。这里 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); OpenGL 需要一个 4 channel 图像,但是这里 SDL_CreateRGBSurface(0, rawImage->w, rawImage->h, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0); 您正在创建一个 3 channel 图像,将 alpha channel 设置为零。 Alpha = 0 表示完全透明。您需要将其更改为 0x000000FF,或执行以下操作:

来自 http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlcreatergbsurface.html :

    Uint32 rmask, gmask, bmask, amask;

    /* SDL interprets each pixel as a 32-bit number, so our masks must depend
       on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    rmask = 0xff000000;
    gmask = 0x00ff0000;
    bmask = 0x0000ff00;
    amask = 0x000000ff;
#else
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
#endif

    surface = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 32,
                                   rmask, gmask, bmask, amask);

关于c++ - 当我传递纹理坐标 (OpenGL) 时没有任何显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23091418/

相关文章:

c++ - 使用 delete-operator 时程序停止工作

c++ - 链接 libboost_log.so 使 boost::asio::io_service::run 立即退出

python - 如何在 Python 中打开外部 .exe 文件后打开文件菜单,然后单击其子菜单之一?

c++ - OpenGL 纹理渲染颠倒且模糊

c++ - 比较分数没有溢出

opengl - VBO状态调用的结构

java - 使用 Slick2D TextureLoader 加载 PNG 图像时 LWJGL 挂起

c++ - 写入 gl_FragDepth,同时仍然执行深度预测试

opengl - 生成 mipmap 的正确方法是什么

c++ - 为什么使用带有可变模板参数的结构会同时实例化两个模板?