0

I am working on a game with 8bit graphics. I provide a Pixelbuffer (OSXRenderer.pbo) to my gameloop to fill it up. Then texsubimage it onto a texture (OSXRenderer.ScreenTexture). The texture is rendered to the screen via a quad.

I got it working without problems with a RGB PBO (size: width*height*3). But now i want the pbo to be indexed color. So i load a palette into another texture (OSXRenderer.PaletteTexture) and changed my PBO. (size: width*height).

How i figure it should work is: PBO gets filled with noise (random uint8 0-63), Screentexture gets texsubimaged, and when rendering it onto the screen via quad, my fragmentshader replaces all the RED channel values with the corresponding colors from my palette and i get 8bit noise on the screen.

But i simply can't get it to work. I only get a black screen. If I set my fragcolor to the incoming screentexture(pbo) data i get red noise. Just as expected.

[EDIT] I tested the fragment-shaders "color"-variable values. And they are always 0.0 except alpha which is always 1.0

setup:

    static uint8 palette[] = {
        0x80,0x80,0x80, 0x00,0x00,0xBB, 0x37,0x00,0xBF, 0x84,0x00,0xA6,
        0xBB,0x00,0x6A, 0xB7,0x00,0x1E, 0xB3,0x00,0x00, 0x91,0x26,0x00,
        0x7B,0x2B,0x00, 0x00,0x3E,0x00, 0x00,0x48,0x0D, 0x00,0x3C,0x22,
        0x00,0x2F,0x66, 0x00,0x00,0x00, 0x05,0x05,0x05, 0x05,0x05,0x05,

        0xC8,0xC8,0xC8, 0x00,0x59,0xFF, 0x44,0x3C,0xFF, 0xB7,0x33,0xCC,
        0xFF,0x33,0xAA, 0xFF,0x37,0x5E, 0xFF,0x37,0x1A, 0xD5,0x4B,0x00,
        0xC4,0x62,0x00, 0x3C,0x7B,0x00, 0x1E,0x84,0x15, 0x00,0x95,0x66,
        0x00,0x84,0xC4, 0x11,0x11,0x11, 0x09,0x09,0x09, 0x09,0x09,0x09,

        0xFF,0xFF,0xFF, 0x00,0x95,0xFF, 0x6F,0x84,0xFF, 0xD5,0x6F,0xFF,
        0xFF,0x77,0xCC, 0xFF,0x6F,0x99, 0xFF,0x7B,0x59, 0xFF,0x91,0x5F,
        0xFF,0xA2,0x33, 0xA6,0xBF,0x00, 0x51,0xD9,0x6A, 0x4D,0xD5,0xAE,
        0x00,0xD9,0xFF, 0x66,0x66,0x66, 0x0D,0x0D,0x0D, 0x0D,0x0D,0x0D,

        0xFF,0xFF,0xFF, 0x84,0xBF,0xFF, 0xBB,0xBB,0xFF, 0xD0,0xBB,0xFF,
        0xFF,0xBF,0xEA, 0xFF,0xBF,0xCC, 0xFF,0xC4,0xB7, 0xFF,0xCC,0xAE,
        0xFF,0xD9,0xA2, 0xCC,0xE1,0x99, 0xAE,0xEE,0xB7, 0xAA,0xF7,0xEE,
        0xB3,0xEE,0xFF, 0xDD,0xDD,0xDD, 0x11,0x11,0x11, 0x11,0x11,0x11
    };

    /* Create the PBO */
    glGenBuffers(1, &OSXRenderer.pbo);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OSXRenderer.pbo);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, W*H, NULL, GL_STREAM_DRAW);

    /* Create the Screen Texture (400*240 pixel) */
    glGenTextures(1, &OSXRenderer.ScreenTexture);
    glBindTexture(GL_TEXTURE_2D, OSXRenderer.ScreenTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, W, H, 0, 
        GL_RED, GL_UNSIGNED_BYTE, OSXRenderer.Pixelbuffer.Data); 

    /* Create the Palette Texture (64*1 pixel) */
    glGenTextures(1, &OSXRenderer.PaletteTexture);
    glBindTexture(GL_TEXTURE_2D, OSXRenderer.PaletteTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 1, 0, 
        GL_RGB, GL_UNSIGNED_BYTE, &palette);

    /* Compile and Link Shaders */
    OSXRenderer.Program = OSXCreateProgram();
    glUseProgram(OSXRenderer.Program);

    /* Get the uniforms for the screen- and the palette-texture */
    OSXRenderer.UniformTex = glGetUniformLocation(OSXRenderer.Program, "tex");
    OSXRenderer.UniformPal = glGetUniformLocation(OSXRenderer.Program, "pal");

