【问题标题】:C++ Texture not displaying correctly: Merging into 1 colourC++ 纹理未正确显示:合并为 1 种颜色
【发布时间】:2017-04-28 13:36:33
【问题描述】:

我正在尝试对 VBO/VAO 模型立方体进行纹理处理。立方体肯定是正确渲染/绘制的,据我所知,我正在做加载纹理所需的一切。

但是,在应用纹理时,它似乎取纹理中所有颜色的平均值,然后将该平均值应用于整个立方体。这会导致它看起来是用普通的常规颜色“绘制”的,如下面的屏幕截图所示:

这是纹理;

我不知道为什么会这样。下面是我的 init、loadTexture 和 display 函数的代码(我没有写 loadTexture 函数):

初始化函数 (只显示立方体+纹理相关的代码) 无效初始化(无效){ . . . pyramidTexture = TextureLoader::fiLoadTexture(wstring(L"Common\Resources\Textures\Sandstone.png"));

// Setup VAO for pyramid object
    glGenVertexArrays(1, &pyramidVAO);
    glBindVertexArray(pyramidVAO);

// Setup VBO for vertex position data
    glGenBuffers(1, &pyramidVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pyramidVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidVertices), pyramidVertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0); // attribute 0 gets data from bound VBO (so assign vertex position buffer to attribute 0)

// Setup VBO for vertex colour data
    glGenBuffers(1, &pyramidColourBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pyramidColourBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidColours), pyramidColours, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, 0, (const GLvoid*)0); // attribute 1 gets colour data

    glGenBuffers(3, &pyramidTexCoordBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pyramidTexCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidTexCoordArray), pyramidTexCoordArray, GL_STATIC_DRAW);
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);

// Enable vertex position and colour + Texture attribute arrays
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(3);

// Setup VBO for face index array
    glGenBuffers(1, &pyramidIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramidIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidVertexIndices), pyramidVertexIndices, GL_STATIC_DRAW);

    glBindVertexArray(0);


    glEnable(GL_NORMALIZE); // If we scale objects, ensure normal vectors are re-normalised to length 1.0 to keep lighting calculations correct (see lecture notes)
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Best colour interpolation results
    .
    .
    .
}

加载纹理函数

GLuint TextureLoader::fiLoadTexture(const wstring& textureFilePath) {

    BOOL                fiOkay = FALSE;
    GLuint              newTexture = 0;
    fipImage            I;

// Convert wstring to const char*
    wstring_convert<codecvt_utf8<wchar_t>, wchar_t> stringConverter;

    string S = stringConverter.to_bytes(textureFilePath);
    const char *filename = S.c_str();


// Call FreeImage to load the image file
    fiOkay = I.load(filename);

    if (!fiOkay) {

            cout << "FreeImagePlus: Cannot open image file.\n";
            return 0;
    }

    fiOkay = I.flipVertical();
    fiOkay = I.convertTo24Bits();

    if (!fiOkay) {

            cout << "FreeImagePlus: Conversion to 24 bits successful.\n";
            return 0;
    }

    auto w = I.getWidth();
    auto h = I.getHeight();

    BYTE *buffer = I.accessPixels();

    if (!buffer) {

             cout << "FreeImagePlus: Cannot access bitmap data.\n";
             return 0;
    }


    glGenTextures(1, &newTexture);
    glBindTexture(GL_TEXTURE_2D, newTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, buffer);

    // Setup default texture properties
    if (newTexture) {

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }

    return newTexture;
}

显示功能

void display(void) {

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set viewport to the client area of the current window
    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

    // Get view-projection transform as a GUMatrix4
    GUMatrix4 T = mainCamera->projectionTransform() * mainCamera->viewTransform();

    if (principleAxes)
        principleAxes->render(T);

    if (texturedQuad)
            texturedQuad->render(T * GUMatrix4::translationMatrix(0.5f, 0.5f, 0.0f));


// Fixed function rendering (Compatability profile only) - use this since CGImport is written against OpenGL 2.1
    glUseProgram(0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMultMatrixf((const float*)mainCamera->projectionTransform().M);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glMultMatrixf((const float*)mainCamera->viewTransform().M);
    glMultMatrixf((const float*)GUMatrix4::translationMatrix(0.0f, -0.15f, 0.0f).M);

    glEnable(GL_TEXTURE_2D);

    glPolygonMode(GL_FRONT, GL_FILL);

    if (exampleModel)
        exampleModel->renderTexturedModel();

    glDisable(GL_TEXTURE_2D);

    //Define position and direction (so appear at fixed point in scene)
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

    // enable texturing
    glEnable(GL_TEXTURE_2D);


    glEnable(GL_LIGHTING);


    glEnable(GL_LIGHT0);
//
// Pyramid VBO rendering
//

    // Use basic shader for rendering pyramid (we'll look at this in more detail next week)
    glUseProgram(basicShader);

    static GLint mvpLocationPyramid = glGetUniformLocation(basicShader, "mvpMatrix");

    glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(T.M));

    GUMatrix4 pyramidModelTransform = GUMatrix4::translationMatrix(-5.75f, 0.0f, 0.0f) * GUMatrix4::scaleMatrix(2.0f, 2.0f, 2.0f);
    GUMatrix4 mvpPyramid = T * pyramidModelTransform;
    glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(mvpPyramid.M));

    // Bind VAO that contains all relevant pyramid VBO buffer and attribute pointer bindings
    glBindVertexArray(pyramidVAO);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, pyramidTexture);
    // Draw pyramid
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (const GLvoid*)0);

    // Unbind pyramid VAO (or bind another VAO)
    glBindVertexArray(0);


    glutSwapBuffers();
}

我已经尝试修复这个问题几个小时了,但没有任何运气,因此我们将非常感谢任何支持!!!

