简体   繁体   English

使用VBO / IBO的OpenGL的纹理三角形

[英]Textured triangles with OpenGL using VBO/IBO

I'm trying to draw out two textured triangles to make a square using a VBO containing the coordinates on the screen and coordinates of the texture and an IBO with the indices. 我正在尝试使用一个VBO绘制两个带纹理的三角形,以形成一个正方形,该VBO包含屏幕上的坐标和纹理的坐标以及带有索引的IBO。 However I'm running into a problem. 但是我遇到了一个问题。 Without using a shader I get the correct size and position of the two triangles but no texture no matter how I try. 在不使用着色器的情况下,无论如何尝试,我都能获得两个三角形的正确大小和位置,但没有纹理。 With a shader I get a texture but the triangle is wrong size, in the wrong position and not using the texture coordinates in any way. 使用着色器时,我得到了纹理,但是三角形的尺寸错误,位置错误并且没有以任何方式使用纹理坐标。

Creating the texture 创建纹理

        glGenTextures(1, &texture);

        glBindTexture(GL_TEXTURE_2D, texture);

        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);

        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

        glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
                        texture_format, GL_UNSIGNED_BYTE, surface->pixels);

        glBindTexture(GL_TEXTURE_2D, NULL);

Filling the VBO and IBO (TileData is a struct with two size 2 arrays) 填充VBO和IBO (TileData是具有两个大小为2的数组的结构)

    indices.push_back(0);
    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(0);
    indices.push_back(2);
    indices.push_back(3);

    TileData tile;

    tile.texCoord[0] = 0 / imageSizeX;
    tile.texCoord[1] = 0 / imageSizeY;
    tile.worldCoord[0] = 0;
    tile.worldCoord[1] = 0;
    tiles.push_back(tile);

    tile.texCoord[0] = (0 + texWidth) / imageSizeX;
    tile.texCoord[1] = 0 / imageSizeY;
    tile.worldCoord[0] = 0 + texWidth;
    tile.worldCoord[1] = 0;
    tiles.push_back(tile);

    tile.texCoord[0] = (0 + texWidth) / imageSizeX;
    tile.texCoord[1] = (0 + texHeight) / imageSizeY;
    tile.worldCoord[0] = 0 + texWidth;
    tile.worldCoord[1] = 0 + texHeight;
    tiles.push_back(tile);

    tile.texCoord[0] = 0 / imageSizeX;
    tile.texCoord[1] = (0 + texHeight) / imageSizeY;
    tile.worldCoord[0] = 0;
    tile.worldCoord[1] = 0 + texHeight;
    tiles.push_back(tile);

This gives code gives me the world coordinates and texture coordinates: 这给出的代码给了我世界坐标和纹理坐标:

0, 0          0, 0
16, 0         0.25, 0
16, 16        0.25, 1
0, 16         0, 1

Generate my buffers 生成我的缓冲区

        glGenBuffers(1, &vboID);
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, tiles.size() * sizeof(TileData), &tiles[0], GL_STATIC_DRAW);

        glGenBuffers(1, &iboID);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID); 
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);

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

Draw function with shader 带着色器的绘图功能

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(camera.x, camera.x + 320, camera.y + 240, camera.y, -1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderHandler.programID);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    GLint texLocation = glGetUniformLocation(shaderHandler.programID, "tex");

    glUniform1i(texLocation, 0);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CGame::TileData), (GLvoid *)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CGame::TileData), (GLvoid*)offsetof(CGame::TileData, CGame::TileData::worldCoord));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID); 
    glDrawElements(GL_TRIANGLES, indices->size(), GL_UNSIGNED_INT, (GLvoid*)0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glBindTexture(GL_TEXTURE_2D, 0);

    SDL_GL_SwapWindow(window);

Result With shader 结果 与着色器

Draw function without shader (The above code can also get the same result as this one if I unlink the shaderprogram) 没有着色器的绘图功能 (如果我取消链接着色器程序 ,上面的代码也可以获得与这一结果相同的结果)

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glClientActiveTexture(GL_TEXTURE0);

    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glVertexPointer(2, GL_FLOAT, sizeof(CGame::TileData), (GLvoid*)0);
    glTexCoordPointer(2, GL_FLOAT, sizeof(CGame::TileData), (GLvoid*)offsetof(CGame::TileData, CGame::TileData::worldCoord));

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

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID); 
    glDrawElements(GL_TRIANGLES, indices->size(), GL_UNSIGNED_INT, (GLvoid*)0);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

    SDL_GL_SwapWindow(window);

