将像素缓冲区类型从 1555 转换为 5551(C++、OpenGL ES)
Convert Pixels Buffer type from 1555 to 5551 (C++, OpenGL ES)
我在转换 OpenGL 视频插件以支持 GLES 3.0 时遇到问题
到目前为止一切顺利,除了 glTexSubImage2D
原始代码使用 GL_UNSIGNED_SHORT_1_5_5_5_REV
作为 GLES 3.0
不支持的像素类型
有效的类型是 GL_UNSIGNED_SHORT_5_5_5_1
,但颜色和像素损坏,
所以我认为转换像素缓冲区会很好..
但是由于我对 GL 和 C++ 的有限理解,我没有成功做到这一点。
像素处理:
- 像素将在内部转换为 16 位 ABGR,如着色器注释中所述:
// Take a normalized color and convert it into a 16bit 1555 ABGR
// integer in the format used internally by the Playstation GPU.
uint rebuild_psx_color(vec4 color) {
uint a = uint(floor(color.a + 0.5));
uint r = uint(floor(color.r * 31. + 0.5));
uint g = uint(floor(color.g * 31. + 0.5));
uint b = uint(floor(color.b * 31. + 0.5));
return (a << 15) | (b << 10) | (g << 5) | r;
}
- vGPU处理后通过此方法接收:
static void Texture_set_sub_image_window(struct Texture *tex, uint16_t top_left[2], uint16_t resolution[2], size_t row_len, uint16_t* data)
{
uint16_t x = top_left[0];
uint16_t y = top_left[1];
/* TODO - Am I indexing data out of bounds? */
size_t index = ((size_t) y) * row_len + ((size_t) x);
uint16_t* sub_data = &( data[index] );
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint) row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, tex->id);
glTexSubImage2D(GL_TEXTURE_2D, 0,
(GLint) top_left[0], (GLint) top_left[1],
(GLsizei) resolution[0], (GLsizei) resolution[1],
GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV /* Not supported in GLES */,
(void*)sub_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
至于 row_len
它是从 #define VRAM_WIDTH_PIXELS 1024
中获取值
我尝试做的事情:
- 1st 我用另一种替换了类型:
glTexSubImage2D(GL_TEXTURE_2D, 0,
(GLint) top_left[0], (GLint) top_left[1],
(GLsizei) resolution[0], (GLsizei) resolution[1],
GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 /* <- Here new type */,
(void*)sub_data);
- 第二次转换
sub_data
使用此方法:
uint16_t* ABGRConversion(const uint16_t* pixels, int row_len, int x, int y, int width, int height) {
uint16_t *frameBuffer = (uint16_t*)malloc(width * row_len * height);
signed i, j;
for (j=0; j < height; j++)
{
for (i=0; i < width; i++)
{
int offset = j * row_len + i;
uint16_t pixel = pixels[offset];
frameBuffer[offset] = Convert1555To5551(pixel); //<- stuck here
}
}
return frameBuffer;
}
- 我不知道
Convert1555To5551
应该是什么样子?
注意:如果有些描述有误请见谅,我不是很了解整个过程。
性能不是大问题..只需要知道如何处理当前的像素缓冲区。
旁注: 我不得不用 glFramebufferTexture2D
替换 glFramebufferTexture
所以我希望它没有涉及到这个问题。
谢谢。
这应该是您要找的。
uint16_t Convert1555To5551(uint16_t pixel)
{
// extract rgba from 1555 (1 bit alpha, 5 bits blue, 5 bits green, 5 bits red)
uint16_t a = pixel >> 15;
uint16_t b = (pixel >> 10) & 0x1f; // mask lowest five bits
uint16_t g = (pixel >> 5) & 0x1f;
uint16_t r = pixel & 0x1f;
// compress rgba into 5551 (5 bits red, 5 bits green, 5 bits blue, 1 bit alpha)
return (r << 11) | (g << 6) | (b << 1) | a;
}
我在转换 OpenGL 视频插件以支持 GLES 3.0 时遇到问题
到目前为止一切顺利,除了 glTexSubImage2D
原始代码使用 GL_UNSIGNED_SHORT_1_5_5_5_REV
作为 GLES 3.0
有效的类型是 GL_UNSIGNED_SHORT_5_5_5_1
,但颜色和像素损坏,
所以我认为转换像素缓冲区会很好..
但是由于我对 GL 和 C++ 的有限理解,我没有成功做到这一点。
像素处理:
- 像素将在内部转换为 16 位 ABGR,如着色器注释中所述:
// Take a normalized color and convert it into a 16bit 1555 ABGR
// integer in the format used internally by the Playstation GPU.
uint rebuild_psx_color(vec4 color) {
uint a = uint(floor(color.a + 0.5));
uint r = uint(floor(color.r * 31. + 0.5));
uint g = uint(floor(color.g * 31. + 0.5));
uint b = uint(floor(color.b * 31. + 0.5));
return (a << 15) | (b << 10) | (g << 5) | r;
}
- vGPU处理后通过此方法接收:
static void Texture_set_sub_image_window(struct Texture *tex, uint16_t top_left[2], uint16_t resolution[2], size_t row_len, uint16_t* data)
{
uint16_t x = top_left[0];
uint16_t y = top_left[1];
/* TODO - Am I indexing data out of bounds? */
size_t index = ((size_t) y) * row_len + ((size_t) x);
uint16_t* sub_data = &( data[index] );
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint) row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, tex->id);
glTexSubImage2D(GL_TEXTURE_2D, 0,
(GLint) top_left[0], (GLint) top_left[1],
(GLsizei) resolution[0], (GLsizei) resolution[1],
GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV /* Not supported in GLES */,
(void*)sub_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
至于 row_len
它是从 #define VRAM_WIDTH_PIXELS 1024
我尝试做的事情:
- 1st 我用另一种替换了类型:
glTexSubImage2D(GL_TEXTURE_2D, 0,
(GLint) top_left[0], (GLint) top_left[1],
(GLsizei) resolution[0], (GLsizei) resolution[1],
GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 /* <- Here new type */,
(void*)sub_data);
- 第二次转换
sub_data
使用此方法:
uint16_t* ABGRConversion(const uint16_t* pixels, int row_len, int x, int y, int width, int height) {
uint16_t *frameBuffer = (uint16_t*)malloc(width * row_len * height);
signed i, j;
for (j=0; j < height; j++)
{
for (i=0; i < width; i++)
{
int offset = j * row_len + i;
uint16_t pixel = pixels[offset];
frameBuffer[offset] = Convert1555To5551(pixel); //<- stuck here
}
}
return frameBuffer;
}
- 我不知道
Convert1555To5551
应该是什么样子?
注意:如果有些描述有误请见谅,我不是很了解整个过程。
性能不是大问题..只需要知道如何处理当前的像素缓冲区。
旁注: 我不得不用 glFramebufferTexture2D
替换 glFramebufferTexture
所以我希望它没有涉及到这个问题。
谢谢。
这应该是您要找的。
uint16_t Convert1555To5551(uint16_t pixel)
{
// extract rgba from 1555 (1 bit alpha, 5 bits blue, 5 bits green, 5 bits red)
uint16_t a = pixel >> 15;
uint16_t b = (pixel >> 10) & 0x1f; // mask lowest five bits
uint16_t g = (pixel >> 5) & 0x1f;
uint16_t r = pixel & 0x1f;
// compress rgba into 5551 (5 bits red, 5 bits green, 5 bits blue, 1 bit alpha)
return (r << 11) | (g << 6) | (b << 1) | a;
}