update loop:

    /* Rendering Prerequesites */
    glUseProgram(OSXRenderer.Program);

    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, OSXRenderer.PaletteTexture);
    glUniform1i(OSXRenderer.UniformPal, 0);

    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, OSXRenderer.ScreenTexture);
    glUniform1i(OSXRenderer.UniformTex, 1);

    /* Bind the PBO */
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OSXRenderer.pbo);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, W*H, NULL, GL_STREAM_DRAW);

    OSXRenderer.Pixelbuffer.Data = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

    //
    //
    FillPixelBuffer();
    //
    //

    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    glBindTexture(GL_TEXTURE_2D, OSXRenderer.ScreenTexture);

    /* Bind the screentexture again just to be save
    and fill it with the PBO data */
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RED, GL_UNSIGNED_BYTE, 0);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

    /* Render it to the screen */
    glBegin(GL_QUADS);
    glTexCoord2f(0.0f,1.0f);
    glVertex2f(-1.0f,1.0f);
    glTexCoord2f(1.0f,1.0f);
    glVertex2f(1.0f,1.0f);
    glTexCoord2f(1.0f,0.0f);
    glVertex2f(1.0f,-1.0f);
    glTexCoord2f(0.0f,0.0f);
    glVertex2f(-1.0f,-1.0f);
    glEnd();

    /* glFlush() */
    CGLFlushDrawable();

vertexshader:

    # version 120
    varying vec2 texcoord;

    // Simple Passthrough
    void main(void) 
    {
        gl_Position = ftransform();
        texcoord = gl_MultiTexCoord0.xy;
    }

fragmentshader:

    # version 120
    uniform sampler2D tex;
    uniform sampler2D pal;
    varying vec2 texcoord;


    void main(void) 
    {
        // Get the color values of the screen-texture. I only want the RED channel
        vec4 index = texture2D(tex, texcoord);
        // Get the color values of the palette texture 
        // using the screen-texture's RED channel as an index

//[EDIT] First post multiplied index.r with 255 here.
        vec4 color = texture2D(pal, vec2(index.r, 0));
        // Use it
        gl_FragColor = color;
    }
amto
  • 141
  • 1
  • 4
  • For one thing, you don't want a `GL_LINEAR` texture filter when you're trying to do this. That should be `GL_NEAREST` and you'll also probably want to use `GL_CLAMP_TO_EDGE` for your S and T wrap modes. These are important things you have to consider when you try to use normalized texture coordinates to implement a lookup table. Ideally, you'd just use `texelFetch (...)` and avoid all of this, but your GLSL version makes me think that's not practical. – Andon M. Coleman Jun 09 '15 at 20:17
  • More to the point though, why are you multiplying `index.r*255`? `index.r` is going to be a normalized floating-point value, which you should be able to feed directly as a texture coordinate. – Andon M. Coleman Jun 09 '15 at 20:19
  • Thanks for the advice, your right about the index.r*255. That's stupid. I tested it without the 255 and implemented all your other advice. Still my problem remains. – amto Jun 09 '15 at 20:29
  • Ah, okay. The other thing to keep in mind is that while something is bound to `GL_PIXEL_UNPACK_BUFFER`, the data pointer argument to `glTexImage2D (...)` is an offset into the bound buffer's memory pool. `OSXRenderer.Pixelbuffer.Data` may be appropriate on the first call, but the second call you're taking the address of some variable in client memory and that definitely won't be valid unless you unbind (bind **0**) the unpack PBO first. – Andon M. Coleman Jun 09 '15 at 20:40
  • Thats it! I was generating the Palette Texture in my setup with the GL_PIXEL_UNPACK_BUFFER still bound to my pbo. After binding it to 0 it worked! Thank you so much!! – amto Jun 10 '15 at 09:34

0 Answers0