Problems with Lib Rocket Open Core Renderer

Help with integrating libRocket into your engine and game

Problems with Lib Rocket Open Core Renderer

Postby nicoraf on Wed Oct 09, 2013 4:20 am

Hi all,

I am having problems using librocket using the following OpenGL core render interface.
I am trying to run a simple example, that that is a file: tutorial.rml , tutorial.rcss , template.rml and rkt.rcss .

And it doesn't render the textures, I think that is an issue caused by an incorrect handling of textures in this renderer.

I am using the lastest development version of librocket.

Any help or suggestions are appreciated.

Thanks,
Nicolas

Code: Select all

#define GLEW_STATIC
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>


#include "ShellRenderInterfaceOpenGL.h"
#include <Rocket/Core.h>

#define GL_CLAMP_TO_EDGE 0x812F


enum GLT_SHADER_ATTRIBUTE { GLT_ATTRIBUTE_VERTEX = 0, GLT_ATTRIBUTE_COLOR, GLT_ATTRIBUTE_NORMAL,
                                    GLT_ATTRIBUTE_TEXTURE0, GLT_ATTRIBUTE_TEXTURE1, GLT_ATTRIBUTE_TEXTURE2, GLT_ATTRIBUTE_TEXTURE3,
                                    GLT_ATTRIBUTE_LAST};


ShellRenderInterfaceOpenGL::ShellRenderInterfaceOpenGL()
{
   if( ! prog.compileShaderFromFile("shaders/guirenderer.vert",GLSLShader::VERTEX) )
   {
      printf("Vertex shader failed to compile!\n%s",
         prog.log().c_str());
      exit(1);
   }

   if( ! prog.compileShaderFromFile("shaders/guirenderer.frag",GLSLShader::FRAGMENT))
   {
      printf("Fragment shader failed to compile!\n%s",
         prog.log().c_str());
      exit(1);
   }

   //prog.bindAttribLocation(GLT_ATTRIBUTE_VERTEX, "vVertex");
   //prog.bindAttribLocation(GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");
   //prog.bindAttribLocation(GLT_ATTRIBUTE_COLOR, "vColor");

   if( ! prog.link() )
   {
      printf("Shader program failed to link!\n%s",
         prog.log().c_str());
      exit(1);
   }

    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    glGenBuffers(1, &m_ebo);
    glGenBuffers(1, &m_vbo);

    glBindVertexArray(m_vao);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
   
   prog.link();
   //m_shader->bindProgram();
    // vertices that will be uploaded.
    size_t buffer_offset = 0;

   GLint pos_attrib = glGetAttribLocation(prog.getHandle(), "position");
    glEnableVertexAttribArray(pos_attrib);
    glVertexAttribPointer(
        pos_attrib,
        2,
        GL_FLOAT,
        GL_FALSE,
        sizeof(Rocket::Core::Vertex),
        (const GLvoid*)buffer_offset
    );

    buffer_offset += sizeof(float) * 2;

    GLint color_attrib = glGetAttribLocation(prog.getHandle(), "color");

    glEnableVertexAttribArray(color_attrib);
    glVertexAttribPointer(
        color_attrib,
        4,
        GL_UNSIGNED_BYTE,
        GL_TRUE,
        sizeof(Rocket::Core::Vertex),
        (const GLvoid*)buffer_offset
    );
    buffer_offset += sizeof(uint32_t);

    GLint texcoord_attrib = glGetAttribLocation(prog.getHandle(), "texcoord");
    glEnableVertexAttribArray(texcoord_attrib);
    glVertexAttribPointer(
        texcoord_attrib,
        2,
        GL_FLOAT,
        GL_FALSE,
        sizeof(Rocket::Core::Vertex),
        (const GLvoid*)buffer_offset
    );

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

    uint8_t red = 255;
    uint8_t green = 255;
    uint8_t blue = 255;
    uint8_t alpha = 255;
    int32_t color = red | (green << 8) | (blue << 16) | (alpha << 24);

    GLubyte imageData = color;

    glActiveTexture(GL_TEXTURE0);

    glGenTextures(1, &m_whiteTexture);
    glBindTexture(GL_TEXTURE_2D, m_whiteTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &imageData);
}

void ShellRenderInterfaceOpenGL::SetViewport(int width, int height)
{
     m_width = width;
    m_height = height;

    m_ortho = glm::ortho(0.0f, float(m_width), float(m_height), 0.0f, -1.0f, 1.0f);
}

