当前位置: 首页 > 知识库问答 >
问题:

纹理加载问题OpenGL无法找出原因

汲涵育
2023-03-14

我有麻烦应用纹理到一个图像。我就是找不到问题所在

没有纹理代码,代码可以正常工作。

主文件:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <filesystem>
#include <stb_image.h>

#include "Shaders/Shader.h"


bool isWireFrame = false;

const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;

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

void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    {
        isWireFrame = !isWireFrame;
    }
}

int main(void)
{
    GLFWwindow* window;
    /* Initialize the library */

    if (!glfwInit())
    {
        std::cout << "GLFW did not init!" << std::endl;
        return EXIT_FAILURE;
    }
    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
    if (window == NULL)
    {
        glfwTerminate();
        return EXIT_FAILURE;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
        return EXIT_FAILURE;
    }
    std::cerr << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;


    /*
     We have to tell OpenGL the size of the rendering window so OpenGL knows how we want to display the data and coordinates with respect to the window. We can set those dimensions via the glViewport function
    */
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    glfwSetFramebufferSizeCallback(window, framebufferCallBack);
    glfwSetKeyCallback(window, keyCallBack);

    Shader shader("Shaders/glsl/vert.glsl", "Shaders/glsl/frag.glsl");

    float vertices[] = {
       // positions         // tex coords
       0.5f,  0.5f, 0.0f,   1.0f, 1.0f,               // top right
       0.5f, -0.5f, 0.0f,   1.0f, 0.0f,               // bottom right
      -0.5f, -0.5f, 0.0f,   0.0f, 0.0f,               // bottom left
      -0.5f,  0.5f, 0.0f,   0.0f, 1.0f                // top left 
    };

    unsigned int indices[] = {
        0, 1, 3,
        1, 2, 3

    };

    unsigned int VBO, VAO, EBO, texture;

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

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


    int width, height, nrChannels;
    unsigned char* data = stbi_load("Images/Crate.png", &width, &height, &nrChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else 
    {
        std::cout << "Failed to load the texture" << std::endl;
    }
    stbi_image_free(data);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_TEXTURE_2D, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

        float timeValue = glfwGetTime();
        float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
        Vector4 colour(0.0f, greenValue, 0.0f, 1.0f);

        glBindTexture(GL_TEXTURE_2D, texture);


        shader.use();
        shader.setVec4("Colour", colour);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();

        if (isWireFrame == true)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }
        else if (isWireFrame == false)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }

    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shader.ID);

    glfwTerminate();
    return 0;
}

片段着色器:

#version 330 core

out vec4 fragColour;

uniform vec4 Colour;

in vec2 TexCoord;

uniform sampler2D Texture;

void main()
{
    fragColour = texture(Texture, TexCoord);
} 

顶点着色器:

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos.xyz, 1.0);
    TexCoord = aTexCoord;
}

没有错误。

这是我画的对象。

这是我想要绘制的实际图像:

图像应该是一个矩形,但它是一个三角形,我不知道为什么会这样,也许这一点信息可以帮助。

编辑,所以我发现我没有使用正确的使用正确的颜色格式

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

但在format参数为gl_rgb而不是gl_rgba之前

但现在我有了一个半绘制的纹理:

共有1个答案

澹台俊达
2023-03-14

步幅的论点是错误的。您的属性包含5个组件(x,y,z,u,v)。因此stride是5*sizeof(float)而不是8*sizeof(float)

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

默认情况下,OpenGL假定图像的每一行的开头是4个字节。这是因为GL_UNPACK_ALIGNING参数默认为4。
由于图像有3个颜色通道(GL_RGB),并且压缩得很紧,图像的行大小可能无法对齐为4个字节。

当将具有3个颜色通道的RGB图像加载到纹理对象且3*width不能被4整除时,GL_UNPACK_ALIGNING必须设置为1:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
 类似资料:
  • 我试图在opengl中使用3d纹理来实现体绘制。每个体素都有一个rgba颜色值,当前渲染为面向屏幕的四元体。(用于测试目的)。我似乎无法让采样器在着色器中给我一个颜色值。四边形总是以黑色结尾。当我更改着色器以生成颜色(基于xyz坐标)时,效果很好。我正在用以下代码加载纹理: 颜色数组包含正确的数据,即前四个字节的值0, 0, 255, 255蓝色。在渲染之前,我将纹理绑定到第二个纹理单元,如下所示

  • 嘿,我不能让我的纹理出现,我不知道怎么了。辅导没有帮助。这是我的代码: spriteX=0,spriteY=0,spriteW=400,spriteL=400,x=0,y=0 这是我得到的输出:输出窗口 正如你所见,黑色三角形显示得很好,但没有纹理

  • 我一直试图让纹理在opengl 3.1下工作,在ubuntu 13.04上运行的intelHD图形2000/3000显卡上。我遇到的问题是纹理要么不加载,我试图纹理的基本三角形变成黑色,要么纹理中的一些颜色会加载,但不会加载整个图像。我使用原始图像文件作为源或使用libjpeg加载jpeg得到相同的结果。 我的着色器如下所示: 创建纹理glGenTexture(1, 还有渲染功能 几何和纹理坐标

  • 在理想情况下,如果屏幕分辨率为1024x768,那么在给定时刻只需要786432 texel,2兆字节的内存就足够了。但在现实世界中,有管理成本,所以纹理需要更多的内存。 纹理流可以降低纹理的内存成本,也就是说,在给定时刻并不需要所有纹理的mipmap。纹理需要0级mipmap,因为它靠近相机,如果它离当前相机很远,5到11级mipmap可能就足够了。相机在场景中移动一段时间,一些mipmap可以

  • 在andrid上的opengl es中,当我将两个纹理相邻放置时,会有一个轻微的接缝,可以看到它们后面绘制的对象。基本上看起来是一个小差距。我把范围缩小到了地图上 glTexParameteri(GL_纹理_2D、GL_纹理_最小过滤器、GL_线性_MIPMAP_线性);glTexParameteri(GL_纹理_2D、GL_纹理_MAG_过滤器、GL_线性); 如果我将它们都设置为距接缝最近的G

  • 所以最近我开始阅读OpenGL维基文章。这就是我在这里描述OpenGL纹理的方式。不过,有几点尚不清楚。 以下陈述是真的、假的还是视情况而定? 将两个纹理绑定到同一个纹理单元是不可能的。 将两个采样器绑定到同一个纹理单元是不可能的。 将一个纹理绑定到两个不同的纹理单元是不可能的。 将一个采样器绑定到两个不同的纹理单元是不可能的。 应用程序有责任明确将什么采样器类型传递给什么统一变量。 着色器程序有