编辑:在 VAO 属性 + 着色器中添加

VAO 设置

// Per-vertex position vectors
static float pyramidVertices[32] =
{
  //Front
  0.0f, 0.0f, 0.0f, 1.0f,   //BtmLeft
  1.0f, 0.0f, 0.0f, 1.0f,   //BtmRight
  1.0f, 1.0f, 0.0f, 1.0f,   //TopRight
  0.0f, 1.0f, 0.0f, 1.0f,   //TopLeft
  //Back
  0.0f, 1.0f, 1.0f, 1.0f,   //TopLeft
  1.0f, 1.0f, 1.0f, 1.0f,   //TopRight
  1.0f, 0.0f, 1.0f, 1.0f,   //BottomRight
  0.0f, 0.0f, 1.0f, 1.0f    //BottomLeft
};


// Per-vertex colours (RGBA) floating point values
static float pyramidColours[32] =
{
    1.0f, 0.0f, 0.0f, 1.0f,
    0.0f, 1.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f,
    1.0f, 0.0f, 1.0f, 1.0f,
    0.0f, 1.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f,
    1.0f, 0.0f, 1.0f, 1.0f,
    1.0f, 0.0f, 0.0f, 1.0f
};

// 5 faces each with 3 vertices (each face forms a triangle)
static unsigned short pyramidVertexIndices[36] =
{
    //Front
    0, 3, 2,
    2, 1, 0,
    //Right
    4, 3, 0,
    0, 7, 4,
    //Back
    4, 7, 6,
    6, 5, 4, 
    //Top
    4, 5, 3,
    3, 5, 2,
    //Left
    2, 5, 1,
    1, 5, 6,
    //Bottom
    6, 7, 0, 
    0, 1, 6
};


static unsigned short pyramidTexCoordArray[24] =
{
    -1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, 1.0f, -1.0f,
    -1.0f, 1.0f, -1.0f,
    -1.0f, -1.0f, 1.0f,
    1.0f, -1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f
};

顶点着色器

#version 330

uniform mat4 mvpMatrix;

layout (location=0) in vec4 vertexPos;
layout (location=3) in vec2 vertexTexCoord;

out vec2 texCoord;

void main(void) {

    mat4 M;
    M[0] = vec4(1.0);

    ivec2 a = ivec2(1, 2);
    //vec3 b = vec3(2.0, 4.0, 1.0) + a;

    texCoord = vertexTexCoord;
    gl_Position = mvpMatrix * vertexPos;
}

片段着色器

#version 330

uniform sampler2D texture;

in vec2 texCoord;

layout (location=0) out vec4 fragColour;

void main(void) {

    vec4 texColor = texture2D(texture, texCoord);
    fragColour = texColor;

}

【问题讨论】:

  • 看不到您使用的纹理坐标和着色器,我们无能为力。
  • 能否提供网格数据和着色器源?
  • 抱歉,我知道我忘记了什么。数据已通过着色器添加到底部
  • 看起来好像 uv 坐标在表面上是恒定的。
  • 是的,我对坐标有点困惑(我的朋友纹理工作,所以他让我借用他的代码,我会在纹理工作时对坐标进行排序!:))

标签: c++ opengl textures vbo vao


【解决方案1】:

您将数据定义为unsigned short

static unsigned short pyramidTexCoordArray[24]

但必须是float

【讨论】:

  • 必须是?如果使用 GL_UNSIGNED_SHORT 会怎样?
  • OP 用浮点数据初始化它并将其解释为浮点数,实际上存储负值,所以是的,它必须是float
  • 这解决了我的问题!非常感谢!
【解决方案2】:

有很多奇怪的东西:

您正在为纹理坐标生成 3 个 VBO,但只使用了一个。除非 pyramidTexCoordBuffer 是 GLuint[3] 类型(我认为这不是由于 &),否则你写的越界。

编辑:这是指glGenBuffers(3, &amp;pyramidTexCoordBuffer); 行,它分配3 个缓冲区并将它们存储在三个连续的GLuint 变量中,从pyramidTexCoordBuffer 开始。因为pyramidTexCoordBuffer 很可能是GLuintpyramidTexCoordBuffer[1]pyramidTexCoordBuffer[2] 指的是未分配的内存。

pyramidTexCoordArray 数组指定为unsigned short,但您正在向其写入浮点数。既然是无符号的,至少负数会消失。

另外,你用

告诉 OpenGL
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);

数据类型为GL_FLOAT(不是)并且每个顶点有两个浮点数(但数据每个顶点有3个元素)的行:

【讨论】:

  • 他没有使用 3 个 VBO 作为纹理坐标,是吗?他正在使用 3 个 VBO,但用于不同的数据。
  • 如果我正确理解 VAO/VBO,我使用 1 个 VBO 来存储顶点位置,1 个 VBO 用于存储颜色,1 个用于 TextureCoords。但是将 unsigned short 更改为 float 已经修复了纹理现在正确显示的问题,非常感谢!我也不确定为什么(或是否)我需要 3 组坐标(我认为纹理坐标是 u,v 所以我删除了第三个值,它似乎仍然有效。现在只需要计算出正确的坐标 :))
  • 我指的是这一行:glGenBuffers(3, &amp;pyramidTexCoordBuffer);,它分配 3 个缓冲区并将它们存储在三个连续的 GLuint 变量中,从 pyramidTexCoordBuffer 开始。因为pyramidTexCoordBuffer 很可能是GLuintpyramidTexCoordBuffer[1]pyramidTexCoordBuffer[2] 指的是未分配的内存。我也将此添加到问题中。
  • 我的眼睛好像错过了,nvm :3
猜你喜欢
  • 2011-08-06
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
  • 2012-09-30
相关资源
最近更新 更多