// Called by Rocket when it wants to render geometry that it does not wish to optimise.
void ShellRenderInterfaceOpenGL::RenderGeometry(Rocket::Core::Vertex* vertices, int ROCKET_UNUSED(num_vertices), int* indices, int num_indices, const Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation)
{
    //glActiveTexture(GL_TEXTURE0);

    if (!texture) {
        glBindTexture(GL_TEXTURE_2D, m_whiteTexture);
    } else {
        glBindTexture(GL_TEXTURE_2D, GLuint(texture));
    }

   prog.use();

    glm::mat4 view = glm::translate(glm::mat4(), glm::vec3(translation.x, translation.y, 0.0f));

    glm::mat4 mvp = m_ortho * view;

   int mvpLoc = glGetUniformLocation(prog.getHandle(), "mvp");
    glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &mvp[0][0]);

    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);

    glBufferData(
        GL_ELEMENT_ARRAY_BUFFER,
        num_indices * sizeof(indices),
        indices,
        GL_DYNAMIC_DRAW
    );

    // finally upload everything to the actual vbo
    glBufferData(
        GL_ARRAY_BUFFER,
        sizeof(Rocket::Core::Vertex) * num_indices,
        vertices,
        GL_DYNAMIC_DRAW
    );

    ////////////////////////////////FINALLY RENDER IT ALL //////////////////////////////////////////
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   prog.use();

    glDrawElements(
        GL_TRIANGLES,
        num_indices,
        GL_UNSIGNED_INT,
        (const GLvoid*)0
    );

    //m_shader->unbindProgram();
   
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
   

    glDisable(GL_BLEND);
}

// Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future.      
Rocket::Core::CompiledGeometryHandle ShellRenderInterfaceOpenGL::CompileGeometry(Rocket::Core::Vertex* ROCKET_UNUSED(vertices), int ROCKET_UNUSED(num_vertices), int* ROCKET_UNUSED(indices), int ROCKET_UNUSED(num_indices), const Rocket::Core::TextureHandle ROCKET_UNUSED(texture))
{
   return (Rocket::Core::CompiledGeometryHandle) NULL;
}

// Called by Rocket when it wants to render application-compiled geometry.      
void ShellRenderInterfaceOpenGL::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle ROCKET_UNUSED(geometry), const Rocket::Core::Vector2f& ROCKET_UNUSED(translation))
{
}

// Called by Rocket when it wants to release application-compiled geometry.      
void ShellRenderInterfaceOpenGL::ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle ROCKET_UNUSED(geometry))
{
}

// Called by Rocket when it wants to enable or disable scissoring to clip content.      
void ShellRenderInterfaceOpenGL::EnableScissorRegion(bool enable)
{
   if (enable)
      glEnable(GL_SCISSOR_TEST);
   else
      glDisable(GL_SCISSOR_TEST);
}

// Called by Rocket when it wants to change the scissor region.      
void ShellRenderInterfaceOpenGL::SetScissorRegion(int x, int y, int width, int height)
{
   glScissor(x, m_height - (y + height), width, height);
}

// Set to byte packing, or the compiler will expand our struct, which means it won't read correctly from file
#pragma pack(1)
struct TGAHeader
{
   char  idLength;
   char  colourMapType;
   char  dataType;
   short int colourMapOrigin;
   short int colourMapLength;
   char  colourMapDepth;
   short int xOrigin;
   short int yOrigin;
   short int width;
   short int height;
   char  bitsPerPixel;
   char  imageDescriptor;
};
// Restore packing
#pragma pack()

