Issues with VBO to texture tiles on a grid
Unsolved
Game Development
-
Hello everyone, i've got an issue using Qt 5, C++ and OepnGL. I'm using instanced drawing to draw a tiles grid on my window. To assign the correct texture on each tile, I use a VBO with divisor to send one value for each tile instance. But i've got trouble with initializing my VBO, and more troubles modifying it with glMapBufferRange. Her is my code and some explanations:
// Method called after initializeGL() to set VAO and VBO. My VBO is here filled with 0, which corresponds in my Fragment Shader to a green color. // I tried to change the binding index to 5 (here and in my Vertex Shader of course) just to test, some issues are resolved but others appears... it seems strange void MainWindow::loadVAO_VBO() { makeCurrent(); // VAO / VBO QVector<GLuint> texIndex; for ( uint i=0;i<m_numberOfTiles;++i ) texIndex.append(0); glGenVertexArrays(1, &m_vaoID); glBindVertexArray(m_vaoID); glCreateBuffers(1, &m_vboID); glBindBuffer(GL_ARRAY_BUFFER, m_vboID); glVertexAttribDivisor(0, 1); glNamedBufferStorage(m_vboID, m_numberOfTiles * sizeof(GLuint), texIndex.constData(), GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); glVertexArrayAttribFormat(m_vaoID, 0, // Attrib Index 1, GL_UNSIGNED_INT, GL_FALSE, 0); glVertexArrayAttribBinding(m_vaoID, 0, // Attrib Index 0); // Binding Index glVertexArrayVertexBuffer(m_vaoID, 0, // Binding Index m_vboID, (GLintptr)0, sizeof(GLuint)); glEnableVertexAttribArray(0); // Binding Index glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); }
// When user clicks on a tile on the screen, I change 0 to 1 in the VBO, so the Fragment Shader will change the green color to a texture. void MainWindow::mousePressEvent(QMouseEvent *e) { if ( e->buttons() & Qt::LeftButton ) { // here I get back the index of the value I want to modify in my VBO. No error here uint index = getTileIndex(m_overflewTile); // VERTICES VBO makeCurrent(); glFinish(); glBindBuffer(GL_ARRAY_BUFFER, m_vboID); // We get back the good pointer in our VBO void *data = glMapNamedBufferRange(m_vboID, // id index * sizeof(GLuint), // offset sizeof(GLuint), // size GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); // flags // We convert data in uint GLuint *buffer = (GLuint*)data; qDebug() << *buffer; // no error here, i get 0 or 1 when expected // We modify the value in the VBO *buffer = 1; //m_tilesMap[m_overflewTile] = 1; glUnmapNamedBuffer(m_vboID); glBindBuffer(GL_ARRAY_BUFFER, 0); } update(); }
And here are my 2 shaders:
// VERTEX SHADER #version 450 layout (location = 0) uniform float screenWidth;// In pixel layout (location = 1) uniform float screenHeight;// In pixel layout (location = 2) uniform float rectsSize; // In pixel // Here is my attrib index 0 the VBO uses. It will be used in Fragment Shader to texture the fragment layout (location = 0) in uint vs_in_texType; out vec2 texCoord; out uint vs_out_texType; void main() { vec3 origin = vec3(1.0, -1.0, 0.0); float rectW = 2.0*rectsSize / screenWidth; float rectH = rectW * screenWidth/screenHeight; // to make squares vec3[4] vertices = vec3[4](vec3( 0.0, -rectH, 0.0) - origin, vec3(rectW, -rectH, 0.0) - origin, vec3(rectW, 0.0, 0.0) - origin, vec3( 0.0, 0.0, 0.0) - origin); vec2[4] texCoords = vec2[4](vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0)); uint i = 0; if ( gl_VertexID <= 2 ) { i = gl_VertexID; } else if ( gl_VertexID == 3 ) { i = 0; } else if ( gl_VertexID == 4 ) { i = 2; } else if ( gl_VertexID == 5 ) { i = 3; } uint rectsInARow = uint(screenWidth) / uint(rectsSize); float xOffset = (gl_InstanceID % rectsInARow) * rectW; float yOffset = (gl_InstanceID / rectsInARow) * rectH; vec3 offset = vec3(xOffset, -yOffset, 0.0); texCoord = texCoords[i]; vs_out_texType = vs_in_texType; // We simply pass it to the Fragment Shader gl_Position = vec4(vertices[i] + offset, 1.0); }
// FRAGMENT SHADER #version 450 // I only have one texture but it contains several seamless textures in it layout (binding = 0) uniform sampler2D textu; in vec2 texCoord; flat in uint vs_out_texType; // Here we get our 0 or 1 from Vertex Shader out vec4 color; void main() { if (vs_out_texType == 0) color = vec4(0.3, 0.7, 0.4, 1.0); // green color else if (vs_out_texType == 1) color = texture(textu, vec2(texCoord.x / 6.0, texCoord.y / 3.0)); // Texture //else // if (vs_out_texture == 0) //color = vec4(0.3, 0.7, 0.4, 1.0); }
When I click on a tile, it correctly changes my value in the VBO to 1, but the value once arrived in the Vertex Shader seems to be more than 1000 000 000 (I made some tests !).
If someone can help me with this I'd be very grateful !
Thanks, Cixi