2009-05-25 12:28:16 +00:00
|
|
|
#ifndef GRAPHICS_TINYGL_ZBUFFER_H_
|
|
|
|
#define GRAPHICS_TINYGL_ZBUFFER_H_
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2012-01-16 17:12:14 +01:00
|
|
|
#include "graphics/pixelbuffer.h"
|
2014-06-18 00:14:55 +02:00
|
|
|
#include "graphics/tinygl/gl.h"
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2009-05-25 13:19:29 +00:00
|
|
|
namespace TinyGL {
|
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
// Z buffer
|
2005-01-12 15:20:02 +00:00
|
|
|
|
|
|
|
#define ZB_Z_BITS 16
|
|
|
|
|
|
|
|
#define ZB_POINT_Z_FRAC_BITS 14
|
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
#define ZB_POINT_S_MIN ( (1 << 13) )
|
|
|
|
#define ZB_POINT_S_MAX ( (1 << 22) - (1 << 13) )
|
|
|
|
#define ZB_POINT_T_MIN ( (1 << 21) )
|
|
|
|
#define ZB_POINT_T_MAX ( (1 << 30) - (1 << 21) )
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
#define ZB_POINT_RED_MIN ( (1 << 10) )
|
|
|
|
#define ZB_POINT_RED_MAX ( (1 << 16) - (1 << 10) )
|
|
|
|
#define ZB_POINT_GREEN_MIN ( (1 << 9) )
|
|
|
|
#define ZB_POINT_GREEN_MAX ( (1 << 16) - (1 << 9) )
|
|
|
|
#define ZB_POINT_BLUE_MIN ( (1 << 10) )
|
|
|
|
#define ZB_POINT_BLUE_MAX ( (1 << 16) - (1 << 10) )
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
// display modes
|
|
|
|
#define ZB_MODE_5R6G5B 1 // true color 16 bits
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
#define RGB_TO_PIXEL(r, g, b) cmode.RGBToColor(r, g, b)
|
2012-01-16 17:12:14 +01:00
|
|
|
typedef byte PIXEL;
|
|
|
|
|
|
|
|
#define PSZSH 4
|
|
|
|
|
|
|
|
extern uint8 PSZB;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2012-02-13 17:59:48 +01:00
|
|
|
struct Buffer {
|
|
|
|
byte *pbuf;
|
2012-02-13 19:19:03 +01:00
|
|
|
unsigned int *zbuf;
|
2012-02-13 21:28:19 +01:00
|
|
|
bool used;
|
2012-02-13 17:59:48 +01:00
|
|
|
};
|
|
|
|
|
2014-06-13 12:59:06 +02:00
|
|
|
struct ZBufferPoint {
|
|
|
|
int x, y, z; // integer coordinates in the zbuffer
|
|
|
|
int s, t; // coordinates for the mapping
|
|
|
|
int r, g, b; // color indexes
|
|
|
|
|
|
|
|
float sz, tz; // temporary coordinates for mapping
|
|
|
|
};
|
|
|
|
|
2014-06-13 14:58:07 +02:00
|
|
|
struct FrameBuffer {
|
|
|
|
FrameBuffer(int xsize, int ysize, const Graphics::PixelBuffer &frame_buffer);
|
|
|
|
~FrameBuffer();
|
2014-06-06 01:34:10 +02:00
|
|
|
|
2014-06-11 16:11:47 +02:00
|
|
|
Buffer *genOffscreenBuffer();
|
2014-06-06 01:34:10 +02:00
|
|
|
void delOffscreenBuffer(Buffer *buffer);
|
|
|
|
void clear(int clear_z, int z, int clear_color, int r, int g, int b);
|
|
|
|
|
2014-06-18 00:14:55 +02:00
|
|
|
FORCEINLINE void writePixel(int pixel, int value) {
|
|
|
|
if (_blendingEnabled == false) {
|
|
|
|
this->pbuf.setPixelAt(pixel,value);
|
|
|
|
} else {
|
|
|
|
byte rSrc, gSrc, bSrc, aSrc;
|
|
|
|
byte rDst, gDst, bDst, aDst;
|
|
|
|
this->pbuf.getFormat().colorToARGB(value, aDst, rDst, gDst, bDst);
|
|
|
|
switch (_sourceBlendingFactor) {
|
|
|
|
case TGL_ZERO:
|
|
|
|
rSrc = gSrc = bSrc = 0;
|
|
|
|
break;
|
|
|
|
case TGL_ONE:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
break;
|
|
|
|
case TGL_DST_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * rDst) >> 8;
|
|
|
|
gSrc = (gSrc * gDst) >> 8;
|
|
|
|
bSrc = (bSrc * bDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * (255 - rDst)) >> 8;
|
|
|
|
gSrc = (gSrc * (255 - gDst)) >> 8;
|
|
|
|
bSrc = (bSrc * (255 - bDst)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * aSrc) >> 8;
|
|
|
|
gSrc = (gSrc * aSrc) >> 8;
|
|
|
|
bSrc = (bSrc * aSrc) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * (255 - aSrc)) >> 8;
|
|
|
|
gSrc = (gSrc * (255 - aSrc)) >> 8;
|
|
|
|
bSrc = (bSrc * (255 - aSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_DST_ALPHA:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * aDst) >> 8;
|
|
|
|
gSrc = (gSrc * aDst) >> 8;
|
|
|
|
bSrc = (bSrc * aDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_ALPHA:
|
|
|
|
rSrc = (rSrc * (1 - aDst)) >> 8;
|
|
|
|
gSrc = (gSrc * (1 - aDst)) >> 8;
|
|
|
|
bSrc = (bSrc * (1 - aDst)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA_SATURATE: {
|
|
|
|
int factor = aDst < 1 - aSrc ? aDst : 1 - aSrc;
|
|
|
|
rSrc = (rSrc * factor) >> 8;
|
|
|
|
gSrc = (gSrc * factor) >> 8;
|
|
|
|
bSrc = (bSrc * factor) >> 8;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (_destinationBlendingFactor) {
|
|
|
|
case TGL_ZERO:
|
|
|
|
rDst = gDst = bDst = 0;
|
|
|
|
break;
|
|
|
|
case TGL_ONE:
|
|
|
|
break;
|
|
|
|
case TGL_SRC_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rSrc * rDst) >> 8;
|
|
|
|
gDst = (gSrc * gDst) >> 8;
|
|
|
|
bDst = (bSrc * bDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * (255 - rSrc)) >> 8;
|
|
|
|
gDst = (gDst * (255 - gSrc)) >> 8;
|
|
|
|
bDst = (bDst * (255 - bSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * aSrc) >> 8;
|
|
|
|
gDst = (gDst * aSrc) >> 8;
|
|
|
|
bDst = (bDst * aSrc) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * (255 - aSrc)) >> 8;
|
|
|
|
gDst = (gDst * (255 - aSrc)) >> 8;
|
|
|
|
bDst = (bDst * (255 - aSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_DST_ALPHA:
|
|
|
|
rDst = (rDst * aDst) >> 8;
|
|
|
|
gDst = (gDst * aDst) >> 8;
|
|
|
|
bDst = (bDst * aDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_ALPHA:
|
|
|
|
rDst = (rDst * (255 - aDst)) >> 8;
|
|
|
|
gDst = (gDst * (255 - aDst)) >> 8;
|
|
|
|
bDst = (bDst * (255 - aDst)) >> 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
this->pbuf.setPixelAt(pixel,255,rSrc + rDst,gSrc + gDst,bSrc + bDst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE void writePixel(int pixel, byte rDst, byte gDst, byte bDst) {
|
|
|
|
if (_blendingEnabled == false) {
|
|
|
|
this->pbuf.setPixelAt(pixel,255,rDst,gDst,bDst);
|
|
|
|
} else {
|
|
|
|
byte rSrc, gSrc, bSrc, aSrc;
|
|
|
|
switch (_sourceBlendingFactor) {
|
|
|
|
case TGL_ZERO:
|
|
|
|
rSrc = gSrc = bSrc = 0;
|
|
|
|
break;
|
|
|
|
case TGL_ONE:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
break;
|
|
|
|
case TGL_DST_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * rDst) >> 8;
|
|
|
|
gSrc = (gSrc * gDst) >> 8;
|
|
|
|
bSrc = (bSrc * bDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * (255 - rDst)) >> 8;
|
|
|
|
gSrc = (gSrc * (255 - gDst)) >> 8;
|
|
|
|
bSrc = (bSrc * (255 - bDst)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * aSrc) >> 8;
|
|
|
|
gSrc = (gSrc * aSrc) >> 8;
|
|
|
|
bSrc = (bSrc * aSrc) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rSrc = (rSrc * (255 - aSrc)) >> 8;
|
|
|
|
gSrc = (gSrc * (255 - aSrc)) >> 8;
|
|
|
|
bSrc = (bSrc * (255 - aSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_DST_ALPHA:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_ALPHA:
|
|
|
|
rSrc = gSrc = bSrc = 0;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA_SATURATE: // Still not sure
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (_destinationBlendingFactor) {
|
|
|
|
case TGL_ZERO:
|
|
|
|
rDst = gDst = bDst = 0;
|
|
|
|
break;
|
|
|
|
case TGL_ONE:
|
|
|
|
break;
|
|
|
|
case TGL_SRC_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rSrc * rDst) >> 8;
|
|
|
|
gDst = (gSrc * gDst) >> 8;
|
|
|
|
bDst = (bSrc * bDst) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_COLOR:
|
|
|
|
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * (255 - rSrc)) >> 8;
|
|
|
|
gDst = (gDst * (255 - gSrc)) >> 8;
|
|
|
|
bDst = (bDst * (255 - bSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * aSrc) >> 8;
|
|
|
|
gDst = (gDst * aSrc) >> 8;
|
|
|
|
bDst = (bDst * aSrc) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
|
|
|
|
rDst = (rDst * (255 - aSrc)) >> 8;
|
|
|
|
gDst = (gDst * (255 - aSrc)) >> 8;
|
|
|
|
bDst = (bDst * (255 - aSrc)) >> 8;
|
|
|
|
break;
|
|
|
|
case TGL_DST_ALPHA:
|
|
|
|
break;
|
|
|
|
case TGL_ONE_MINUS_DST_ALPHA:
|
|
|
|
rDst = gDst = bDst = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
this->pbuf.setPixelAt(pixel,255,rSrc + rDst,gSrc + gDst,bSrc + bDst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void enableBlending(bool enableBlending);
|
|
|
|
void setBlendingFactors(int sfactor, int dfactor);
|
2014-06-16 21:41:02 +02:00
|
|
|
|
2014-06-06 01:34:10 +02:00
|
|
|
/**
|
|
|
|
* Blit the buffer to the screen buffer, checking the depth of the pixels.
|
|
|
|
* Eack pixel is copied if and only if its depth value is bigger than the
|
|
|
|
* depth value of the screen pixel, so if it is 'above'.
|
|
|
|
*/
|
2014-06-11 16:11:47 +02:00
|
|
|
void blitOffscreenBuffer(Buffer *buffer);
|
|
|
|
void selectOffscreenBuffer(Buffer *buffer);
|
|
|
|
void clearOffscreenBuffer(Buffer *buffer);
|
|
|
|
void setTexture(const Graphics::PixelBuffer &texture);
|
2014-06-06 01:34:10 +02:00
|
|
|
|
2014-06-16 21:41:02 +02:00
|
|
|
template <bool interpRGB, bool interpZ, bool interpST, bool interpSTZ, int drawLogic>
|
|
|
|
void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
|
2014-06-17 17:00:20 +02:00
|
|
|
template <bool interpRGB, bool interpZ>
|
|
|
|
void fillLine(ZBufferPoint *p1, ZBufferPoint *p2, int color);
|
|
|
|
|
2014-06-13 12:59:06 +02:00
|
|
|
void fillTriangleMappingPerspective(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleDepthOnly(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleFlatShadowMask(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleFlatShadow(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillTriangleMapping(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
|
|
|
|
void plot(ZBufferPoint *p);
|
|
|
|
void fillLine(ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillLineZ(ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillLineFlatZ(ZBufferPoint *p1, ZBufferPoint *p2, int color);
|
|
|
|
void fillLineInterpZ(ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
void fillLineFlat(ZBufferPoint *p1, ZBufferPoint *p2, int color);
|
|
|
|
void fillLineInterp(ZBufferPoint *p1, ZBufferPoint *p2);
|
|
|
|
|
2008-07-05 08:48:39 +00:00
|
|
|
int xsize, ysize;
|
2006-05-16 10:02:27 +00:00
|
|
|
int linesize; // line size, in bytes
|
2012-01-16 17:12:14 +01:00
|
|
|
Graphics::PixelFormat cmode;
|
|
|
|
int pixelbits;
|
|
|
|
int pixelbytes;
|
2006-05-16 10:02:27 +00:00
|
|
|
|
2013-01-11 12:39:12 +01:00
|
|
|
Buffer buffer;
|
2012-02-13 17:59:48 +01:00
|
|
|
|
2012-02-13 19:19:03 +01:00
|
|
|
unsigned int *zbuf;
|
2008-07-05 08:48:39 +00:00
|
|
|
unsigned char *shadow_mask_buf;
|
|
|
|
int shadow_color_r;
|
|
|
|
int shadow_color_g;
|
|
|
|
int shadow_color_b;
|
2006-05-16 10:02:27 +00:00
|
|
|
int frame_buffer_allocated;
|
|
|
|
|
|
|
|
unsigned char *dctable;
|
|
|
|
int *ctable;
|
2012-01-16 17:12:14 +01:00
|
|
|
Graphics::PixelBuffer current_texture;
|
2014-06-16 21:41:02 +02:00
|
|
|
Graphics::PixelBuffer pbuf;
|
2014-06-18 00:14:55 +02:00
|
|
|
private:
|
|
|
|
bool _blendingEnabled;
|
|
|
|
int _sourceBlendingFactor;
|
|
|
|
int _destinationBlendingFactor;
|
2014-02-20 19:08:55 +01:00
|
|
|
};
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
// memory.c
|
2005-01-12 15:20:02 +00:00
|
|
|
void gl_free(void *p);
|
|
|
|
void *gl_malloc(int size);
|
|
|
|
void *gl_zalloc(int size);
|
|
|
|
|
2009-05-25 13:19:29 +00:00
|
|
|
} // end of namespace TinyGL
|
|
|
|
|
|
|
|
#endif
|