繁体   English   中英

Opengl 没有使用正确的纹理

[英]Opengl is not using the correct texture

我最近开始在 learnopengl.com 上学习 opengl。 我是关于纹理的章节。 我已经设法加载了 2 个纹理,但是当我告诉 opengl 渲染当前绑定到GL_TEXTURE0的纹理时,它会绘制当前绑定到GL_TEXTURE1的纹理。

我的main.c文件如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "stb/stb_image_init.h"

#define WIDTH 1080
#define HEIGHT 720

typedef unsigned int uint;

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void process_input(GLFWwindow* window);
void check_shader_compilation(GLuint shader_object, GLenum shader_type);
void check_shader_linking(GLuint shader_program);
char* get_shader_code(const char* path);

int main(void) {
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Triangle", NULL, NULL);

    if (window == NULL) {
        printf("Unable to create glfw window!\n");
        return -1;
    }

    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        printf("Couldn't initialize glad!\n");
        return -1;
    }

    glViewport(0, 0, WIDTH, HEIGHT);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    char* vertex_shader_code = get_shader_code("shaders/vertex.glsl");

    GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader_object, 1, &vertex_shader_code, NULL);
    glCompileShader(vertex_shader_object);
    check_shader_compilation(vertex_shader_object, GL_VERTEX_SHADER);

    free(vertex_shader_code);

    char* fragment_shader_code = get_shader_code("shaders/fragment.glsl");

    GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader_object, 1, &fragment_shader_code, NULL);
    glCompileShader(fragment_shader_object);

    check_shader_compilation(fragment_shader_object, GL_FRAGMENT_SHADER);
    free(fragment_shader_code);

    uint shader_program = glCreateProgram();
    glAttachShader(shader_program, vertex_shader_object);
    glAttachShader(shader_program, fragment_shader_object);
    glLinkProgram(shader_program);
    glUseProgram(shader_program);

    check_shader_linking(shader_program);

    float rectangle_data[] = {
        // Coords           Colors              Texture coords
       -0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   0.0f,  0.0f, // Bottom Left
        0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   1.0f,  0.0f, // Bottom Right
       -0.5f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f,   0.0f,  1.0f, // Top Left
        0.5f,  0.5f, 0.0f,  1.0f, 1.0f, 0.0f,   1.0f,  1.0f, // Top Right
    };

    unsigned int indicies[] = {
        0, 2, 3,
        0, 1, 3,
    };

    uint vao, vbo, ebo;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glGenBuffers(1, &ebo);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

    glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle_data), rectangle_data, GL_STATIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*3));
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*6));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    float border_color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
    uint texture_buffer, texture2_buffer;
    glGenBuffers(1, &texture_buffer);
    glBindTexture(GL_TEXTURE_2D, texture_buffer);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);

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

    stbi_set_flip_vertically_on_load(true);
    int width = 0, height = 0, n_channels = 0;
    unsigned char* texture_image = stbi_load("assets/textures/luffy.jpg", &width, &height, &n_channels, 0);

    if (texture_image) {
        printf("Loaded texture0!\n");
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        printf("Couldn't find the image for the texture\n");
        exit(-1);
    }

    stbi_image_free(texture_image);

    glGenBuffers(1, &texture2_buffer);
    glBindTexture(GL_TEXTURE_2D, texture2_buffer);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);

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

    int t2_width = 0, t2_height = 0, t2_n_channels = 0;
    unsigned char* texture2_image = stbi_load("assets/textures/face.png", &t2_width, &t2_height, &t2_n_channels, 0);

    if (texture2_image) {
        printf("Loaded texture1!\n");
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t2_width, t2_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture2_image);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        printf("Couldn't find the image for texture2\n");
        exit(-1);
    }

    stbi_image_free(texture2_image);

    glUseProgram(shader_program);
    glUniform1i(glGetUniformLocation(shader_program, "luffy"), 0);
    glUniform1i(glGetUniformLocation(shader_program, "face"),  1);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    while (!glfwWindowShouldClose(window)) {
        process_input(window);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture_buffer);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2_buffer);

        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwPollEvents();
        glfwSwapBuffers(window);
    }

    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ebo);
    glDeleteShader(vertex_shader_object);
    glDeleteShader(fragment_shader_object);
    glDeleteProgram(shader_program);

    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
    glViewport(0, 0, width, height);
}

