TINYGL: Implemented alpha blending and color transformation in sprite blitting for Grim TinyGL renderer.

This commit is contained in:
Stefano Musumeci 2014-06-20 14:13:52 +02:00
parent 63fd685589
commit 109767e513
10 changed files with 197 additions and 273 deletions

View file

@ -636,12 +636,11 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
}
// FIXME: TinyGL doesn't seem to support translucency.
const float alpha = actor->getEffectiveAlpha();
if (alpha < 1.f) {
_alpha = alpha;
tglEnable(TGL_BLEND);
//tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
tglEnable(TGL_BLEND);
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
}
const Math::Quaternion &quat = actor->getRotationQuat();
@ -686,7 +685,7 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
}
if (actor->getSortOrder() >= 100) {
tglColorMask(false, false, false, false);
tglColorMask(TGL_FALSE, TGL_FALSE, TGL_FALSE, TGL_FALSE);
}
}
@ -698,9 +697,8 @@ void GfxTinyGL::finishActorDraw() {
tglMatrixMode(TGL_MODELVIEW);
tglDisable(TGL_TEXTURE_2D);
// FIXME: TinyGL doesn't seem to support translucency.
if (_alpha < 1.f) {
tglDisable(TGL_BLEND);
tglDisable(TGL_BLEND);
_alpha = 1.f;
}
@ -823,6 +821,8 @@ void GfxTinyGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
tglEnable(TGL_TEXTURE_2D);
tglEnable(TGL_DEPTH_TEST);
tglEnable(TGL_ALPHA_TEST);
tglDisable(TGL_BLEND);
tglColor3f(1.0f, 1.0f, 1.0f);
}
void GfxTinyGL::drawModelFace(const Mesh *mesh, const MeshFace *face) {
@ -837,7 +837,7 @@ void GfxTinyGL::drawModelFace(const Mesh *mesh, const MeshFace *face) {
if (face->hasTexture())
tglTexCoord2fv(textureVerts + 2 * face->getTextureVertex(i));
tglColor4f(1.0f,1.0f,1.0f,_alpha);
tglColor4f(1.0f, 1.0f, 1.0f, _alpha);
tglVertex3fv(vertices + 3 * face->getVertex(i));
}
tglEnd();
@ -884,9 +884,9 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
}
if (sprite->_blendMode == Sprite::BlendAdditive) {
//tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE);
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE);
} else {
//tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
}
tglDisable(TGL_LIGHTING);
@ -955,7 +955,8 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
tglEnable(TGL_LIGHTING);
tglDisable(TGL_ALPHA_TEST);
//tglDepthMask(GL_TRUE);
//tglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
tglDisable(TGL_BLEND);
tglEnable(TGL_DEPTH_TEST);
tglPopMatrix();
@ -1063,7 +1064,7 @@ void GfxTinyGL::createBitmap(BitmapData *bitmap) {
}
}
void GfxTinyGL::blitScreen( const Graphics::PixelFormat &format, BlitImage *image, byte *src, int x, int y, int width, int height, bool trans ) {
void GfxTinyGL::blitScreen(const Graphics::PixelFormat &format, BlitImage *image, byte *src, int x, int y, int width, int height, bool trans, bool dimSprites) {
int srcX, srcY;
if (x < 0) {
@ -1080,7 +1081,7 @@ void GfxTinyGL::blitScreen( const Graphics::PixelFormat &format, BlitImage *imag
srcY = 0;
}
blitScreen(format, image, src, x, y, srcX, srcY, width, height, width, height, trans);
blitScreen(format, image, src, x, y, srcX, srcY, width, height, width, height, trans, dimSprites);
}
void GfxTinyGL::blit(const Graphics::PixelFormat &format, BlitImage *image, byte *dst, byte *src, int x, int y, int width, int height, bool trans) {
@ -1146,9 +1147,9 @@ void GfxTinyGL::blit(const Graphics::PixelFormat &format, BlitImage *image, byte
while (l && l->y < maxY) {
if (l->x < maxX && l->x + l->length > srcX) {
int length = l->length;
int skipStart = l->x < srcX ? srcX - l->x : 0;
int skipStart = (l->x < srcX) ? (srcX - l->x) : 0;
length -= skipStart;
int skipEnd = l->x + l->length > maxX ? l->x + l->length - maxX : 0;
int skipEnd = (l->x + l->length > maxX) ? (l->x + l->length - maxX) : 0;
length -= skipEnd;
memcpy(dstBuf.getRawBuffer((l->y - srcY) * _gameWidth + MAX(l->x - srcX, 0)),
l->pixels + skipStart * format.bytesPerPixel, length * format.bytesPerPixel);
@ -1169,12 +1170,7 @@ void GfxTinyGL::blit(const Graphics::PixelFormat &format, BlitImage *image, byte
}
}
void GfxTinyGL::blitScreen( const Graphics::PixelFormat &format, BlitImage *image, byte *src, int dstX, int dstY, int srcX, int srcY, int width, int height, int srcWidth, int srcHeight, bool trans ) {
if (_dimLevel > 0.0f && _dimLevel < 1.0f) {
warning("TinyGL doesn't implement partial screen-dimming yet");
}
void GfxTinyGL::blitScreen(const Graphics::PixelFormat &format, BlitImage *image, byte *src, int dstX, int dstY, int srcX, int srcY, int width, int height, int srcWidth, int srcHeight, bool trans, bool dimSprites) {
if (dstX >= _gameWidth || dstY >= _gameHeight)
return;
@ -1190,49 +1186,69 @@ void GfxTinyGL::blitScreen( const Graphics::PixelFormat &format, BlitImage *imag
else
clampHeight = height;
byte *dst = _zb->getPixelBuffer();
dst += (dstX + (dstY * _gameWidth)) * format.bytesPerPixel;
int blendEnabled;
tglGetIntegerv(TGL_BLEND, &blendEnabled);
src += (srcX + (srcY * srcWidth)) * format.bytesPerPixel;
Graphics::PixelBuffer srcBuf(format, src);
Graphics::PixelBuffer dstBuf(format, dst);
bool hasDim = _dimLevel > 0.0f;
dimSprites &= hasDim;
if (!trans) {
for (int l = 0; l < clampHeight; l++) {
dstBuf.copyBuffer(0, clampWidth, srcBuf);
dstBuf.shiftBy(_gameWidth);
srcBuf.shiftBy(srcWidth);
}
} else {
if (image) {
BlitImage::Line *l = image->_lines;
int maxY = srcY + clampHeight;
int maxX = srcX + clampWidth;
while (l && l->y < srcY)
l = l->next;
while (l && l->y < maxY) {
if (l->x < maxX && l->x + l->length > srcX) {
int length = l->length;
int skipStart = l->x < srcX ? srcX - l->x : 0;
length -= skipStart;
int skipEnd = l->x + l->length > maxX ? l->x + l->length - maxX : 0;
length -= skipEnd;
memcpy(dstBuf.getRawBuffer((l->y - srcY) * _gameWidth + MAX(l->x - srcX, 0)),
l->pixels + skipStart * format.bytesPerPixel, length * format.bytesPerPixel);
}
l = l->next;
}
} else {
if ((trans == false || blendEnabled == false) && (dimSprites == false)) {
byte *dst = _zb->getPixelBuffer();
dst += (dstX + (dstY * _gameWidth)) * format.bytesPerPixel;
Graphics::PixelBuffer dstBuf(format, dst);
if (!trans) {
for (int l = 0; l < clampHeight; l++) {
for (int r = 0; r < clampWidth; ++r) {
if (srcBuf.getValueAt(r) != 0xf81f) {
dstBuf.setPixelAt(r, srcBuf);
}
}
dstBuf.copyBuffer(0, clampWidth, srcBuf);
dstBuf.shiftBy(_gameWidth);
srcBuf.shiftBy(srcWidth);
}
} else {
if (image) {
BlitImage::Line *l = image->_lines;
int maxY = srcY + clampHeight;
int maxX = srcX + clampWidth;
while (l && l->y < srcY) {
l = l->next;
}
while (l && l->y < maxY) {
if (l->x < maxX && l->x + l->length > srcX) {
int length = l->length;
int skipStart = (l->x < srcX) ? (srcX - l->x) : 0;
length -= skipStart;
int skipEnd = (l->x + l->length > maxX) ? (l->x + l->length - maxX) : 0;
length -= skipEnd;
memcpy(dstBuf.getRawBuffer((l->y - srcY) * _gameWidth + MAX(l->x - srcX, 0)),
l->pixels + skipStart * format.bytesPerPixel, length * format.bytesPerPixel);
}
l = l->next;
}
} else {
for (int l = 0; l < clampHeight; l++) {
for (int r = 0; r < clampWidth; ++r) {
if (srcBuf.getValueAt(r) != 0xf81f) {
dstBuf.setPixelAt(r, srcBuf);
}
}
dstBuf.shiftBy(_gameWidth);
srcBuf.shiftBy(srcWidth);
}
}
}
} else {
float colFactor = 1.0f - _dimLevel;
if (dimSprites == false) {
colFactor = 1.0f;
}
for (int l = 0; l < clampHeight; l++) {
for (int r = 0; r < clampWidth; ++r) {
byte aDst, rDst, gDst, bDst;
srcBuf.getARGBAt(r, aDst, rDst, gDst, bDst);
if (rDst == 248 && gDst == 0 && bDst == 248)
continue;
_zb->writePixel((dstX + r) + (dstY + l) * _gameWidth, aDst, rDst * colFactor, gDst * colFactor, bDst * colFactor);
}
srcBuf.shiftBy(srcWidth);
}
}
}
@ -1264,7 +1280,7 @@ void GfxTinyGL::drawBitmap(const Bitmap *bitmap, int x, int y, uint32 layer) {
int srcY = texc[ntex + 3] * bitmap->getHeight();
blitScreen(bitmap->getPixelFormat(texId), &b[texId], bitmap->getData(texId).getRawBuffer(),
x + dx1, y + dy1, srcX, srcY, dx2 - dx1, dy2 - dy1, b[texId]._width, b[texId]._height, true);
x + dx1, y + dy1, srcX, srcY, dx2 - dx1, dy2 - dy1, b[texId]._width, b[texId]._height, true, true);
ntex += 16;
}
}
@ -1284,7 +1300,7 @@ void GfxTinyGL::drawBitmap(const Bitmap *bitmap, int x, int y, uint32 layer) {
if (bitmap->getFormat() == 1)
blitScreen(bitmap->getPixelFormat(num), &b[num], (byte *)bitmap->getData(num).getRawBuffer(),
x, y, bitmap->getWidth(), bitmap->getHeight(), true);
x, y, bitmap->getWidth(), bitmap->getHeight(), true, false);
else
blit(bitmap->getPixelFormat(num), nullptr, (byte *)_zb->zbuf, (byte *)bitmap->getData(num).getRawBuffer(),
x, y, bitmap->getWidth(), bitmap->getHeight(), false);
@ -1391,7 +1407,7 @@ void GfxTinyGL::drawTextObject(const TextObject *text) {
if (userData) {
int numLines = text->getNumLines();
for (int i = 0; i < numLines; ++i) {
blitScreen(_pixelFormat, nullptr, userData[i].data, userData[i].x, userData[i].y, userData[i].width, userData[i].height, true);
blitScreen(_pixelFormat, nullptr, userData[i].data, userData[i].x, userData[i].y, userData[i].width, userData[i].height, true, false);
}
}
}
@ -1469,9 +1485,9 @@ void GfxTinyGL::selectMaterial(const Texture *material) {
TGLuint *textures = (TGLuint *)material->_texture;
tglBindTexture(TGL_TEXTURE_2D, textures[0]);
/*if (material->_hasAlpha && g_grim->getGameType() == GType_MONKEY4) {
if (material->_hasAlpha && g_grim->getGameType() == GType_MONKEY4) {
tglEnable(TGL_BLEND);
}*/
}
// Grim has inverted tex-coords, EMI doesn't
if (g_grim->getGameType() != GType_MONKEY4) {
@ -1502,7 +1518,7 @@ void GfxTinyGL::drawMovieFrame(int offsetX, int offsetY) {
if (_smushWidth == _gameWidth && _smushHeight == _gameHeight) {
_zb->copyFromBuffer(_smushBitmap);
} else {
blitScreen(_pixelFormat, nullptr, _smushBitmap.getRawBuffer(), offsetX, offsetY, _smushWidth, _smushHeight, false);
blitScreen(_pixelFormat, nullptr, _smushBitmap.getRawBuffer(), offsetX, offsetY, _smushWidth, _smushHeight, false, false);
}
}

View file

@ -146,8 +146,8 @@ private:
void readPixels(int x, int y, int width, int height, uint8 *buffer);
void blit(const Graphics::PixelFormat &format, BlitImage *blit, byte *dst, byte *src, int x, int y, int width, int height, bool trans);
void blit(const Graphics::PixelFormat &format, BlitImage *blit, byte *dst, byte *src, int dstX, int dstY, int srcX, int srcY, int width, int height, int srcWidth, int srcHeight, bool trans);
void blitScreen(const Graphics::PixelFormat &format, BlitImage *blit, byte *src, int x, int y, int width, int height, bool trans);
void blitScreen(const Graphics::PixelFormat &format, BlitImage *blit, byte *src, int dstX, int dstY, int srcX, int srcY, int width, int height, int srcWidth, int srcHeight, bool trans);
void blitScreen(const Graphics::PixelFormat &format, BlitImage *blit, byte *src, int x, int y, int width, int height, bool trans, bool dimSprites);
void blitScreen(const Graphics::PixelFormat &format, BlitImage *blit, byte *src, int dstX, int dstY, int srcX, int srcY, int width, int height, int srcWidth, int srcHeight, bool trans, bool dimSprites);
};
} // end of namespace Grim

View file

@ -28,6 +28,9 @@ void tglGetIntegerv(int pname, int *params) {
case TGL_MAX_TEXTURE_STACK_DEPTH:
*params = MAX_TEXTURE_STACK_DEPTH;
break;
case TGL_BLEND:
*params = c->enableBlend;
break;
default:
error("glGet: option not implemented");
break;

View file

@ -126,7 +126,7 @@ void glInit(void *zbuffer1) {
c->render_mode = TGL_RENDER;
c->select_buffer = NULL;
c->name_stack_size = 0;
c->enable_blend = false;
c->enableBlend = false;
// matrix
c->matrix_mode = 0;
@ -146,6 +146,7 @@ void glInit(void *zbuffer1) {
tglLoadIdentity();
tglMatrixMode(TGL_MODELVIEW);
tglLoadIdentity();
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
c->matrix_model_projection_updated = 1;

View file

@ -62,6 +62,7 @@ void glopEnableDisable(GLContext *c, GLParam *p) {
c->depth_test = v;
break;
case TGL_BLEND:
c->enableBlend = v;
c->fb->enableBlending(v);
break;
case TGL_POLYGON_OFFSET_FILL:
@ -107,7 +108,7 @@ void glopEnableDisable(GLContext *c, GLParam *p) {
void glopBlendFunc(GLContext *c, GLParam *p) {
TGLenum sfactor = p[1].i;
TGLenum dfactor = p[2].i;
c->fb->setBlendingFactors(sfactor,dfactor);
c->fb->setBlendingFactors(sfactor, dfactor);
}
void glopShadeModel(GLContext *c, GLParam *p) {

View file

@ -162,13 +162,13 @@ void FrameBuffer::setTexture(const Graphics::PixelBuffer &texture) {
current_texture = texture;
}
void FrameBuffer::setBlendingFactors(int sfactor, int dfactor) {
_sourceBlendingFactor = sfactor;
_destinationBlendingFactor = dfactor;
void FrameBuffer::setBlendingFactors(int sFactor, int dFactor) {
_sourceBlendingFactor = sFactor;
_destinationBlendingFactor = dFactor;
}
void FrameBuffer::enableBlending(bool enableBlending) {
_blendingEnabled = enableBlending;
void FrameBuffer::enableBlending(bool enable) {
_blendingEnabled = enable;
}
} // end of namespace TinyGL

View file

@ -71,202 +71,124 @@ struct FrameBuffer {
this->pbuf.setPixelAt(pixel, value);
} else {
byte rSrc, gSrc, bSrc, aSrc;
this->pbuf.getFormat().colorToARGB(value, aSrc, rSrc, gSrc, bSrc);
writePixel(pixel, aSrc, rSrc, gSrc, bSrc);
}
}
FORCEINLINE void writePixel(int pixel, byte rSrc, byte gSrc, byte bSrc) {
writePixel(pixel, 255, rSrc, gSrc, bSrc);
}
FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
if (_blendingEnabled == false) {
this->pbuf.setPixelAt(pixel, aSrc, rSrc, gSrc, bSrc);
} else {
byte rDst, gDst, bDst, aDst;
this->pbuf.getFormat().colorToARGB(value, aDst, rDst, gDst, bDst);
this->pbuf.getARGBAt(pixel, aDst, rDst, gDst, bDst);
switch (_sourceBlendingFactor) {
case TGL_ZERO:
rSrc = gSrc = bSrc = 0;
break;
case TGL_ONE:
break;
case TGL_DST_COLOR:
rSrc = (rDst * rSrc) >> 8;
gSrc = (gDst * gSrc) >> 8;
bSrc = (bDst * bSrc) >> 8;
break;
case TGL_ONE_MINUS_DST_COLOR:
rSrc = (rSrc * (255 - rDst)) >> 8;
gSrc = (gSrc * (255 - gDst)) >> 8;
bSrc = (bSrc * (255 - bDst)) >> 8;
break;
case TGL_SRC_ALPHA:
rSrc = (rSrc * aSrc) >> 8;
gSrc = (gSrc * aSrc) >> 8;
bSrc = (bSrc * aSrc) >> 8;
break;
case TGL_ONE_MINUS_SRC_ALPHA:
rSrc = (rSrc * (255 - aSrc)) >> 8;
gSrc = (gSrc * (255 - aSrc)) >> 8;
bSrc = (bSrc * (255 - aSrc)) >> 8;
break;
case TGL_DST_ALPHA:
rSrc = (rSrc * aDst) >> 8;
gSrc = (gSrc * aDst) >> 8;
bSrc = (bSrc * aDst) >> 8;
break;
case TGL_ONE_MINUS_DST_ALPHA:
rSrc = (rSrc * (255 - aDst)) >> 8;
gSrc = (gSrc * (255 - aDst)) >> 8;
bSrc = (bSrc * (255 - aDst)) >> 8;
break;
default:
break;
}
switch (_destinationBlendingFactor) {
case TGL_ZERO:
rDst = gDst = bDst = 0;
break;
case TGL_ONE:
break;
case TGL_DST_COLOR:
this->pbuf.getRGBAt(pixel, rSrc, gSrc, bSrc);
rDst = (rSrc * rDst) >> 8;
gDst = (gSrc * gDst) >> 8;
bDst = (bSrc * bDst) >> 8;
rDst = (rDst * rSrc) >> 8;
gDst = (gDst * gSrc) >> 8;
bDst = (bDst * bSrc) >> 8;
break;
case TGL_ONE_MINUS_DST_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:
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_SRC_ALPHA:
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
case TGL_ONE_MINUS_DST_ALPHA:
rDst = (rDst * (255 - aDst)) >> 8;
gDst = (gDst * (255 - aDst)) >> 8;
bDst = (bDst * (255 - aDst)) >> 8;
break;
case TGL_DST_ALPHA:
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;
int factor = aSrc < 1 - aDst ? aSrc : 1 - aDst;
rDst = (rDst * factor) >> 8;
gDst = (gDst * factor) >> 8;
bDst = (bDst * factor) >> 8;
}
break;
default:
break;
}
switch (_destinationBlendingFactor) {
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 * aDst) >> 8;
gSrc = (gSrc * aDst) >> 8;
bSrc = (bSrc * aDst) >> 8;
break;
case TGL_ONE_MINUS_SRC_ALPHA:
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
rSrc = (rSrc * (255 - aDst)) >> 8;
gSrc = (gSrc * (255 - aDst)) >> 8;
bSrc = (bSrc * (255 - aDst)) >> 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;
}
this->pbuf.setPixelAt(pixel,255,rSrc + rDst,gSrc + gDst,bSrc + bDst);
int finalR, finalG, finalB;
finalR = rDst + rSrc;
finalG = gDst + gSrc;
finalB = bDst + bSrc;
if (finalR > 255) { finalR = 255; }
if (finalG > 255) { finalG = 255; }
if (finalB > 255) { finalB = 255; }
this->pbuf.setPixelAt(pixel, 255, finalR, finalG, finalB);
}
}
FORCEINLINE void writePixel(int pixel, byte rDst, byte gDst, byte bDst) {
writePixel(pixel, 255, rDst, gDst, bDst);
void copyToBuffer(Graphics::PixelBuffer &buf) {
buf.copyBuffer(0, xsize * ysize, pbuf);
}
FORCEINLINE void writePixel(int pixel, byte aDst, byte rDst, byte gDst, byte bDst) {
if (_blendingEnabled == false) {
this->pbuf.setPixelAt(pixel, aDst, rDst, gDst, bDst);
} else {
byte rSrc, gSrc, bSrc, aSrc;
switch (_sourceBlendingFactor) {
case TGL_ZERO:
rDst = gDst = bDst = 0;
break;
case TGL_ONE:
break;
case TGL_DST_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_DST_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 * aDst) >> 8;
gDst = (gDst * aDst) >> 8;
bDst = (bDst * aDst) >> 8;
break;
case TGL_ONE_MINUS_SRC_ALPHA:
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
rDst = (rDst * (255 - aDst)) >> 8;
gDst = (gDst * (255 - aDst)) >> 8;
bDst = (bDst * (255 - aDst)) >> 8;
break;
case TGL_DST_ALPHA:
break;
case TGL_ONE_MINUS_DST_ALPHA:
rDst = gDst = bDst = 0;
break;
default:
break;
}
switch (_destinationBlendingFactor) {
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 * aDst) >> 8;
gSrc = (gSrc * aDst) >> 8;
bSrc = (bSrc * aDst) >> 8;
break;
case TGL_ONE_MINUS_SRC_ALPHA:
this->pbuf.getARGBAt(pixel, aSrc, rSrc, gSrc, bSrc);
rSrc = (rSrc * (255 - aDst)) >> 8;
gSrc = (gSrc * (255 - aDst)) >> 8;
bSrc = (bSrc * (255 - aDst)) >> 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;
}
this->pbuf.setPixelAt(pixel, 255, rSrc + rDst, gSrc + gDst, bSrc + bDst);
}
}
void copyToBuffer(Graphics::PixelBuffer &buffer) {
buffer.copyBuffer(0, xsize * ysize, pbuf);
}
void copyFromBuffer(Graphics::PixelBuffer &buffer) {
pbuf.copyBuffer(0, xsize * ysize, buffer);
void copyFromBuffer(Graphics::PixelBuffer buf) {
pbuf.copyBuffer(0, xsize * ysize, buf);
}
void enableBlending(bool enableBlending);

View file

@ -209,7 +209,7 @@ struct GLContext {
gl_draw_triangle_func draw_triangle_front, draw_triangle_back;
// selection
bool enable_blend;
bool enableBlend;
int render_mode;
unsigned int *select_buffer;
int select_size;

View file

@ -75,7 +75,7 @@ FORCEINLINE static void drawLine(FrameBuffer *buffer, ZBufferPoint *p1, ZBufferP
template <bool interpRGB, bool interpZ>
void FrameBuffer::fillLine(ZBufferPoint *p1, ZBufferPoint *p2, int color) {
int dx, dy, sx, pp;
int dx, dy, sx;
unsigned int r, g, b;
unsigned int *pz = NULL;
unsigned int z;
@ -105,20 +105,16 @@ void FrameBuffer::fillLine(ZBufferPoint *p1, ZBufferPoint *p2, int color) {
putPixel<interpRGB, interpZ>(this, pixelOffset, cmode, pz, z, color, r, g, b);
} else if (dx > 0) {
if (dx >= dy) {
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx + 1,
1);
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx + 1, 1);
} else {
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx + 1,
sx);
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx + 1, sx);
}
} else {
dx = -dx;
if (dx >= dy) {
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx - 1,
-1);
drawLine<interpRGB, interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx - 1, -1);
} else {
drawLine<interpRGB,interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx - 1,
sx);
drawLine<interpRGB,interpZ>(this, p1, p2, pixelOffset, cmode, pz, z, color, r, g, b, dx, dy, sx - 1, sx);
}
}
}

View file

@ -72,33 +72,18 @@ FORCEINLINE static void putPixelMappingPerspective(FrameBuffer *buffer, int buf,
c_r = (col >> textureFormat.rShift) & 0xFF;
c_g = (col >> textureFormat.gShift) & 0xFF;
c_b = (col >> textureFormat.bShift) & 0xFF;
if (c_a == 0xFF) {
tmp = rgba & 0xF81F07E0;
unsigned int light = tmp | (tmp >> 16);
unsigned int l_r = (light & 0xF800) >> 8;
unsigned int l_g = (light & 0x07E0) >> 3;
unsigned int l_b = (light & 0x001F) << 3;
unsigned int l_a = (a / 256);
c_a = (c_a * l_a) / 256;
c_r = (c_r * l_r) / 256;
c_g = (c_g * l_g) / 256;
c_b = (c_b * l_b) / 256;
buffer->writePixel(buf + _a, c_a, c_r, c_g, c_b);
pz[_a] = z;
} else if (c_a != 0) { // Implementing non binary alpha blending.
tmp = rgba & 0xF81F07E0;
unsigned int light = tmp | (tmp >> 16);
unsigned int l_r = (light & 0xF800) >> 8;
unsigned int l_g = (light & 0x07E0) >> 3;
unsigned int l_b = (light & 0x001F) << 3;
unsigned int l_a = (a / 256);
c_a = (c_a * l_a) / 256;
c_r = (c_r * l_r) / 256;
c_g = (c_g * l_g) / 256;
c_b = (c_b * l_b) / 256;
buffer->writePixel(buf + _a, c_a, c_r, c_g, c_b);
pz[_a] = z;
}
tmp = rgba & 0xF81F07E0;
unsigned int light = tmp | (tmp >> 16);
unsigned int l_r = (light & 0xF800) >> 8;
unsigned int l_g = (light & 0x07E0) >> 3;
unsigned int l_b = (light & 0x001F) << 3;
unsigned int l_a = (a / 256);
c_a = (c_a * l_a) / 256;
c_r = (c_r * l_r) / 256;
c_g = (c_g * l_g) / 256;
c_b = (c_b * l_b) / 256;
buffer->writePixel(buf + _a, c_a, c_r, c_g, c_b);
pz[_a] = z;
}
z += dzdx;
s += dsdx;