为了学图形学方便,用SDL写了个光栅显示的模拟,
还花了几个下午来研究了下,主要就是坐标之间的
转换着实让人烦,开始写的一个因为烦透了,删了又重写过……
这个写得还算满意了,坐标之间的转换关系蛮方便地,
也可以从象素级别上刷写一张图象,作一堆杂七杂八的变换,
达到什么效果就看自己写的程序了……
这只是个学习的工具,自己写的图形程序可以直接用来试验,
没什么其它功能,就一个操作伪象素有点用……
呵呵,模拟的就是伪象素嘛……
//raster.h头文件
#include <SDL/SDL.h>
#include <stdlib.h>
#include <iostream>
#define SetR 100
#define SetG 255
#define SetB 255
#define FrameR 255
#define FrameG 0
#define FrameB 0
void init ();
void loop ();
void drawjay ();
void setpixel (int x, int y, Uint8 R = SetR, Uint8 G = SetG, Uint8 B = SetB);
void setpixel (int x, int y, Uint32 pixel);
void drawframe (int x, int y, Uint8 R = FrameR, Uint8 G = FrameG, Uint8 B =
FrameB);
void drawframe (int x, int y, Uint32 pixel);
int maxx ();
int minx ();
int maxy ();
int miny ();
//raster.cc程序文件
#include "raster.h"
#define HW 800 //hardware width
#define HH 600 //hardware hight
#define PIXEL_H 4 //minimum
#define PIXEL_W 4
#define OO 1 //是否用一到四象限坐标
#define CUTR 255 //切割颜色
#define CUTG 255
#define CUTB 255
#define OOR 255 //坐标线颜色
#define OOG 0
#define OOB 0
SDL_Surface *screen, *jay;
//对屏幕的象素级操作
void
putpixel (SDL_Surface * img, int x, int y, Uint32 pixel)
{
int bpp = img->format->BytesPerPixel;
Uint8 *p = (Uint8 *) img->pixels + y * img->pitch + x * bpp;
switch (bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *) p = pixel;
break;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *) p = pixel;
break;
};
}
Uint32
returnpixel (SDL_Surface * img, int x, int y)
{
int bpp = img->format->BytesPerPixel;
Uint8 *p = (Uint8 *) img->pixels + y * img->pitch + x * bpp;
switch (bpp)
{
case 1:
return *p;
case 2:
return *(Uint16 *) p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *) p;
default:
return 0;
};
}
void
drawooline () //画十字线坐标,只有打开四个象限(OO)才用到,
{
if (OO)
{
Uint32 pixel = SDL_MapRGB (screen->format, OOR,
OOG, OOB);
int i;
for (i = 0; i < HW; i++)
putpixel (screen, i, HH / 2, pixel);
for (i = 0; i < HH; i++)
putpixel (screen, HW / 2, i, pixel);
SDL_UpdateRect (screen, 0, HH / 2, HW, 1);
SDL_UpdateRect (screen, HW / 2, 0, 1, HH);
}
}
void
drawcut () //画屏幕切割线,如果只用到第一象限就不画十字线坐标了
{
int i, j;
Uint32 pixel = SDL_MapRGB (screen->format, CUTR,
CUTG, CUTB);
for (i = 0; i < HH; i++)
for (j = 0; j < HW; j++)
{
if (i % PIXEL_H != 0 && j % PIXEL_W == 0)
putpixel (screen, j, i, pixel);
else if (i % PIXEL_H == 0)
putpixel (screen, j, i, pixel);
}
SDL_ShowCursor (0);
SDL_WM_SetCaption ("Computer raster display emulation", "");
if (OO)
drawooline ();
SDL_Flip (screen);
}
void
init ()
{
if ((SDL_Init (SDL_INIT_VIDEO)) < 0)
fprintf (stderr, "init error\n");
atexit (SDL_Quit);
if ((screen =
SDL_SetVideoMode (HW, HH, 32,
SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
fprintf (stderr, "set video mode error\n");
drawcut ();
if ((jay = SDL_LoadBMP ("jay.bmp")) == NULL)
fprintf (stderr, "load jay error\n");
}
void
drawjay () //画图片(jay)
{
int i, j;
if (OO)
{
int mx = minx (), my = miny ();
for (i = mx; i <= maxx (); i++)
for (j = my; j <= maxy (); j++)
setpixel (i, maxy () - j - abs (my),
returnpixel (jay, i + abs (mx),
j + abs (my)));
}
else
{
for (i = minx (); i <= maxx (); i++)
for (j = miny (); j <= maxy (); j++)
setpixel (i, maxy () - j,
returnpixel (jay, i, j));
}
}
int
maxx () //伪象素系统的最大的X值,
{
if (OO)
return (HW - 1) / PIXEL_W - HW / 2 / PIXEL_W;
else
return (HW - 1) / PIXEL_W;
}
int
minx ()
{
if (OO)
return -HW / 2 / PIXEL_W;
else
return 0;
}
int
maxy ()
{
if (OO)
return (HH - 1) / PIXEL_H - HH / 2 / PIXEL_H;
else
return (HH - 1) / PIXEL_H;
}
int
miny ()
{
if (OO)
return -HH / 2 / PIXEL_H;
else
return 0;
}
//真实坐标系统到伪象素系统的坐标转换
void
changecoor (int a, int b, int &x, int &y)
{
if (a < 0 || a >= HW || b < 0 || b >= HH)
return;
if (OO)
{
int ox = HW / 2;
int oy = HH / 2;
x = a / PIXEL_W - ox / PIXEL_W;
y = (HH - 1 - b) / PIXEL_H - oy / PIXEL_H;
}
else
{
x = a / PIXEL_W;
y = (HH - 1 - b) / PIXEL_H;
}
}
//伪象素坐标系统到真实坐标的坐标转换
void
changebackcoor (int x, int y, int &a, int &b) //oo to sdl
{
if (x > maxx () || x < minx () || y > maxy () || y < miny ())
return;
if (OO)
{
a = HW / 2 + x * PIXEL_W;
b = HH / 2 - y * PIXEL_H;
}
else
{
a = x * PIXEL_W;
b = HH - y * PIXEL_H;
}
}
//画一个伪象素点的边框,鼠标移动到一个伪象素点上时有用
void
drawframe (int x, int y, Uint8 R, Uint8 G, Uint8 B) //oo坐标
{
if (x > maxx () || x < minx () || y > maxy () || y < miny ())
return;
Uint32 pixel = SDL_MapRGB (screen->format, R, G, B);
changebackcoor (x, y, x, y);
int i;
for (i = 1; i < PIXEL_W; i++)
{
putpixel (screen, x + i, y - 1, pixel);
putpixel (screen, x + i, y - PIXEL_H + 1, pixel);
}
for (i = 1; i < PIXEL_H; i++)
{
putpixel (screen, x + 1, y - i, pixel);
putpixel (screen, x + PIXEL_W - 1, y - i, pixel);
}
SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
PIXEL_H - 1);
}
//重载一下
void
drawframe (int x, int y, Uint32 pixel)
{
if (x > maxx () || x < minx () || y > maxy () || y < miny ())
return;
changebackcoor (x, y, x, y);
int i;
for (i = 1; i < PIXEL_W; i++)
{
putpixel (screen, x + i, y - 1, pixel);
putpixel (screen, x + i, y - PIXEL_H + 1, pixel);
}
for (i = 1; i < PIXEL_H; i++)
{
putpixel (screen, x + 1, y - i, pixel);
putpixel (screen, x + PIXEL_W - 1, y - i, pixel);
}
SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
PIXEL_H - 1);
}
//主loop
void
loop ()
{
SDL_Event event;
Uint32 oldpixel = SDL_MapRGB (screen->format, 0, 0, 0);
int run = 1, bx, by, oldx = minx () - 1, oldy = miny () - 1, x, y;
int tmpx, tmpy;
while (run)
{
SDL_Delay (50);
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_QUIT:
run = 0;
break;
case SDL_MOUSEBUTTONDOWN:
changecoor (event.
button.x, event.button.y, bx, by);
fprintf (stdout, "X:%d\tY:%d\n", bx, by);
break;
};
}
SDL_GetMouseState (&x, &y);
changecoor (x, y, x, y);
if (oldx != x || oldy != y) //鼠标移动后的还原
drawframe (oldx, oldy, oldpixel);
changebackcoor (x, y, tmpx, tmpy);
oldpixel = returnpixel (screen, tmpx + 2, tmpy - 2);
drawframe (x, y);
oldx = x;
oldy = y;
}
}
//操作伪象素点
void
setpixel (int x, int y, Uint8 R, Uint8 G, Uint8 B)
{
if (x > maxx () || x < minx () || y > maxy () || y < miny ())
return;
changebackcoor (x, y, x, y);
Uint32 pixel = SDL_MapRGB (screen->format, R, G, B);
int i, j;
for (i = 1; i < PIXEL_W; i++)
for (j = 1; j < PIXEL_H; j++)
putpixel (screen, x + i, y - j, pixel);
SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
PIXEL_H - 1);
}
void
setpixel (int x, int y, Uint32 pixel)
{
if (x > maxx () || x < minx () || y > maxy () || y < miny ())
return;
changebackcoor (x, y, x, y);
int i, j;
for (i = 1; i < PIXEL_W; i++)
for (j = 1; j < PIXEL_H; j++)
putpixel (screen, x + i, y - j, pixel);
SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
PIXEL_H - 1);
}
评论