簡體   English   中英

OpenGL C ++使用頂點緩沖區和紋理緩沖區的順序

[英]OpenGL C++ order for using a vertex buffer and a texture buffer

我在將紋理加載到三角帶上時遇到問題。 我遵循的是Anton Gerdelan的教程 ,在主程序失敗之后,我回到了基礎知識,只是試圖制作一個普通的正方形並將其紋理放在上面(骷髏和交叉骨)。

我完全從他的“ Hello Triangle”頁面復制並粘貼了代碼,該頁面可以正常工作,但是一旦嘗試使其適合他上面的紋理教程中的代碼(並將三角形更改為正方形),我得到的就是一個帶有白色大正方形沒有質感。

我已經使用glGetShaderiv()檢查了着色器的狀態,並且它們返回正值,我檢查了加載的圖像以查看像素數據是否合理,因此我認為我的錯誤在於聲明我的VBO或其中的順序/參數我正在使用它們。

這是我復制的完整代碼,可以在Visual Studio 2013中很好地編譯,只是輸出不是預期的。

我正在使用GLEW和GLFW的靜態庫以及STBI Image標頭

#include <GL/glew.h> // include GLEW and new version of GL on Windows
#include <GL/glfw3.h> // GLFW helper library
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>

const char* vertex_shader =
"#version 400\n"
"in vec3 vp;"
"layout (location=1) in vec2 vt; // per-vertex texture co-ords"
"out vec2 texture_coordinates; "
"void main () {"
"  gl_Position = vec4 (vp, 1.0);"
"  texture_coordinates = vt; "
"}";

const char* fragment_shader =
"#version 400\n"
"in vec2 texture_coordinates;"
"uniform sampler2D basic_texture;"
"out vec4 frag_colour;"
"void main () {"
"vec4 texel = texture(basic_texture, texture_coordinates);"
"frag_colour = texel; "
"}";

float points[] = {
    -0.5f, -0.5f, 0.0f,
    -0.5f, 0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.5f, 0.5f, 0.0f

};

float texcoords[] = {
    0.0f, 1.0f,
    0.0f, 0.0f,
    1.0, 0.0,
    1.0, 0.0,
    1.0, 1.0,
    0.0, 1.0
};

GLFWwindow* window;
unsigned int vt_vbo;
unsigned int tex = 0;
GLuint vao = 0;
GLuint vbo = 0;
GLuint shader_programme;

void initializeGL(){
    // start GL context and O/S window using the GLFW helper library
    if (!glfwInit()) {
        printf("ERROR: could not start GLFW3\n");
        return;
    }

    window = glfwCreateWindow(640, 480, "Texture Test", NULL, NULL);
    if (!window) {
        printf("ERROR: could not open window with GLFW3\n");
        glfwTerminate();
        return;
    }
    glfwMakeContextCurrent(window);

    // start GLEW extension handler
    glewExperimental = GL_TRUE;
    glewInit();

    // get version info
    const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
    const GLubyte* version = glGetString(GL_VERSION); // version as a string
    printf("Renderer: %s\n", renderer);
    printf("OpenGL version supported %s\n", version);

    // tell GL to only draw onto a pixel if the shape is closer to the viewer
    glEnable(GL_DEPTH_TEST); // enable depth-testing
    glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
}

void startShaders(){

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, &vertex_shader, NULL);
    glCompileShader(vs);
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fs, 1, &fragment_shader, NULL);
    glCompileShader(fs);

    shader_programme = glCreateProgram();
    glAttachShader(shader_programme, fs);
    glAttachShader(shader_programme, vs);
    glLinkProgram(shader_programme);
    GLint vsstat;
    glGetShaderiv(vs, GL_COMPILE_STATUS, &vsstat);
    GLint fsstat;
    glGetShaderiv(fs, GL_COMPILE_STATUS, &fsstat);
    printf("%i\n%i\n", vsstat, fsstat);
}

void loadImage(){
    int x, y, n;
    int force_channels = 4;
    unsigned char* image_data = stbi_load("skulluvmap.png", &x, &y, &n, force_channels);
    if (!image_data) {
        printf("ERROR: could not load %s\n", "skulluvmap.png");
    }

    int width_in_bytes = x * 4;
    unsigned char *top = NULL;
    unsigned char *bottom = NULL;
    unsigned char temp = 0;
    int half_height = y / 2;


    for (int row = 0; row < half_height; row++) {
        top = image_data + row * width_in_bytes;
        bottom = image_data + (y - row - 1) * width_in_bytes;
        for (int col = 0; col < width_in_bytes; col++) {
            temp = *top;
            *top = *bottom;
            *bottom = temp;
            top++;
            bottom++;
        }
    }
    printf("first 4 bytes are: %i %i %i %i\n",
        image_data[0], image_data[1], image_data[2], image_data[3]
        );
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
    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_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

void generateBuffers(){
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), points, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0); // don't forget this!

    glGenBuffers(1, &vt_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), texcoords, GL_STATIC_DRAW);

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(1); // don't forget this!
}

void mainLoop(){
    while (!glfwWindowShouldClose(window)) {
        // wipe the drawing surface clear
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
        int tex_loc = glGetUniformLocation(shader_programme, "basic_texture");
        glUseProgram(shader_programme);
        glUniform1i(tex_loc, 0); // use active texture 0
        // draw points 0-4 from the currently bound VAO with current in-use shader
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        // update other events like input handling 
        glfwPollEvents();
        // put the stuff we've been drawing onto the display
        glfwSwapBuffers(window);
    }
}

int main() {

    initializeGL();
    startShaders();
    loadImage();
    generateBuffers();
    mainLoop();

    // close GL context and any other GLFW resources
    glfwTerminate();
    return 0;
}

您正在濫用第二個緩沖區,該緩沖區應該是texcoords的緩沖區。 因此,您真正想要實現的是每個頂點都有一對紋理坐標。 這意味着您的texcoords數組實際上應該存儲4對,因為您在points數組中有4個三元組。 所以這是第一個解決方法。 您可能希望它看起來像:

float texcoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0, 0.0,
1.0, 1.0,
};

然后在generateBuffers ,您的vt_vbo是錯誤的。 數據應通過以下方式傳遞:

glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), texcoords, GL_STATIC_DRAW);

因為您只想在那里傳遞8個值。 每個頂點2個texcoords。

編輯:

但是,這並不能完全解釋為什么紋理根本不出現。 我最初以為您的texcoords指針可能有問題,但事實並非如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM