Opengl 片段着色器中调色板的PBO索引颜色纹理渲染不工作
我正在开发一款8位图形的游戏。我提供了一个像素缓冲区(OSXRenderer.pbo) 到我的gameloop来填满它。然后将其子映像到纹理上(OSXRenderer.ScreenTexture)。 纹理通过四边形渲染到屏幕 我使用RGB PBO(尺寸:宽*高*3)使其正常工作。 但现在我希望pbo被索引为彩色。所以我将调色板加载到另一个纹理中 (OSXRenderer.PaletteTexture)并更改了我的PBO。(尺寸:宽*高) 我认为它应该如何工作: PBO被噪声填充(随机uint8 0-63),Screentexture被子成像, 当通过quad将其渲染到屏幕上时,我的fragmentshader将替换所有 红色通道值和调色板中相应的颜色,我在屏幕上得到8比特噪声 但我就是不能让它工作。我只有一个黑屏。如果我将fragcolor设置为传入 屏幕纹理(pbo)数据我得到红色噪音。正如所料 [编辑] 我测试了片段着色器“颜色”-变量值。它们总是0.0,除了alpha总是1.0 设置:Opengl 片段着色器中调色板的PBO索引颜色纹理渲染不工作,opengl,glsl,fragment-shader,color-palette,pbo,Opengl,Glsl,Fragment Shader,Color Palette,Pbo,我正在开发一款8位图形的游戏。我提供了一个像素缓冲区(OSXRenderer.pbo) 到我的gameloop来填满它。然后将其子映像到纹理上(OSXRenderer.ScreenTexture)。 纹理通过四边形渲染到屏幕 我使用RGB PBO(尺寸:宽*高*3)使其正常工作。 但现在我希望pbo被索引为彩色。所以我将调色板加载到另一个纹理中 (OSXRenderer.PaletteTexture)并更改了我的PBO。(尺寸:宽*高) 我认为它应该如何工作: PBO被噪声填充(随机uint8
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");
更新循环:
/* 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();
顶点着色器:
# version 120
varying vec2 texcoord;
// Simple Passthrough
void main(void)
{
gl_Position = ftransform();
texcoord = gl_MultiTexCoord0.xy;
}
碎片着色器:
# 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;
}
首先,当您尝试这样做时,您不希望使用
GL\u线性
纹理过滤器。这应该是GL\u最近的
,您可能还希望在S和T包裹模式中使用GL\u夹紧到边缘
。当您尝试使用规范化纹理坐标来实现查找表时,这些都是必须考虑的重要事项。理想情况下,您只需使用texelFetch(…)
并避免所有这些,但您的GLSL版本让我认为这不实用。更重要的是,为什么要将index.r*255
相乘index.r
将是一个标准化的浮点值,您应该能够直接将其作为纹理坐标输入。感谢您的建议,您有权使用index.r*255。那太愚蠢了。我在没有255的情况下测试了它,并实现了您所有的其他建议。我的问题仍然存在。啊,好的。要记住的另一件事是,当某些东西绑定到GL\u PIXEL\u UNPACK\u BUFFER
时,glTexImage2D(…)
的数据指针参数是绑定缓冲区内存池的偏移量OSXRenderer.Pixelbuffer.Data
在第一次调用时可能是合适的,但是在第二次调用时,您正在获取客户端内存中某个变量的地址,除非您首先解除绑定(绑定0)解包PBO,否则该调用肯定无效。仅此而已!我在设置中生成调色板纹理时,GL_像素_解包_缓冲区仍然绑定到我的pbo。在将其绑定到0后,它工作了!非常感谢你!!