// Called by Rocket when a texture is required by the library.      
bool ShellRenderInterfaceOpenGL::LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source)
{
   Rocket::Core::FileInterface* file_interface = Rocket::Core::GetFileInterface();
   Rocket::Core::FileHandle file_handle = file_interface->Open(source);
   if (!file_handle)
   {
      return false;
   }
   
   file_interface->Seek(file_handle, 0, SEEK_END);
   size_t buffer_size = file_interface->Tell(file_handle);
   file_interface->Seek(file_handle, 0, SEEK_SET);
   
   char* buffer = new char[buffer_size];
   file_interface->Read(buffer, buffer_size, file_handle);
   file_interface->Close(file_handle);

   TGAHeader header;
   memcpy(&header, buffer, sizeof(TGAHeader));
   
   int color_mode = header.bitsPerPixel / 8;
   int image_size = header.width * header.height * 4; // We always make 32bit textures
   
   if (header.dataType != 2)
   {
      Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24/32bit uncompressed TGAs are supported.");
      return false;
   }
   
   // Ensure we have at least 3 colors
   if (color_mode < 3)
   {
      Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24 and 32bit textures are supported");
      return false;
   }
   
   const char* image_src = buffer + sizeof(TGAHeader);
   unsigned char* image_dest = new unsigned char[image_size];
   
   // Targa is BGR, swap to RGB and flip Y axis
   for (long y = 0; y < header.height; y++)
   {
      long read_index = y * header.width * color_mode;
      long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * color_mode;
      for (long x = 0; x < header.width; x++)
      {
         image_dest[write_index] = image_src[read_index+2];
         image_dest[write_index+1] = image_src[read_index+1];
         image_dest[write_index+2] = image_src[read_index];
         if (color_mode == 4)
            image_dest[write_index+3] = image_src[read_index+3];
         else
            image_dest[write_index+3] = 255;
         
         write_index += 4;
         read_index += color_mode;
      }
   }

   texture_dimensions.x = header.width;
   texture_dimensions.y = header.height;
   
   bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions);
   
   delete [] image_dest;
   delete [] buffer;
   
   return success;
}

// Called by Rocket when a texture is required to be built from an internally-generated sequence of pixels.
bool ShellRenderInterfaceOpenGL::GenerateTexture(Rocket::Core::TextureHandle& texture_handle, const Rocket::Core::byte* source, const Rocket::Core::Vector2i& source_dimensions)
{
   GLuint texture_id = 0;
   glGenTextures(1, &texture_id);
   if (texture_id == 0)
   {
      printf("Failed to generate textures\n");
      return false;
   }

   glBindTexture(GL_TEXTURE_2D, texture_id);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

   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_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, source_dimensions.x, source_dimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, source);

   texture_handle = (Rocket::Core::TextureHandle) texture_id;

   return true;
}

// Called by Rocket when a loaded texture is no longer required.      
void ShellRenderInterfaceOpenGL::ReleaseTexture(Rocket::Core::TextureHandle texture_handle)
{
   glDeleteTextures(1, (GLuint*) &texture_handle);
}





Code: Select all

#ifndef ROCKETSHELLRENDERINTERFACE_H
#define ROCKETSHELLRENDERINTERFACE_H

#include <Rocket/Core/RenderInterface.h>

#include "GLSLProgram.h"

/**
   Low level OpenGL render interface for Rocket
   @author Peter Curry
 */

class ShellRenderInterfaceOpenGL : public Rocket::Core::RenderInterface
{
private:
   GLSLProgram prog;

   int m_width;
    int m_height;

    GLuint m_whiteTexture;

    GLuint m_vao; // vertex array object
    GLuint m_vbo; // vertex buffer object
    GLuint m_ebo; // element buffer object

    glm::mat4 m_ortho;

public:
   ShellRenderInterfaceOpenGL();

    /**
     * @p width width of viewport
     * @p height height of viewport
     */
    void SetViewport(int width, int height);

   /// Called by Rocket when it wants to render geometry that it does not wish to optimise.
   virtual void RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation);

   /// Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future.
   virtual Rocket::Core::CompiledGeometryHandle CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture);

   /// Called by Rocket when it wants to render application-compiled geometry.
   virtual void RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation);
   /// Called by Rocket when it wants to release application-compiled geometry.
   virtual void ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry);

   /// Called by Rocket when it wants to enable or disable scissoring to clip content.
   virtual void EnableScissorRegion(bool enable);
   /// Called by Rocket when it wants to change the scissor region.
   virtual void SetScissorRegion(int x, int y, int width, int height);

   /// Called by Rocket when a texture is required by the library.
   virtual bool LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source);
   /// Called by Rocket when a texture is required to be built from an internally-generated sequence of pixels.
   virtual bool GenerateTexture(Rocket::Core::TextureHandle& texture_handle, const Rocket::Core::byte* source, const Rocket::Core::Vector2i& source_dimensions);
   /// Called by Rocket when a loaded texture is no longer required.
   virtual void ReleaseTexture(Rocket::Core::TextureHandle texture_handle);

};

#endif


nicoraf
 
Posts: 1
Joined: Sun Sep 29, 2013 10:19 pm

Return to Engine Integration


cron