void process_input(GLFWwindow* window) {
    if (glfwGetKey(window, GLFW_KEY_Q) == true) {
        glfwSetWindowShouldClose(window, true);
    }
}

void check_shader_compilation(GLuint shader_object, GLenum shader_type) {
    char* print_shader_type;
    switch (shader_type) {
        case GL_VERTEX_SHADER:
            print_shader_type = "vertex";
            break; 

        case GL_FRAGMENT_SHADER:
            print_shader_type = "fragment";
            break;
        
        default:
            printf("Cannot check for shader compilation, the shader_type is not GL_VERTEX_SHADER or GL_FRAGMENT_SHADER!\n");
            exit(-1);
    }

    int shader_status;
    glGetShaderiv(shader_object, GL_COMPILE_STATUS, &shader_status);

    if (!shader_status) {
        int message_length;
        GLchar error[1024];
        glGetShaderInfoLog(shader_object, 1024, &message_length, error);
        printf("Could not compile the %s shader: \n %s\n", print_shader_type,  error);
        exit(-1);
    }
    else {
        printf("Compiled the %s shader!\n", print_shader_type);
    }
}

void check_shader_linking(GLuint shader_program) {
    int linking_status;
    glGetProgramiv(shader_program, GL_LINK_STATUS, &linking_status);

    if (!linking_status) {
        int message_length;
        GLchar error[1024];
        glGetProgramInfoLog(shader_program, 1024, &message_length, error);
        printf("Could not link the shader program:\n %s\n", error);
        exit(-1);
    }
    else {
        printf("Linked the shader program!\n");
    }
}

char* get_shader_code(const char* path) {
    FILE* shader_file = fopen(path, "rb");

    if (!shader_file) {
        printf("Incorrect file path for shader: %s\n", path);
        exit(-1);
    }

    fseek(shader_file, 0, SEEK_END);
    int file_size = ftell(shader_file);
    rewind(shader_file);
    char* shader_code = malloc(file_size + 1);
    shader_code[file_size] = '\0';
    fread(shader_code, sizeof(char), file_size, shader_file);
    return shader_code;
}

我的顶点着色器是:

#version 330

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 colors;
layout (location = 2) in vec2 texCoords;

out vec3 vertex_colors;
out vec2 tex_coords;

void main() {
    gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
    vertex_colors = colors;
    tex_coords = texCoords;
}

我的片段着色器是:

#version 330 core

out vec4 fragColor;

in vec3 vertex_colors;
in vec2 tex_coords;

uniform sampler2D luffy;
uniform sampler2D face;

void main() {
    fragColor = texture(luffy, tex_coords);
}

每当我运行程序时,它使用的纹理是face.png中的图像,而我告诉它使用luffy.jpg中的图像。

您永远不会创建任何纹理对象:

 glGenBuffers(1, &texture_buffer); glBindTexture(GL_TEXTURE_2D, texture_buffer);

glGenBuffers用于缓冲区对象,而不是纹理对象。 你必须使用glGenTextures (在这里也调用你的变量texture_buffer非常令人困惑。GL 中有缓冲纹理,但你没有在这里使用它们)。

而且由于您使用核心配置文件,因此glBindTexture()调用只会生成 GL 错误并且没有其他效果,因为您尝试绑定的对象名称从未由glGenTextures生成。 所以实际上,您在这里使用纹理对象 0,并将两个图像加载到该纹理对象,后者覆盖前者。 在核心分析器中,使用纹理对象 0 实际上不应该工作,但许多驱动程序仍然允许它(就像在旧版 GL 中允许的那样),因此也不能保证您实际上看到任何纹理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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