ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

zbuffer.h

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 /*
00024  * This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
00025  * which is licensed under the zlib-license (see LICENSE).
00026  * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
00027  */
00028 
00029 #ifndef GRAPHICS_TINYGL_ZBUFFER_H_
00030 #define GRAPHICS_TINYGL_ZBUFFER_H_
00031 
00032 #include "graphics/pixelbuffer.h"
00033 #include "graphics/tinygl/gl.h"
00034 #include "common/rect.h"
00035 
00036 namespace TinyGL {
00037 
00038 // Z buffer
00039 
00040 #define ZB_Z_BITS 16
00041 
00042 #define ZB_POINT_Z_FRAC_BITS 14
00043 
00044 #define ZB_POINT_ST_FRAC_BITS 14
00045 #define ZB_POINT_ST_FRAC_SHIFT     (ZB_POINT_ST_FRAC_BITS - 1)
00046 #define ZB_POINT_ST_MAX            ( (c->_textureSize << ZB_POINT_ST_FRAC_BITS) - 1 )
00047 
00048 #define ZB_POINT_RED_BITS         16
00049 #define ZB_POINT_RED_FRAC_BITS    8
00050 #define ZB_POINT_RED_FRAC_SHIFT   (ZB_POINT_RED_FRAC_BITS - 1)
00051 #define ZB_POINT_RED_MAX          ( (1 << ZB_POINT_RED_BITS) - 1 )
00052 
00053 #define ZB_POINT_GREEN_BITS       16
00054 #define ZB_POINT_GREEN_FRAC_BITS  8
00055 #define ZB_POINT_GREEN_FRAC_SHIFT (ZB_POINT_GREEN_FRAC_BITS - 1)
00056 #define ZB_POINT_GREEN_MAX        ( (1 << ZB_POINT_GREEN_BITS) - 1 )
00057 
00058 #define ZB_POINT_BLUE_BITS        16
00059 #define ZB_POINT_BLUE_FRAC_BITS   8
00060 #define ZB_POINT_BLUE_FRAC_SHIFT  (ZB_POINT_BLUE_FRAC_BITS - 1)
00061 #define ZB_POINT_BLUE_MAX         ( (1 << ZB_POINT_BLUE_BITS) - 1 )
00062 
00063 #define ZB_POINT_ALPHA_BITS       16
00064 #define ZB_POINT_ALPHA_FRAC_BITS  8
00065 #define ZB_POINT_ALPHA_FRAC_SHIFT (ZB_POINT_ALPHA_FRAC_BITS - 1)
00066 #define ZB_POINT_ALPHA_MAX        ( (1 << ZB_POINT_ALPHA_BITS) - 1 )
00067 
00068 #define RGB_TO_PIXEL(r, g, b) cmode.ARGBToColor(255, r, g, b) // Default to 255 alpha aka solid colour.
00069 
00070 static const int DRAW_DEPTH_ONLY = 0;
00071 static const int DRAW_FLAT = 1;
00072 static const int DRAW_SMOOTH = 2;
00073 static const int DRAW_SHADOW_MASK = 3;
00074 static const int DRAW_SHADOW = 4;
00075 
00076 struct Buffer {
00077     byte *pbuf;
00078     unsigned int *zbuf;
00079     bool used;
00080 };
00081 
00082 struct ZBufferPoint {
00083     int x, y, z;   // integer coordinates in the zbuffer
00084     int s, t;      // coordinates for the mapping
00085     int r, g, b, a;   // color indexes
00086 
00087     float sz, tz;  // temporary coordinates for mapping
00088 
00089     bool operator==(const ZBufferPoint &other) const {
00090         return  x == other.x &&
00091                 y == other.y && 
00092                 z == other.z &&
00093                 s == other.s &&
00094                 t == other.t && 
00095                 r == other.r && 
00096                 g == other.g && 
00097                 b == other.b &&
00098                 a == other.a;
00099     }
00100 };
00101 
00102 struct FrameBuffer {
00103     FrameBuffer(int xsize, int ysize, const Graphics::PixelBuffer &frame_buffer);
00104     ~FrameBuffer();
00105 
00106     Buffer *genOffscreenBuffer();
00107     void delOffscreenBuffer(Buffer *buffer);
00108     void clear(int clear_z, int z, int clear_color, int r, int g, int b);
00109     void clearRegion(int x, int y, int w, int h,int clear_z, int z, int clear_color, int r, int g, int b);
00110 
00111     byte *getPixelBuffer() {
00112         return pbuf.getRawBuffer(0);
00113     }
00114 
00115     unsigned int *getZBuffer() {
00116         return _zbuf;
00117     }
00118 
00119     FORCEINLINE void readPixelRGB(int pixel, byte &r, byte &g, byte &b) {
00120         pbuf.getRGBAt(pixel, r, g, b);
00121     }
00122 
00123     FORCEINLINE bool compareDepth(unsigned int &zSrc, unsigned int &zDst) {
00124         if (!_depthTestEnabled)
00125             return true;
00126 
00127         switch (_depthFunc) {
00128         case TGL_NEVER:
00129             break;
00130         case TGL_LESS:
00131             if (zDst < zSrc)
00132                 return true;
00133             break;
00134         case TGL_EQUAL:
00135             if (zDst == zSrc)
00136                 return true;
00137             break;
00138         case TGL_LEQUAL:
00139             if (zDst <= zSrc)
00140                 return true;
00141             break;
00142         case TGL_GREATER:
00143             if (zDst > zSrc)
00144                 return true;
00145             break;
00146         case TGL_NOTEQUAL:
00147             if (zDst != zSrc)
00148                 return true;
00149             break;
00150         case TGL_GEQUAL:
00151             if (zDst >= zSrc)
00152                 return true;
00153             break;
00154         case TGL_ALWAYS:
00155             return true;
00156         }
00157         return false;
00158     }
00159 
00160     FORCEINLINE bool checkAlphaTest(byte aSrc) {
00161         if (!_alphaTestEnabled)
00162             return true;
00163 
00164         switch (_alphaTestFunc) {
00165         case TGL_NEVER:
00166             break;
00167         case TGL_LESS:
00168             if (aSrc < _alphaTestRefVal)
00169                 return true;
00170             break;
00171         case TGL_EQUAL:
00172             if (aSrc == _alphaTestRefVal)
00173                 return true;
00174             break;
00175         case TGL_LEQUAL:
00176             if (aSrc <= _alphaTestRefVal)
00177                 return true;
00178             break;
00179         case TGL_GREATER:
00180             if (aSrc > _alphaTestRefVal)
00181                 return true;
00182             break;
00183         case TGL_NOTEQUAL:
00184             if (aSrc != _alphaTestRefVal)
00185                 return true;
00186             break;
00187         case TGL_GEQUAL:
00188             if (aSrc >= _alphaTestRefVal)
00189                 return true;
00190             break;
00191         case TGL_ALWAYS:
00192             return true;
00193         }
00194         return false;
00195     }
00196 
00197     template <bool kEnableAlphaTest, bool kBlendingEnabled>
00198     FORCEINLINE void writePixel(int pixel, int value) {
00199         writePixel<kEnableAlphaTest, kBlendingEnabled, false>(pixel, value, 0);
00200     }
00201 
00202     template <bool kEnableAlphaTest, bool kBlendingEnabled, bool kDepthWrite>
00203     FORCEINLINE void writePixel(int pixel, int value, unsigned int z) {
00204         if (kBlendingEnabled == false) {
00205             this->pbuf.setPixelAt(pixel, value);
00206             if (kDepthWrite) {
00207                 _zbuf[pixel] = z;
00208             }
00209         } else {
00210             byte rSrc, gSrc, bSrc, aSrc;
00211             this->pbuf.getFormat().colorToARGB(value, aSrc, rSrc, gSrc, bSrc);
00212 
00213             writePixel<kEnableAlphaTest, kBlendingEnabled, kDepthWrite>(pixel, aSrc, rSrc, gSrc, bSrc, z);
00214         }
00215     }
00216 
00217     FORCEINLINE void writePixel(int pixel, int value) {
00218         if (_alphaTestEnabled) {
00219             writePixel<true>(pixel, value);
00220         } else {
00221             writePixel<false>(pixel, value);
00222         }
00223     }
00224 
00225     template <bool kEnableAlphaTest>
00226     FORCEINLINE void writePixel(int pixel, int value) {
00227         if (_blendingEnabled) {
00228             writePixel<kEnableAlphaTest, true>(pixel, value);
00229         } else {
00230             writePixel<kEnableAlphaTest, false>(pixel, value);
00231         }
00232     }
00233 
00234     FORCEINLINE void writePixel(int pixel, byte rSrc, byte gSrc, byte bSrc) {
00235         writePixel(pixel, 255, rSrc, gSrc, bSrc);
00236     }
00237 
00238     FORCEINLINE bool scissorPixel(int x, int y) {
00239         return !_clipRectangle.contains(x, y);
00240     }
00241 
00242     FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
00243         if (_alphaTestEnabled) {
00244             writePixel<true>(pixel, aSrc, rSrc, gSrc, bSrc);
00245         } else {
00246             writePixel<false>(pixel, aSrc, rSrc, gSrc, bSrc);
00247         }
00248     }
00249 
00250     template <bool kEnableAlphaTest>
00251     FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
00252         if (_blendingEnabled) {
00253             writePixel<kEnableAlphaTest, true>(pixel, aSrc, rSrc, gSrc, bSrc);
00254         } else {
00255             writePixel<kEnableAlphaTest, false>(pixel, aSrc, rSrc, gSrc, bSrc);
00256         }
00257     }
00258 
00259     template <bool kEnableAlphaTest, bool kBlendingEnabled>
00260     FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
00261         writePixel<kEnableAlphaTest, kBlendingEnabled, false>(pixel, aSrc, rSrc, gSrc, bSrc, 0);
00262     }
00263 
00264     template <bool kEnableAlphaTest, bool kBlendingEnabled, bool kDepthWrite>
00265     FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc, unsigned int z) {
00266         if (kEnableAlphaTest) {
00267             if (!checkAlphaTest(aSrc))
00268                 return;
00269         }
00270         if (kDepthWrite) {
00271             _zbuf[pixel] = z;
00272         }
00273         
00274         if (kBlendingEnabled == false) {
00275             this->pbuf.setPixelAt(pixel, aSrc, rSrc, gSrc, bSrc);
00276         } else {
00277             byte rDst, gDst, bDst, aDst;
00278             this->pbuf.getARGBAt(pixel, aDst, rDst, gDst, bDst);
00279             switch (_sourceBlendingFactor) {
00280             case TGL_ZERO:
00281                 rSrc = gSrc = bSrc = 0;
00282                 break;
00283             case TGL_ONE:
00284                 break;
00285             case TGL_DST_COLOR:
00286                 rSrc = (rDst * rSrc) >> 8;
00287                 gSrc = (gDst * gSrc) >> 8;
00288                 bSrc = (bDst * bSrc) >> 8;
00289                 break;
00290             case TGL_ONE_MINUS_DST_COLOR:
00291                 rSrc = (rSrc * (255 - rDst)) >> 8;
00292                 gSrc = (gSrc * (255 - gDst)) >> 8;
00293                 bSrc = (bSrc * (255 - bDst)) >> 8;
00294                 break;
00295             case TGL_SRC_ALPHA:
00296                 rSrc = (rSrc * aSrc) >> 8;
00297                 gSrc = (gSrc * aSrc) >> 8;
00298                 bSrc = (bSrc * aSrc) >> 8;
00299                 break;
00300             case TGL_ONE_MINUS_SRC_ALPHA:
00301                 rSrc = (rSrc * (255 - aSrc)) >> 8;
00302                 gSrc = (gSrc * (255 - aSrc)) >> 8;
00303                 bSrc = (bSrc * (255 - aSrc)) >> 8;
00304                 break;
00305             case TGL_DST_ALPHA:
00306                 rSrc = (rSrc * aDst) >> 8;
00307                 gSrc = (gSrc * aDst) >> 8;
00308                 bSrc = (bSrc * aDst) >> 8;
00309                 break;
00310             case TGL_ONE_MINUS_DST_ALPHA:
00311                 rSrc = (rSrc * (255 - aDst)) >> 8;
00312                 gSrc = (gSrc * (255 - aDst)) >> 8;
00313                 bSrc = (bSrc * (255 - aDst)) >> 8;
00314                 break;
00315             default:
00316                 break;
00317             }
00318 
00319             switch (_destinationBlendingFactor) {
00320             case TGL_ZERO:
00321                 rDst = gDst = bDst = 0;
00322                 break;
00323             case TGL_ONE:
00324                 break;
00325             case TGL_DST_COLOR:
00326                 rDst = (rDst * rSrc) >> 8;
00327                 gDst = (gDst * gSrc) >> 8;
00328                 bDst = (bDst * bSrc) >> 8;
00329                 break;
00330             case TGL_ONE_MINUS_DST_COLOR:
00331                 rDst = (rDst * (255 - rSrc)) >> 8;
00332                 gDst = (gDst * (255 - gSrc)) >> 8;
00333                 bDst = (bDst * (255 - bSrc)) >> 8;
00334                 break;
00335             case TGL_SRC_ALPHA:
00336                 rDst = (rDst * aSrc) >> 8;
00337                 gDst = (gDst * aSrc) >> 8;
00338                 bDst = (bDst * aSrc) >> 8;
00339                 break;
00340             case TGL_ONE_MINUS_SRC_ALPHA:
00341                 rDst = (rDst * (255 - aSrc)) >> 8;
00342                 gDst = (gDst * (255 - aSrc)) >> 8;
00343                 bDst = (bDst * (255 - aSrc)) >> 8;
00344                 break;
00345             case TGL_DST_ALPHA:
00346                 rDst = (rDst * aDst) >> 8;
00347                 gDst = (gDst * aDst) >> 8;
00348                 bDst = (bDst * aDst) >> 8;
00349                 break;
00350             case TGL_ONE_MINUS_DST_ALPHA:
00351                 rDst = (rDst * (255 - aDst)) >> 8;
00352                 gDst = (gDst * (255 - aDst)) >> 8;
00353                 bDst = (bDst * (255 - aDst)) >> 8;
00354                 break;
00355             case TGL_SRC_ALPHA_SATURATE: {
00356                 int factor = aSrc < 1 - aDst ? aSrc : 1 - aDst;
00357                 rDst = (rDst * factor) >> 8;
00358                 gDst = (gDst * factor) >> 8;
00359                 bDst = (bDst * factor) >> 8;
00360                 }
00361                 break;
00362             default:
00363                 break;
00364             }
00365             int finalR, finalG, finalB;
00366             finalR = rDst + rSrc;
00367             finalG = gDst + gSrc;
00368             finalB = bDst + bSrc;
00369             if (finalR > 255) { finalR = 255; }
00370             if (finalG > 255) { finalG = 255; }
00371             if (finalB > 255) { finalB = 255; }
00372             this->pbuf.setPixelAt(pixel, 255, finalR, finalG, finalB);
00373         }
00374     }
00375 
00376     void copyToBuffer(Graphics::PixelBuffer &buf) {
00377         buf.copyBuffer(0, xsize * ysize, pbuf);
00378     }
00379 
00380     void copyFromBuffer(Graphics::PixelBuffer buf) {
00381         pbuf.copyBuffer(0, xsize * ysize, buf);
00382     }
00383     
00384     void enableBlending(bool enable) {
00385         _blendingEnabled = enable;
00386     }
00387 
00388     void enableDepthTest(bool enable) {
00389         _depthTestEnabled = enable;
00390     }
00391 
00392     void setBlendingFactors(int sFactor, int dFactor) {
00393         _sourceBlendingFactor = sFactor;
00394         _destinationBlendingFactor = dFactor;
00395     }
00396 
00397     void enableAlphaTest(bool enable) {
00398         _alphaTestEnabled = enable;
00399     }
00400 
00401     void setAlphaTestFunc(int func, int ref) {
00402         _alphaTestFunc = func;
00403         _alphaTestRefVal = ref;
00404     }
00405 
00406     void setDepthFunc(int func) {
00407         _depthFunc = func;
00408     }
00409 
00410     void enableDepthWrite(bool enable) {
00411         this->_depthWrite = enable;
00412     }
00413 
00414     bool isAlphaBlendingEnabled() const {
00415         return _sourceBlendingFactor == TGL_SRC_ALPHA && _destinationBlendingFactor == TGL_ONE_MINUS_SRC_ALPHA;
00416     }
00417 
00423     void blitOffscreenBuffer(Buffer *buffer);
00424     void selectOffscreenBuffer(Buffer *buffer);
00425     void clearOffscreenBuffer(Buffer *buffer);
00426     void setTexture(const Graphics::PixelBuffer &texture);
00427 
00428     template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor, bool enableBlending>
00429     void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00430 
00431     template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor>
00432     void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00433 
00434     template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool enableAlphaTest>
00435     void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00436 
00437     template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite>
00438     void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00439 
00440     template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode>
00441     void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00442 
00443     void fillTriangleTextureMappingPerspectiveSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00444     void fillTriangleTextureMappingPerspectiveFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00445     void fillTriangleDepthOnly(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00446     void fillTriangleFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00447     void fillTriangleSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00448     void fillTriangleFlatShadowMask(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00449     void fillTriangleFlatShadow(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
00450 
00451     void plot(ZBufferPoint *p);
00452     void fillLine(ZBufferPoint *p1, ZBufferPoint *p2);
00453     void fillLineZ(ZBufferPoint *p1, ZBufferPoint *p2);
00454     void fillLineFlatZ(ZBufferPoint *p1, ZBufferPoint *p2);
00455     void fillLineInterpZ(ZBufferPoint *p1, ZBufferPoint *p2);
00456     void fillLineFlat(ZBufferPoint *p1, ZBufferPoint *p2);
00457     void fillLineInterp(ZBufferPoint *p1, ZBufferPoint *p2);
00458 
00459     void setScissorRectangle(const Common::Rect &rect) {
00460         _clipRectangle = rect;
00461         _enableScissor = true;
00462     }
00463     void resetScissorRectangle() {
00464         _enableScissor = false;
00465     }
00466 
00467     Common::Rect _clipRectangle;
00468     bool _enableScissor;
00469     int xsize, ysize;
00470     int linesize; // line size, in bytes
00471     Graphics::PixelFormat cmode;
00472     int pixelbytes;
00473 
00474     Buffer buffer;
00475 
00476     unsigned char *shadow_mask_buf;
00477     int shadow_color_r;
00478     int shadow_color_g;
00479     int shadow_color_b;
00480     int frame_buffer_allocated;
00481 
00482     unsigned char *dctable;
00483     int *ctable;
00484     Graphics::PixelBuffer current_texture;
00485     int _textureSize;
00486     int _textureSizeMask;
00487 
00488     FORCEINLINE bool isBlendingEnabled() const { return _blendingEnabled; }
00489     FORCEINLINE void getBlendingFactors(int &sourceFactor, int &destinationFactor) const { sourceFactor = _sourceBlendingFactor; destinationFactor = _destinationBlendingFactor; }
00490     FORCEINLINE bool isAlphaTestEnabled() const { return _alphaTestEnabled; }
00491     FORCEINLINE bool isDepthWriteEnabled() const { return _depthWrite; }
00492     FORCEINLINE int getDepthFunc() const { return _depthFunc; }
00493     FORCEINLINE int getDepthWrite() const { return _depthWrite; }
00494     FORCEINLINE int getAlphaTestFunc() const { return _alphaTestFunc; }
00495     FORCEINLINE int getAlphaTestRefVal() const { return _alphaTestRefVal; }
00496     FORCEINLINE int getDepthTestEnabled() const { return _depthTestEnabled; }
00497 
00498 private:
00499 
00500     template <bool kDepthWrite>
00501     FORCEINLINE void putPixel(unsigned int pixelOffset, int color, int x, int y, unsigned int z);
00502 
00503     template <bool kDepthWrite, bool kEnableScissor>
00504     FORCEINLINE void putPixel(unsigned int pixelOffset, int color, int x, int y, unsigned int z);
00505 
00506     template <bool kEnableScissor>
00507     FORCEINLINE void putPixel(unsigned int pixelOffset, int color, int x, int y);
00508 
00509     template <bool kInterpRGB, bool kInterpZ, bool kDepthWrite>
00510     void drawLine(const ZBufferPoint *p1, const ZBufferPoint *p2);
00511 
00512     template <bool kInterpRGB, bool kInterpZ, bool kDepthWrite, bool kEnableScissor>
00513     void drawLine(const ZBufferPoint *p1, const ZBufferPoint *p2);
00514 
00515     unsigned int *_zbuf;
00516     bool _depthWrite;
00517     Graphics::PixelBuffer pbuf;
00518     bool _blendingEnabled;
00519     int _sourceBlendingFactor;
00520     int _destinationBlendingFactor;
00521     bool _alphaTestEnabled;
00522     bool _depthTestEnabled;
00523     int _alphaTestFunc;
00524     int _alphaTestRefVal;
00525     int _depthFunc;
00526 };
00527 
00528 // memory.c
00529 void gl_free(void *p);
00530 void *gl_malloc(int size);
00531 void *gl_zalloc(int size);
00532 
00533 } // end of namespace TinyGL
00534 
00535 #endif


Generated on Sat May 18 2019 05:01:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge