Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Sprite Batching attempt programmable pipeline, VBOs nothing shown

Threaded View

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8

    Sprite Batching attempt programmable pipeline, VBOs nothing shown

    I'm losing my hair over this, I've been scrounging the net for some good non-fixed pipeline examples of how to implement sprite batching so that I can efficiently render thousands of sprites. Someone gave me some code that looks wonderful and exactly like what I need, but I can't figure out why absolutely nothing is being shown on-screen. I'm using SDL2 and i use that (not shown) to init a 3.0 GL context which works great for other things, but this does not. I even tried decoupling my image loading stuff from it, and just create a junk checkboard image in it.

    The only thing I can think of is that my offsets aren't specified correctly, but I've gone through them several times and can't find anything wrong. All I want to do is be able to see 1 sprite. Then it should be easy to take it from there, with this code...

    It doesn't assert, the shaders compile fine, etc..so I don't know what's going on. And it isn't a hidden color because I tried disabling glClearColor or setting it to something else.

    And yeah, I'm very new to opengl.

    Any help on pointing me in the right direction would be greatly appreciated, I simply cannot find material that covers this exact topic.

    Code :
    void Game::init()
    {
       glewInit();
        glClearColor(1.f, 1.f, 1.f, 1.0f);
     
        glViewport(0, 0, SCREEN_W, SCREEN_H);
     
        tick();
        shutdown();
    }
     
    /* Each vertex is:
     * two floats for the 2d coordinate
     * four u8s for the color
     * two f32s for the texcoords
     * the vbo contains data of the aforementioned elements interleaved.
     * Each sprite has four vertices.
     */
    typedef float spriteVertex[5];
    GLuint new_vao = 0;
    GLuint new_vbo = 0;
    GLuint new_ebo = 0;
    GLuint new_vs;
    GLuint new_fs;
    GLuint new_sp;
    typedef uint32_t u32;
    typedef float f32;
     
     
    GLuint tex;
    static int spriteCount = 1;
    void initGL() {
        //////////////////// create texture, checkerboard texture
        glGenTextures( 1, &tex );
        glActiveTexture( GL_TEXTURE0 );
        glBindTexture( GL_TEXTURE_2D, tex );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        float pixels[] = {
            0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
        };
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels );
     
     
     
     
     
     
     
        //////////////////////
     
        glGenVertexArrays(1, &new_vao);
        glBindVertexArray(new_vao);
     
        glGenBuffers(1,&new_vbo);
        glBindBuffer(GL_ARRAY_BUFFER,new_vbo);
        glBufferData(
            GL_ARRAY_BUFFER,
            spriteCount * 4 * sizeof(spriteVertex),
            NULL,
            GL_DYNAMIC_DRAW);
     
        GLenum err = glGetError();
        if (err)
        {
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            assert(0);
        }
     
        std::vector<u32> indicesv;
     
        // prepare and upload indices as a one time deal
        const u32 indices[] = { 0, 1, 2, 0, 2, 3 }; // pattern for a triangle array
        // for each possible sprite, add the 6 index pattern
        for (size_t j = 0; j < spriteCount; j++)
        {
            for (size_t i = 0; i < sizeof(indices)/sizeof(*indices); i++)
            {
                indicesv.push_back(4*j + indices[i]);
            }
        }
     
        glGenBuffers(1,&new_ebo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,new_ebo);
        glBufferData(
            GL_ELEMENT_ARRAY_BUFFER,
            indicesv.size()*sizeof(u32),
            indicesv.data(),
            GL_STATIC_DRAW);
     
        err = glGetError();
        if (err)
        {
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
            assert(0);
        }
     
     
        static const char* vshader_src =
            "#version 120\n"
     
            "attribute vec2 position;"
     
            "attribute vec2 texcoord;"
            "varying vec2 frag_texcoord;"
     
            "attribute vec4 color;"
            "varying vec4 frag_color;"
     
            "void main() {"
            "    gl_Position = vec4( position, 0.0, 1.0 );"
            "    frag_texcoord = texcoord;"
            "    frag_color = color;"
            "}";
     
        static const char* fshader_src =
            "#version 120\n"
     
            "varying vec2 frag_texcoord;"
            "varying vec4 frag_color;"
     
            "uniform sampler2D sampler;"
     
            "void main(void) {"
            "    gl_FragColor = frag_color * texture2D(sampler,frag_texcoord);"
            "}";
     
        GLint status;
        GLchar infolog[1024];
        GLsizei infolog_len;
     
        new_vs = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(new_vs, 1, &vshader_src, NULL);
        glCompileShader(new_vs);
     
        glGetShaderiv(new_vs,GL_COMPILE_STATUS,&status);
     
        if (status == GL_FALSE)
        {
            glGetShaderInfoLog(new_vs,sizeof(infolog),&infolog_len,infolog);
            std::cout
                    << "Failed to compile SpriteBatch vertex shader."
                    << std::endl
                    << infolog << std::endl;
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
            glDeleteShader(new_vs);
            assert(0);
        }
     
        new_fs = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(new_fs, 1, &fshader_src, NULL);
        glCompileShader(new_fs);
     
        glGetShaderiv(new_fs,GL_COMPILE_STATUS,&status);
     
        if (status == GL_FALSE)
        {
            glGetShaderInfoLog(new_fs,sizeof(infolog),&infolog_len,infolog);
            std::cout
                    << "Failed to compile SpriteBatch fragment shader."
                    << std::endl
                    << infolog << std::endl;
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
            glDeleteShader(new_vs);
            glDeleteShader(new_fs);
            assert(0);
        }
     
        new_sp = glCreateProgram();
        glAttachShader(new_sp, new_vs);
        glAttachShader(new_sp, new_fs);
        glLinkProgram(new_sp);
     
        glGetProgramiv(new_sp,GL_LINK_STATUS,&status);
     
        if (status == GL_FALSE)
        {
            glGetProgramInfoLog(new_sp,sizeof(infolog),&infolog_len,infolog);
            std::cout << "Failed to link SpriteBatch shader program."
                      << std::endl
                      << infolog << std::endl;
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
            glDeleteShader(new_vs);
            glDeleteShader(new_fs);
            glDeleteProgram(new_sp);
            assert(0);
        }
     
        glValidateProgram(new_sp);
        glGetProgramiv(new_sp,GL_VALIDATE_STATUS,&status);
     
        if (status == GL_FALSE)
        {
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
            glDeleteShader(new_vs);
            glDeleteShader(new_fs);
            glDeleteProgram(new_sp);
            assert(0);
        }
     
        size_t buffer_offset = 0;
     
        GLint pos_attrib = glGetAttribLocation(new_sp, "position");
        glEnableVertexAttribArray(pos_attrib);
        glVertexAttribPointer(
            pos_attrib,
            2,
            GL_FLOAT,
            GL_FALSE,
            sizeof(spriteVertex),
            (const GLvoid*)buffer_offset);
        buffer_offset += sizeof(f32) * 2;
     
        GLint color_attrib = glGetAttribLocation(new_sp, "color");
     
        glEnableVertexAttribArray(color_attrib);
        glVertexAttribPointer(
            color_attrib,
            4,
            GL_UNSIGNED_BYTE,
            GL_TRUE,
            sizeof(spriteVertex),
            (const GLvoid*)buffer_offset);
        buffer_offset += sizeof(u32);
     
        GLint texcoord_attrib = glGetAttribLocation(new_sp, "texcoord");
        glEnableVertexAttribArray(texcoord_attrib);
        glVertexAttribPointer(
            texcoord_attrib,
            2,
            GL_FLOAT,
            GL_FALSE,
            sizeof(spriteVertex),
            (const GLvoid*)buffer_offset);
     
        err = glGetError();
        if (err)
        {
     
            glDeleteVertexArrays(1,&new_vao);
            glDeleteBuffers(1,&new_vbo);
            glDeleteBuffers(1,&new_ebo);
     
            assert(0);
        }
    }

    ACTUAL RENDER CODE, EACH FRAME:
    Code :
    void render() {
         // vertices that will be uploaded.
        spriteVertex vertices[4];
     
        // transform vertices and copy them to the buffer
        vertices[0][0] = vertices[0][1] = vertices[1][0] = vertices[3][1] = 0;
        /*    vertices[1][1] = f32(tex.size().y()) * std::abs(uvrect.height);
            vertices[2][0] = f32(tex.size().x()) * std::abs(uvrect.width);
            vertices[2][1] = f32(tex.size().y()) * std::abs(uvrect.height);
            vertices[3][0] = f32(tex.size().x()) * std::abs(uvrect.width);
            */
     
        vertices[1][1] = f32(1.0f);
        vertices[2][0] = f32(1.0f);
        vertices[2][1] = f32(1.0f);
        vertices[3][0] = f32(1.0f);
     
     
        // copy color to the buffer
        // copy color to the buffer
        for (size_t i = 0; i < sizeof(vertices)/sizeof(*vertices); i++)
        {
            uint32_t* colorp = reinterpret_cast<uint32_t*>(&vertices[i][2]);
            //        *colorp = color.bgra;
            uint8_t red = 120;
            uint8_t blue = 0;
            uint8_t green = 120;
            uint8_t alpha = 255;
            int32_t color = red | (green << 8) | (blue << 16) | (alpha << 24);
            *colorp = color;
        }
     
        // copy texcoords to the buffer
        vertices[0][3] = vertices[1][3] = 0.0f;
        vertices[0][4] = vertices[3][4] = 1.0f;
        vertices[1][4] = vertices[2][4] = 0.0f;
        vertices[2][3] = vertices[3][3] = 1.0f;
     
        // finally upload everything to the actual vbo
        glBindBuffer(GL_ARRAY_BUFFER,new_vbo);
        glBufferSubData(
            GL_ARRAY_BUFFER,
            0,
            spriteCount * sizeof(vertices),
            vertices);
     
     
     
     
     
        //////////////////////////////////////////////////////////////////////////////////////////
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,new_ebo);
        glBindBuffer(GL_ARRAY_BUFFER,new_vbo);
        glBindVertexArray(new_vao);
     
        glUseProgram(new_sp);
     
     
        glDrawElements(
            GL_TRIANGLES,
            6*(spriteCount), // 6 indices per 2 triangles
            GL_UNSIGNED_INT,
            (const GLvoid*)0);
     
        glUseProgram(0);
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
     
        glDisable(GL_BLEND);
    }
     
    double fps = 0.0;
     
    void Game::tick()
    {
        Uint32 startTime = SDL_GetTicks();
        int frameCount = 0;
     
        initGL();
        while (m_running) {
            fps =(frameCount / float(SDL_GetTicks() - startTime)) * 1000;
     
            handleEvents();
     
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            render();
     
     
            SDL_GL_SwapWindow(m_window);
     
            ++frameCount;
        }
     
    shutdown:
        shutdown();
    }
    Last edited by Predator105; 01-11-2013 at 11:03 AM. Reason: fix vertex coords

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •