2016-02-07 62 views
0

我想繪製出兩個紋理三角形,使用包含屏幕上的座標和紋理座標以及具有索引的IBO的VBO。但是我遇到了一個問題。無需使用着色器,無論我如何嘗試,我都可以獲得兩個三角形的正確大小和位置,但無紋理。使用着色器時,我會得到紋理,但是三角形尺寸錯誤,位置錯誤,並且沒有以任何方式使用紋理座標。使用VBO/IBO的OpenGL紋理三角形

創建紋理

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

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

這使代碼給我的世界座標和紋理座標:

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

生成我緩衝器

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

使用着色器繪製功能

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

結果 With shader

繪圖功能,無需渲染 (上面的代碼也可以得到相同的結果,這一個,如果我取消鏈接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

頂點着色器

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

片段着色器

#version 330 

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

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

在這一點上,我不知道如何繼續。我在這裏或任何地方找不到任何有助於我的事情。我已經嘗試了很多東西,我可能會使用某些不贊成使用的東西,或者做一些不受支持的東西,但我無法弄清楚是什麼。

回答

0

我可以看到幾個問題:

  1. 在固定的功能,你必須明確地調用glEnable(GL_TEXTURE_2D)告訴GL您當前綁定的2D紋理應適用(分別爲每個紋理單元) 。

  2. 頂點着色器不會根據變換狀態變換頂點。所有與矩陣相關的GL功能(如glOrtho,glTranslate,glMatrixMode)均已棄用。你必須使用自己的矩陣函數(或像glm這樣的庫),並通過制服(或其他方法)將矩陣提供給着色器。在兼容性配置文件中,您還可以使用GLSL內置制服,該制服允許您訪問那些不贊成使用的功能的舊內置矩陣,但我強烈建議不要使用已棄用的功能。無論哪種情況,着色器都必須實際應用頂點和模型視圖轉換,這些轉換通常歸結爲矩陣矢量產品,如projection * modelView * vec4(pos,1)

  3. 你的屬性指針很奇怪,至少可以說。您對頂點位置使用0的偏移量,並且對於紋理座標的偏移量爲offsetof(...::worldCoord)。現在根據您的成員定義的順序,兩者都可能指向內存中完全相同的值,這將解釋您提到的「以任何方式使用紋理座標」的部分。

+0

非常感謝!我在使用glEnable時只是在粘貼代碼時錯過了它。我曾嘗試製作一個模型視圖/投影矩陣,但我似乎做了錯誤,或者在測試之前忘了刪除glMatrix函數,我不記得了。是的,他們是很奇怪的,出於某種原因,我認爲他們是一種跨步爭論或某種事情,那麼:: worldCoord會讓它跳過那部分。但我解決了這個問題,現在它使用了紋理的正確部分!只是投影離開。 – Asddev