Resulst Without shader Resulst 没有着色器

Vertex Shader 顶点着色器

#version 330
layout(location = 0) in vec2 vert;
layout(location = 1) in vec2 vertTexCoord;

out vec2 fragTexCoord;

void main() 
{
    fragTexCoord = vertTexCoord; 
    gl_Position = vec4(vert, 0, 1);
}

Fragment Shader 片段着色器

#version 330

uniform sampler2D tex; 
in vec2 fragTexCoord; 
out vec4 finalColor; 

void main() 
{
    finalColor = texture2D(tex, fragTexCoord);
}

At this point I've no idea how to continue. 在这一点上,我不知道如何继续。 I can't find anything that helps me on here or anywhere. 在这里或任何地方,找不到任何对我有帮助的东西。 I've tried so much things that I probably use something deprecated or doing something unsupported but I can't figure out what. 我已经做了很多尝试,以至于我可能使用了不赞成使用的功能或执行了不受支持的操作,但我不知道该怎么做。

I can see a couple of issues: 我可以看到几个问题:

  1. In the fixed function, you have to explicitely call glEnable(GL_TEXTURE_2D) to tell the GL that your currently bound 2D texture shall be applied (separately for each texture unit). 在固定函数中,必须显式调用glEnable(GL_TEXTURE_2D)告诉GL应应用当前绑定的2D纹理(每个纹理单元分别使用)。

  2. Your vertex shader does never transform the vertices according to your transform state. 顶点着色器永远不会根据变换状态来变换顶点。 All the matrix-related GL functions like glOrtho , glTranslate , glMatrixMode are deprecated. 不推荐使用所有与矩阵相关的GL函数,例如glOrthoglTranslateglMatrixMode You have to use your own matrix functions (or a library like glm) and supply the matrices to the shader via uniforms (or other means). 您必须使用自己的矩阵函数(或类似glm的库),并通过统一方式(或其他方式)将矩阵提供给着色器。 In a compatiblity profile, you could also use the GLSL builtin uniforms which allow you to access the old builtin matrices set with those deprecated functions, but I strongly recommend to not rely on deprecated functionality. 在兼容性配置文件中,您还可以使用GLSL内置制服,该制服允许您访问使用那些不推荐使用的功能设置的旧内置矩阵,但是我强烈建议不要依赖不推荐使用的功能。 In either case, your shader has to actually apply your vertex and modelview transformations, which typically boils down to matrix-vector products like projection * modelView * vec4(pos,1) . 无论哪种情况,着色器都必须实际应用顶点和modelview转换,通常可以归结为矩阵向量乘积,例如projection * modelView * vec4(pos,1)

  3. Your attribute pointers are weird, to say the least. 至少可以说,您的属性指针很奇怪。 You use an offset of 0 for the vertex positions, and and offset of offsetof(...::worldCoord) for the texture coordinates. 顶点位置使用偏移量0, 纹理坐标使用offsetof(...::worldCoord)偏移量。 Now depending on which order your members are defined, both might point to the exact same values in memory, which would explain the "and not using the texture coordinates in any way" part you mentioned. 现在,根据定义成员的顺序,这两个成员都可能指向内存中完全相同的值,这将解释您提到的“并且不以任何方式使用纹理坐标”部分。

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

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