除了像@ddriver 建议的那样在多平台库之上简单地构建您的 2d 引擎之外,您还可以为像素颜色分配一个大缓冲区并编写代码来渲染所有基元(单个像素、线条、框、圆、椭圆、弧,纹理/位图/图像,文本字符)。一旦您在此缓冲区中完成了帧的渲染,您就可以调用那里的任何库来将此缓冲区显示为屏幕或窗口中的图像。或者,如果您的代码在没有任何支持库的裸硬件上运行,您可以简单地将这个缓冲区复制到显卡的视频缓冲区中。
您的 API 可能如下所示:
typedef struct
{
unsigned BitsPerPixel; // 8,16,32
unsigned ColorScheme; // something that tells the order of the R, G and B components and how many bits are in each or if there's a palette used instead of RGB
unsigned Width; // in pixels
unsigned Height; // in pixels
size_t Size; // buffer size in bytes
void* Buf; // pointer to the beginning of the buffer itself
// extra info
} tBuffer;
int BufferInit(tBuffer* Buf, unsigned BitsPerPixel, unsigned ColorScheme, unsigned Width, unsigned Height)
{
Buf->BitsPerPixel = BitsPerPixel;
Buf->ColorScheme = ColorScheme;
Buf->Width = Width;
Buf->Height = Height;
Buf->Size = Buf->Width * Buf->Height * Buf->BitsPerPixel / 8;
Buf->Buf = malloc(Buf->Size);
if (Buf->Buf != NULL)
{
memset(Buf->Buf, 0, Buf->Size);
return 1;
}
return 0;
}
void BufferDone(tBuffer* Buf)
{
free(Buf->Buf);
Buf->Buf = NULL;
}
unsigned FindClosest8BitPaletteIndex(unsigned R, unsigned G, unsigned B)
{
// find the palette element that's closest to the given R, G and B
// and return its index
}
unsigned BufferRgbToColor(tBuffer* Buf, unsigned R, unsigned G, unsigned B)
{
switch (Buf->BitsPerPixel)
{
case 8:
return FindClosest8BitPaletteIndex(R, G, B);
case 16:
return ((R & 0x1F) << 11) | ((G & 0x3F) << 6) | (B & 0x1F); // 5-6-5
case 32:
return ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF); // (8)-8-8-8
default:
return 0; // error
}
}
void BufferSetPixel(tBuffer* Buf, unsigned X, unsigned Y, unsigned Color)
{
switch (Buf->BitsPerPixel)
{
case 8:
*((unsigned char*)Buf->Buf + Buf->Width * Y + X) = Color;
break;
case 16:
*((unsigned short*)Buf->Buf + Buf->Width * Y + X) = Color;
break;
case 32:
*((unsigned*)Buf->Buf + Buf->Width * Y + X) = Color;
break;
}
}
然后你可以像这样使用它:
tBuffer buf;
if (BufferInit(&buf, 32, 0, 1024, 768))
{
BufferSetPixel(&buf, 512, 384, BufferRgbToColor(&buf, 0xFF, 0xFF, 0xFF));
// make the contents of buf.Buf visible in some way
BufferDone(&buf);
}
这应该会给你一些想法。