OpenGL 3.3 Renderer

Help with integrating libRocket into your engine and game

OpenGL 3.3 Renderer

Postby ReeferMan on Sat Aug 11, 2012 4:24 pm

Hey all,

I've been trying to implement an OpenGL 3.3 based libRocket renderer.

I've done a bit of research here and there. First I tried implementing it by using the compile/render/release geometry functions, this resulted into quite a slow rendering. What was worse is that releasing/compiling geometry while resizing a window would really kill the framerate.

The second attempt was by trying to stream the data to the GPU, which after some googling is supposedly done best by using glMapBufferRange. This is almost/partially working. So far the implementation I have is able to render the fonts, but the texture coordinates for the window seem to be bugged. The thing is that I believe this is due to some memory corruption probably taking place inside the code, instead of invalid texture coordinates.

Also, before anyone tells me to go visit a programming forum/graphics-dev forum. I think the question is better suited in here since it may have to do with me misunderstanding parts of libRocket.

So what is my question?
Can you spot anything wrong in the following code?

(Note that I am using my own wrappers around OpenGL, which work well, most functions align accordingly with the native OpenGL implementation's. Should anyone be interested into seeing these functions, then I could post them in here as well)

Code: Select all
/// Called by Rocket when it wants to render geometry that it does not wish to optimise.
void RenderInterface::RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle textureID, const Rocket::Core::Vector2f& translation) {
   // Texture handle.
   basix::GL::Texture *texture = NULL;

   // Determine if data is valid or not.
   if (!vertices || !num_vertices || !indices || !num_indices) {
      std::cout << "Invalid data passed to libRocket::RenderGeometry" << std::endl;
      return;
   }

   // Determine what render path to take.
   if (textureMap.find(textureID) != textureMap.end()) {
      texture = textureMap[textureID];
   }

   // Bind the GUI VAO.
   basix::GL::bindVertexArray(guiVA);

   // Orphan the vertex buffer.
   if (guiVertexStreamOffset + (sizeof(Rocket::Core::Vertex) * num_vertices) >= GL_GUI_BUFFER_SIZE * sizeof(Rocket::Core::Vertex)) {
      // Bind the gui Vertex VB.
      basix::GL::bindBuffer(GL_ARRAY_BUFFER, guiVertexVB);
      guiVertexVB->bufferData(GL_ARRAY_BUFFER, GL_GUI_BUFFER_SIZE * sizeof(Rocket::Core::Vertex), NULL, GL_STREAM_DRAW);

      // Setup the vertex attributes.
      guiVA->setVertexAttribute(0, 2, GL_FLOAT, GL_FALSE, sizeof(Rocket::Core::Vertex), GL_BUFFER_OFFSET(0));
      guiVA->setVertexAttribute(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Rocket::Core::Vertex), GL_BUFFER_OFFSET(sizeof(Rocket::Core::Vector2f)));
      guiVA->setVertexAttribute(2, 2, GL_FLOAT, GL_FALSE, sizeof(Rocket::Core::Vertex), GL_BUFFER_OFFSET(sizeof(Rocket::Core::Vector2f) + sizeof(Rocket::Core::Colourb)));

      // Reset the offset.
      guiVertexStreamOffset = 0;
   }

   // Bind the gui Vertex VB.
   basix::GL::bindBuffer(GL_ARRAY_BUFFER, guiVertexVB);

   // Map the buffer for write access.
   Rocket::Core::Vertex *mappedVertices = (Rocket::Core::Vertex*)guiVertexVB->mapBufferRange(GL_ARRAY_BUFFER, guiVertexStreamOffset, (sizeof(Rocket::Core::Vertex) * num_vertices), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);

   // Write to the buffer in case it was succesfully mapped.
   if (mappedVertices != NULL) {
//      memcpy(mappedVertices, vertices, sizeof(Rocket::Core::Vertex) * num_vertices);
      
      unsigned int temporaryOffset = 0;
      int i = 0;

      // Position.
      for(i = 0; i < num_vertices; i++) {
         mappedVertices[i].position.x = vertices[i].position.x;
         mappedVertices[i].position.y = vertices[i].position.y;

         mappedVertices[i].colour.red = vertices[i].colour.red;
         mappedVertices[i].colour.green  = vertices[i].colour.green;
         mappedVertices[i].colour.blue = vertices[i].colour.blue;
         mappedVertices[i].colour.alpha = vertices[i].colour.alpha;      
      
      //   mappedVertices[i].tex_coord.x = (1.0f / texture->getWidth()) * vertices[i].tex_coord.x;
      //   mappedVertices[i].tex_coord.y = (1.0f / texture->getHeight()) * vertices[i].tex_coord.y;
         mappedVertices[i].tex_coord.x = vertices[i].tex_coord.x;
         mappedVertices[i].tex_coord.y = vertices[i].tex_coord.y;
      }

   }

   // Unmap the buffer.
   guiVertexVB->UnmapBuffer(GL_ARRAY_BUFFER);
   basix::GL::bindBuffer(GL_ARRAY_BUFFER, NULL);

   // Bind the gui Index VB.
   basix::GL::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, guiIndiceVB);

   // Orphan the Index buffer.
   if (guiIndiceStreamOffset + (num_indices * sizeof(unsigned int)) >= GL_GUI_BUFFER_SIZE * sizeof(unsigned int)) {
      guiIndiceVB->bufferData(GL_ELEMENT_ARRAY_BUFFER, GL_GUI_BUFFER_SIZE * sizeof(unsigned int), NULL, GL_STREAM_DRAW);
      
      // Reset the offset.
      guiIndiceStreamOffset = 0;
   }

   // Map the buffer for writ e access.
   unsigned int *mappedIndices = (unsigned int*)guiIndiceVB->mapBufferRange(GL_ELEMENT_ARRAY_BUFFER, guiIndiceStreamOffset, (sizeof(unsigned int) * num_indices), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT  | GL_MAP_INVALIDATE_RANGE_BIT);

   // Write to the buffer in case it was succesfully mapped.
   if (mappedIndices != NULL) {
      for(int i = 0; i < num_indices; i++) {
         mappedIndices[i] = (guiVertexStreamOffset / sizeof(Rocket::Core::Vertex)) + (unsigned int)indices[i];
      }
   }
   
   // Unmap the buffer.
   guiIndiceVB->UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
   basix::GL::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);

   // Bind the VAO, texture and according shaders, then render the object.
   basix::GL::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, guiIndiceVB);

   // Translate euj.
   matModel   = glm::translate(glm::mat4(1.0), glm::vec3(translation.x, translation.y, 0.0f));
   matModelViewProjection   = matOrtho * matModel;

   // Determine render path.
   if (texture != NULL) {
      // Bind shader and Setup the uniform variables.
      basix::GL::bindShaderProgram(texturedProgram);
      texturedProgram->setUniform1i("textureA", 0);
      texturedProgram->setUniformMatrix4m("matModelViewProjection", (matModelViewProjection));

      // Bind the corresponding texture.
      glActiveTexture(GL_TEXTURE0 + 0);
      glBindTexture(GL_TEXTURE_2D, texture->getGpuID());
   } else {
      // Bind shader and Setup the uniform variables.
      basix::GL::bindShaderProgram(basicProgram);
      basicProgram->setUniformMatrix4m("matModelViewProjection", (matModelViewProjection));

      // Bind the corresponding texture.
      glActiveTexture(GL_TEXTURE0 + 0);
      glBindTexture(GL_TEXTURE_2D, 0);
   }

   // Render the elements.
   glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, (GLvoid*)(guiIndiceStreamOffset));

   // Increment the offsets.
   //guiVertexStreamOffset += num_vertices;
   guiVertexStreamOffset += (sizeof(Rocket::Core::Vertex) * num_vertices);
   guiIndiceStreamOffset += num_indices * sizeof(unsigned int);
}
ReeferMan
 
Posts: 4
Joined: Sat Aug 11, 2012 4:12 pm

Re: OpenGL 3.3 Renderer

Postby ReeferMan on Sun Aug 12, 2012 10:52 am

Shameless self bump for lack of better resources, seriously can't figure this out and have been at it well for over a few weeks. Sorry, but I would really appreciate the help :-)
ReeferMan
 
Posts: 4
Joined: Sat Aug 11, 2012 4:12 pm

Re: OpenGL 3.3 Renderer

Postby ReeferMan on Sun Aug 12, 2012 5:20 pm

I figured showing an example of what is currently onscreen may be of use as well.

Image
ReeferMan
 
Posts: 4
Joined: Sat Aug 11, 2012 4:12 pm

Re: OpenGL 3.3 Renderer

Postby Bdmtr on Wed Jan 20, 2016 3:53 am

Texture coordinates might be flipped around Y.
Bdmtr
 
Posts: 1
Joined: Wed Jan 20, 2016 3:26 am


Return to Engine Integration


cron