mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 03:10:22 +00:00
added initial support for shadows in software renderer but still a bit broken
This commit is contained in:
parent
6cc8a3db80
commit
5ea5ffb030
@ -578,6 +578,9 @@
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle_shadow.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="imuse">
|
||||
|
@ -592,6 +592,9 @@
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle_shadow.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="imuse">
|
||||
|
@ -810,6 +810,10 @@
|
||||
RelativePath="..\..\engine\tinygl\ztriangle.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle_shadow.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="imuse"
|
||||
|
@ -815,6 +815,10 @@
|
||||
RelativePath="..\..\engine\tinygl\ztriangle.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\tinygl\ztriangle_shadow.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="imuse"
|
||||
|
@ -62,7 +62,8 @@ Actor::Actor(const char *name) :
|
||||
_shadowArray = new Shadow[5];
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_shadowArray[i].active = true;
|
||||
_shadowArray[i].active = false;
|
||||
_shadowArray[i].shadowMask = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@ -599,12 +600,36 @@ void Actor::draw() {
|
||||
for (std::list<Costume *>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); i++)
|
||||
(*i)->setupTextures();
|
||||
|
||||
if (!g_driver->isHardwareAccelerated()/* && g_engine->getFlagRefreshShadowMask()*/) {
|
||||
for (int l = 0; l < 5; l++) {
|
||||
if (!_shadowArray[l].active)
|
||||
continue;
|
||||
g_driver->setShadow(&_shadowArray[l]);
|
||||
g_driver->drawShadowPlanes();
|
||||
g_driver->setShadow(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_costumeStack.empty()) {
|
||||
setupDrawShadow();
|
||||
Costume *costume = _costumeStack.back();
|
||||
if (!g_driver->isHardwareAccelerated()) {
|
||||
for (int l = 0; l < 5; l++) {
|
||||
if (!_shadowArray[l].active)
|
||||
continue;
|
||||
g_driver->setShadow(&_shadowArray[l]);
|
||||
g_driver->setShadowMode();
|
||||
g_driver->startActorDraw(_pos, _yaw, _pitch, _roll);
|
||||
costume->draw();
|
||||
g_driver->finishActorDraw();
|
||||
g_driver->setShadow(NULL);
|
||||
g_driver->clearShadowMode();
|
||||
}
|
||||
}
|
||||
|
||||
// normal draw actor
|
||||
g_driver->startActorDraw(_pos, _yaw, _pitch, _roll);
|
||||
_costumeStack.back()->draw();
|
||||
costume->draw();
|
||||
g_driver->finishActorDraw();
|
||||
finishDrawShadow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,6 +665,20 @@ void Actor::setActiveShadow(int shadowId) {
|
||||
assert(shadowId >= 0 && shadowId <= 4);
|
||||
|
||||
_activeShadowSlot = shadowId;
|
||||
_shadowArray[_activeShadowSlot].active = true;
|
||||
}
|
||||
|
||||
void Actor::setShadowValid(int valid) {
|
||||
/* if (valid == -1)
|
||||
_shadowArray[_activeShadowSlot].active = false;
|
||||
else
|
||||
_shadowArray[_activeShadowSlot].active = true;*/
|
||||
}
|
||||
|
||||
void Actor::setActivateShadow(int shadowId, bool state) {
|
||||
assert(shadowId >= 0 && shadowId <= 4);
|
||||
|
||||
_shadowArray[shadowId].active = state;
|
||||
}
|
||||
|
||||
void Actor::setShadowPoint(Vector3d pos) {
|
||||
@ -654,16 +693,9 @@ void Actor::clearShadowPlanes() {
|
||||
while (!shadow->planeList.empty()) {
|
||||
shadow->planeList.pop_back();
|
||||
}
|
||||
delete[] shadow->shadowMask;
|
||||
shadow->shadowMask = NULL;
|
||||
shadow->active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Actor::setupDrawShadow() {
|
||||
if (_activeShadowSlot == -1)
|
||||
return;
|
||||
|
||||
g_driver->setupShadower(_shadowArray);
|
||||
}
|
||||
|
||||
void Actor::finishDrawShadow() {
|
||||
g_driver->setupShadower(NULL);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ struct Shadow {
|
||||
std::string name;
|
||||
Vector3d pos;
|
||||
SectorListType planeList;
|
||||
byte *shadowMask;
|
||||
bool active;
|
||||
};
|
||||
|
||||
@ -132,8 +133,8 @@ public:
|
||||
void setShadowPlane(const char *name);
|
||||
void addShadowPlane(const char *name);
|
||||
void clearShadowPlanes();
|
||||
void setupDrawShadow();
|
||||
void finishDrawShadow();
|
||||
void setShadowValid(int);
|
||||
void setActivateShadow(int, bool);
|
||||
|
||||
void setConstrain(bool constrain) {
|
||||
_constrain = constrain;
|
||||
|
@ -78,7 +78,11 @@ public:
|
||||
|
||||
virtual void startActorDraw(Vector3d pos, float yaw, float pitch, float roll) = 0;
|
||||
virtual void finishActorDraw() = 0;
|
||||
virtual void setupShadower(Shadow *shadow) = 0;
|
||||
virtual void setShadow(Shadow *shadow) = 0;
|
||||
virtual void drawShadowPlanes() = 0;
|
||||
virtual void setShadowMode() = 0;
|
||||
virtual void clearShadowMode() = 0;
|
||||
virtual void setShadowColor(byte r, byte g, byte b) = 0;
|
||||
|
||||
virtual void set3DMode() = 0;
|
||||
|
||||
@ -296,6 +300,9 @@ protected:
|
||||
int _screenWidth, _screenHeight, _screenBPP;
|
||||
bool _isFullscreen;
|
||||
Shadow *_currentShadowArray;
|
||||
unsigned char _shadowColorR;
|
||||
unsigned char _shadowColorG;
|
||||
unsigned char _shadowColorB;
|
||||
};
|
||||
|
||||
extern Driver *g_driver;
|
||||
|
@ -131,7 +131,19 @@ void DriverGL::finishActorDraw() {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void DriverGL::setupShadower(Shadow *shadow) {
|
||||
void DriverGL::setShadow(Shadow *shadow) {
|
||||
}
|
||||
|
||||
void DriverGL::drawShadowPlanes() {
|
||||
}
|
||||
|
||||
void DriverGL::setShadowMode() {
|
||||
}
|
||||
|
||||
void DriverGL::clearShadowMode() {
|
||||
}
|
||||
|
||||
void DriverGL::setShadowColor(byte r, byte g, byte b) {
|
||||
}
|
||||
|
||||
void DriverGL::set3DMode() {
|
||||
|
@ -57,8 +57,12 @@ public:
|
||||
|
||||
void startActorDraw(Vector3d pos, float yaw, float pitch, float roll);
|
||||
void finishActorDraw();
|
||||
void setupShadower(Shadow *shadow);
|
||||
|
||||
void setShadow(Shadow *shadow);
|
||||
void drawShadowPlanes();
|
||||
void setShadowMode();
|
||||
void clearShadowMode();
|
||||
void setShadowColor(byte r, byte g, byte b);
|
||||
|
||||
void set3DMode();
|
||||
|
||||
void translateViewpoint(Vector3d pos, float pitch, float yaw, float roll);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "common/sys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/vector3d.h"
|
||||
|
||||
#include "engine/colormap.h"
|
||||
#include "engine/material.h"
|
||||
@ -184,10 +185,61 @@ bool DriverTinyGL::isHardwareAccelerated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void tglShadowProjection(Vector3d *light, Vector3d *plane, Vector3d *normal) {
|
||||
// Based on GPL shadow projection example by
|
||||
// (c) 2002-2003 Phaetos <phaetos@gaffga.de>
|
||||
float d, c;
|
||||
float mat[16];
|
||||
float nx, ny, nz, lx, ly, lz, px, py, pz;
|
||||
|
||||
nx = normal->x();
|
||||
ny = normal->y();
|
||||
nz = -normal->z(); // for some unknown for me reason it need negate
|
||||
lx = light->x();
|
||||
ly = light->y();
|
||||
lz = light->z();
|
||||
px = plane->x();
|
||||
py = plane->y();
|
||||
pz = plane->z();
|
||||
|
||||
d = nx * lx + ny * ly + nz * lz;
|
||||
c = px * nx + py * ny + pz * nz - d;
|
||||
|
||||
mat[0] = lx * nx + c;
|
||||
mat[4] = ny * lx;
|
||||
mat[8] = nz * lx;
|
||||
mat[12] = -lx * c - lx * d;
|
||||
|
||||
mat[1] = nx * ly;
|
||||
mat[5] = ly * ny + c;
|
||||
mat[9] = nz * ly;
|
||||
mat[13] = -ly * c - ly * d;
|
||||
|
||||
mat[2] = nx * lz;
|
||||
mat[6] = ny * lz;
|
||||
mat[10] = lz * nz + c;
|
||||
mat[14] = -lz * c - lz * d;
|
||||
|
||||
mat[3] = nx;
|
||||
mat[7] = ny;
|
||||
mat[11] = nz;
|
||||
mat[15] = -d;
|
||||
|
||||
tglMultMatrixf(mat);
|
||||
}
|
||||
|
||||
void DriverTinyGL::startActorDraw(Vector3d pos, float yaw, float pitch, float roll) {
|
||||
tglEnable(TGL_TEXTURE_2D);
|
||||
tglMatrixMode(TGL_MODELVIEW);
|
||||
tglPushMatrix();
|
||||
if (_currentShadowArray) {
|
||||
assert(_currentShadowArray->shadowMask);
|
||||
tglSetShadowColor(_shadowColorR, _shadowColorG, _shadowColorB);
|
||||
tglSetShadowMaskBuf(_currentShadowArray->shadowMask);
|
||||
SectorListType::iterator i = _currentShadowArray->planeList.begin();
|
||||
Sector *shadowSector = *i;
|
||||
tglShadowProjection(&_currentShadowArray->pos, &shadowSector->getVertices()[1], &shadowSector->getNormal());
|
||||
}
|
||||
tglTranslatef(pos.x(), pos.y(), pos.z());
|
||||
tglRotatef(yaw, 0, 0, 1);
|
||||
tglRotatef(pitch, 1, 0, 0);
|
||||
@ -199,24 +251,38 @@ void DriverTinyGL::finishActorDraw() {
|
||||
tglPopMatrix();
|
||||
tglDisable(TGL_TEXTURE_2D);
|
||||
|
||||
/* // enable to draw shadow planes (Special Sectors)
|
||||
int k, r;
|
||||
if (!_currentShadowArray)
|
||||
return;
|
||||
if (_currentShadowArray) {
|
||||
tglSetShadowMaskBuf(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
tglColor3f(0.8,0.8,0.8);
|
||||
for (r = 0; r < 5; r++) {
|
||||
_currentShadowArray[r].planeList.begin();
|
||||
for (SectorListType::iterator i = _currentShadowArray[r].planeList.begin(); i != _currentShadowArray[r].planeList.end(); i++) {
|
||||
Sector *shadowSector = *i;
|
||||
tglBegin(TGL_POLYGON);
|
||||
tglNormal3f(shadowSector->getNormal().x(), shadowSector->getNormal().y(), shadowSector->getNormal().z());
|
||||
for (k = 0; k < shadowSector->getNumVertices(); k++) {
|
||||
tglVertex3f(shadowSector->getVertices()[k].x(), shadowSector->getVertices()[k].y(), shadowSector->getVertices()[k].z());
|
||||
}
|
||||
tglEnd();
|
||||
void DriverTinyGL::drawShadowPlanes() {
|
||||
tglEnable(TGL_SHADOW_MASK_MODE);
|
||||
if (_currentShadowArray->shadowMask)
|
||||
memset(_currentShadowArray->shadowMask, 0, _screenWidth * _screenHeight);
|
||||
else
|
||||
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
|
||||
|
||||
tglSetShadowMaskBuf(_currentShadowArray->shadowMask);
|
||||
_currentShadowArray->planeList.begin();
|
||||
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); i++) {
|
||||
Sector *shadowSector = *i;
|
||||
tglBegin(TGL_POLYGON);
|
||||
for (int k = 0; k < shadowSector->getNumVertices(); k++) {
|
||||
tglVertex3f(shadowSector->getVertices()[k].x(), shadowSector->getVertices()[k].y(), shadowSector->getVertices()[k].z());
|
||||
}
|
||||
}*/
|
||||
tglEnd();
|
||||
}
|
||||
tglSetShadowMaskBuf(NULL);
|
||||
tglDisable(TGL_SHADOW_MASK_MODE);
|
||||
}
|
||||
|
||||
void DriverTinyGL::setShadowMode() {
|
||||
tglEnable(TGL_SHADOW_MODE);
|
||||
}
|
||||
|
||||
void DriverTinyGL::clearShadowMode() {
|
||||
tglDisable(TGL_SHADOW_MODE);
|
||||
}
|
||||
|
||||
void DriverTinyGL::set3DMode() {
|
||||
@ -224,8 +290,18 @@ void DriverTinyGL::set3DMode() {
|
||||
tglEnable(TGL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void DriverTinyGL::setupShadower(Shadow *shadow) {
|
||||
void DriverTinyGL::setShadow(Shadow *shadow) {
|
||||
_currentShadowArray = shadow;
|
||||
if (shadow)
|
||||
tglDisable(TGL_LIGHTING);
|
||||
else
|
||||
tglEnable(TGL_LIGHTING);
|
||||
}
|
||||
|
||||
void DriverTinyGL::setShadowColor(byte r, byte g, byte b) {
|
||||
_shadowColorR = r;
|
||||
_shadowColorG = g;
|
||||
_shadowColorB = b;
|
||||
}
|
||||
|
||||
void DriverTinyGL::drawModelFace(const Model::Face *face, float *vertices, float *vertNormals, float *textureVerts) {
|
||||
|
@ -57,8 +57,12 @@ public:
|
||||
|
||||
void startActorDraw(Vector3d pos, float yaw, float pitch, float roll);
|
||||
void finishActorDraw();
|
||||
void setupShadower(Shadow *shadow);
|
||||
|
||||
void setShadow(Shadow *shadow);
|
||||
void drawShadowPlanes();
|
||||
void setShadowMode();
|
||||
void clearShadowMode();
|
||||
void setShadowColor(byte r, byte g, byte b);
|
||||
|
||||
void set3DMode();
|
||||
|
||||
void translateViewpoint(Vector3d pos, float pitch, float yaw, float roll);
|
||||
|
@ -358,6 +358,7 @@ void Engine::updateDisplayScene() {
|
||||
a->draw();
|
||||
a->undraw(a->inSet(_currScene->name()) && a->visible());
|
||||
}
|
||||
flagRefreshShadowMask(false);
|
||||
|
||||
// Draw overlying scene components
|
||||
// The overlay objects should be drawn on top of everything else,
|
||||
@ -413,6 +414,7 @@ void Engine::mainLoop() {
|
||||
_savegameLoadRequest = false;
|
||||
_savegameSaveRequest = false;
|
||||
_savegameFileName = NULL;
|
||||
_refreshShadowMask = false;
|
||||
|
||||
for (;;) {
|
||||
if (_savegameLoadRequest) {
|
||||
@ -644,6 +646,7 @@ void Engine::setScene(const char *name) {
|
||||
if (b == NULL)
|
||||
warning("Could not find scene file %s\n", name);
|
||||
_currScene = new Scene(name, b->data(), b->len());
|
||||
flagRefreshShadowMask(true);
|
||||
registerScene(_currScene);
|
||||
_currScene->setSoundParameters(20, 127);
|
||||
// should delete the old scene after creating the new one
|
||||
@ -673,7 +676,3 @@ void Engine::setTextSpeed(int speed) {
|
||||
_textSpeed = 10;
|
||||
_textSpeed = speed;
|
||||
}
|
||||
|
||||
void Engine::setShadowColor(Color c) {
|
||||
_shadowColor = c;
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ public:
|
||||
bool getFlipEnable() { return _flipEnable; }
|
||||
void refreshDrawMode() { _refreshDrawNeeded = true; }
|
||||
void drawPrimitives();
|
||||
void setShadowColor(Color c);
|
||||
|
||||
void mainLoop();
|
||||
unsigned frameStart() const { return _frameStart; }
|
||||
@ -106,6 +105,13 @@ public:
|
||||
_scenes.remove(a);
|
||||
}
|
||||
|
||||
void flagRefreshShadowMask(bool flag) {
|
||||
_refreshShadowMask = flag;
|
||||
}
|
||||
bool getFlagRefreshShadowMask() {
|
||||
return _refreshShadowMask;
|
||||
}
|
||||
|
||||
// Actor registration
|
||||
typedef std::list<Actor *> ActorListType;
|
||||
ActorListType::const_iterator actorsBegin() const {
|
||||
@ -187,7 +193,7 @@ private:
|
||||
bool _refreshDrawNeeded;
|
||||
char _fps[8];
|
||||
bool _doFlip;
|
||||
Color _shadowColor;
|
||||
bool _refreshShadowMask;
|
||||
|
||||
unsigned _frameStart, _frameTime, _movieTime;
|
||||
unsigned int _frameTimeCollection;
|
||||
|
@ -1431,7 +1431,7 @@ static void SetShadowColor() {
|
||||
int g = check_int(2);
|
||||
int b = check_int(3);
|
||||
|
||||
g_engine->setShadowColor(Color(r, g, b));
|
||||
g_driver->setShadowColor(r, g, b);
|
||||
}
|
||||
|
||||
static void KillActorShadows() {
|
||||
@ -1483,20 +1483,22 @@ static void AddShadowPlane() {
|
||||
static void ActivateActorShadow() {
|
||||
DEBUG_FUNCTION();
|
||||
|
||||
/*Actor *act = */check_actor(1);
|
||||
/*int shadowId = */check_int(2);
|
||||
/*bool state = */getbool(3);
|
||||
Actor *act = check_actor(1);
|
||||
int shadowId = check_int(2);
|
||||
bool state = getbool(3);
|
||||
|
||||
//act->setActivateShadow(shadowId, state);
|
||||
act->setActivateShadow(shadowId, state);
|
||||
}
|
||||
|
||||
static void SetActorShadowValid() {
|
||||
DEBUG_FUNCTION();
|
||||
|
||||
/*Actor *act = */check_actor(1);
|
||||
/*int valid = */check_int(2);
|
||||
Actor *act = check_actor(1);
|
||||
int valid = check_int(2);
|
||||
|
||||
//act->setShadowValid(valid);
|
||||
warning("SetActorShadowValid(%d) unknown purpose", valid);
|
||||
|
||||
act->setShadowValid(valid);
|
||||
}
|
||||
|
||||
// 0 - translate from '/msgId/'
|
||||
|
@ -219,6 +219,7 @@ void Scene::setSetup(int num) {
|
||||
return;
|
||||
}
|
||||
_currSetup = _setups + num;
|
||||
g_engine->flagRefreshShadowMask(true);
|
||||
}
|
||||
|
||||
void Scene::drawBitmaps(ObjectState::Position stage) {
|
||||
|
@ -10,3 +10,4 @@ The changes made from the original version of TinyGL 0.4 are:
|
||||
* Removed unneeded code.
|
||||
* Introduced second 32-bit z-buffer for 3d objects only,
|
||||
and kept 16-bit only for static z-buffer bitmaps.
|
||||
* Added support for drawing in shadow mode (generate mask and polygon shadow).
|
||||
|
@ -604,3 +604,15 @@ void tglDebug(int mode) {
|
||||
GLContext *c = gl_get_context();
|
||||
c->print_flag = mode;
|
||||
}
|
||||
|
||||
void tglSetShadowMaskBuf(unsigned char *buf) {
|
||||
GLContext *c = gl_get_context();
|
||||
c->zb->shadow_mask_buf = buf;
|
||||
}
|
||||
|
||||
void tglSetShadowColor(unsigned char r, unsigned char g, unsigned char b) {
|
||||
GLContext *c = gl_get_context();
|
||||
c->zb->shadow_color_r = r << 8;
|
||||
c->zb->shadow_color_g = g << 8;
|
||||
c->zb->shadow_color_b = b << 8;
|
||||
}
|
||||
|
@ -388,7 +388,13 @@ void gl_draw_triangle_fill(GLContext *c, GLVertex *p0, GLVertex *p1, GLVertex *p
|
||||
}
|
||||
#endif
|
||||
|
||||
if (c->texture_2d_enabled) {
|
||||
if (c->shadow_mode & 1) {
|
||||
assert(c->zb->shadow_mask_buf);
|
||||
ZB_fillTriangleFlatShadowMask(c->zb, &p0->zp, &p1->zp, &p2->zp);
|
||||
} else if (c->shadow_mode & 2) {
|
||||
assert(c->zb->shadow_mask_buf);
|
||||
ZB_fillTriangleFlatShadow(c->zb, &p0->zp, &p1->zp, &p2->zp);
|
||||
} else if (c->texture_2d_enabled) {
|
||||
#ifdef PROFILE
|
||||
count_triangles_textured++;
|
||||
#endif
|
||||
|
@ -125,6 +125,8 @@ enum {
|
||||
TGL_POLYGON_OFFSET_POINT = 0x2A01,
|
||||
TGL_POLYGON_OFFSET_LINE = 0x2A02,
|
||||
TGL_POLYGON_OFFSET_FILL = 0x8037,
|
||||
TGL_SHADOW_MASK_MODE = 0x0C40,
|
||||
TGL_SHADOW_MODE = 0x0C41,
|
||||
|
||||
// Display Lists
|
||||
TGL_COMPILE = 0x1300,
|
||||
@ -783,6 +785,9 @@ void tglGetIntegerv(int pname, int *params);
|
||||
void tglGetFloatv(int pname, float *v);
|
||||
void tglFrontFace(int mode);
|
||||
|
||||
void tglSetShadowMaskBuf(unsigned char *buf);
|
||||
void tglSetShadowColor(unsigned char r, unsigned char g, unsigned char b);
|
||||
|
||||
// opengl 1.2 arrays
|
||||
void tglEnableClientState(TGLenum array);
|
||||
void tglDisableClientState(TGLenum array);
|
||||
|
@ -164,6 +164,9 @@ void tglInit(void *zbuffer1) {
|
||||
// opengl 1.1 polygon offset
|
||||
c->offset_states = 0;
|
||||
|
||||
// shadow mode
|
||||
c->shadow_mode = 0;
|
||||
|
||||
// clear the resize callback function pointer
|
||||
c->gl_resize_viewport = NULL;
|
||||
|
||||
|
@ -82,6 +82,18 @@ void glopEnableDisable(GLContext *c, TGLParam *p) {
|
||||
else
|
||||
c->offset_states &= ~TGL_OFFSET_LINE;
|
||||
break;
|
||||
case TGL_SHADOW_MASK_MODE:
|
||||
if (v)
|
||||
c->shadow_mode |= 1;
|
||||
else
|
||||
c->shadow_mode &= ~1;
|
||||
break;
|
||||
case TGL_SHADOW_MODE:
|
||||
if (v)
|
||||
c->shadow_mode |= 2;
|
||||
else
|
||||
c->shadow_mode &= ~2;
|
||||
break;
|
||||
default:
|
||||
if (code>=TGL_LIGHT0 && code<TGL_LIGHT0+MAX_LIGHTS) {
|
||||
gl_enable_disable_light(c,code - TGL_LIGHT0, v);
|
||||
|
@ -22,7 +22,8 @@ MODULE_OBJS := \
|
||||
zbuffer.o \
|
||||
zline.o \
|
||||
zmath.o \
|
||||
ztriangle.o
|
||||
ztriangle.o \
|
||||
ztriangle_shadow.o
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
@ -14,7 +14,7 @@ ZBuffer *ZB_open(int xsize, int ysize, int mode, void *frame_buffer) {
|
||||
|
||||
zb = (ZBuffer *)gl_malloc(sizeof(ZBuffer));
|
||||
if (zb == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
zb->xsize = xsize;
|
||||
zb->ysize = ysize;
|
||||
@ -55,6 +55,7 @@ ZBuffer *ZB_open(int xsize, int ysize, int mode, void *frame_buffer) {
|
||||
}
|
||||
|
||||
zb->current_texture = NULL;
|
||||
zb->shadow_mask_buf = NULL;
|
||||
|
||||
return zb;
|
||||
error:
|
||||
@ -182,7 +183,7 @@ void ZB_clear(ZBuffer *zb, int clear_z, int z,
|
||||
memset_s(zb->zbuf, z, zb->xsize * zb->ysize);
|
||||
}
|
||||
if (clear_z) {
|
||||
memset_l(zb->zbuf, z, zb->xsize * zb->ysize);
|
||||
memset_l(zb->zbuf2, z, zb->xsize * zb->ysize);
|
||||
}
|
||||
if (clear_color) {
|
||||
pp = zb->pbuf;
|
||||
|
@ -29,12 +29,16 @@ typedef unsigned short PIXEL;
|
||||
#define PSZSH 4
|
||||
|
||||
typedef struct {
|
||||
int xsize,ysize;
|
||||
int xsize, ysize;
|
||||
int linesize; // line size, in bytes
|
||||
int mode;
|
||||
|
||||
unsigned short *zbuf;
|
||||
unsigned long *zbuf2;
|
||||
unsigned char *shadow_mask_buf;
|
||||
int shadow_color_r;
|
||||
int shadow_color_g;
|
||||
int shadow_color_b;
|
||||
PIXEL *pbuf;
|
||||
int frame_buffer_allocated;
|
||||
|
||||
@ -59,6 +63,7 @@ void ZB_resize(ZBuffer *zb, void *frame_buffer, int xsize, int ysize);
|
||||
void ZB_clear(ZBuffer *zb, int clear_z, int z, int clear_color, int r, int g, int b);
|
||||
// linesize is in BYTES
|
||||
void ZB_copyFrameBuffer(ZBuffer *zb, void *buf, int linesize);
|
||||
//void ZB_setShadowMaskBuf(
|
||||
|
||||
// zline.c
|
||||
|
||||
@ -71,6 +76,10 @@ void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2);
|
||||
void ZB_setTexture(ZBuffer *zb, PIXEL *texture);
|
||||
void ZB_fillTriangleFlat(ZBuffer *zb, ZBufferPoint *p1,
|
||||
ZBufferPoint *p2, ZBufferPoint *p3);
|
||||
void ZB_fillTriangleFlatShadowMask(ZBuffer *zb, ZBufferPoint *p1,
|
||||
ZBufferPoint *p2, ZBufferPoint *p3);
|
||||
void ZB_fillTriangleFlatShadow(ZBuffer *zb, ZBufferPoint *p1,
|
||||
ZBufferPoint *p2, ZBufferPoint *p3);
|
||||
void ZB_fillTriangleSmooth(ZBuffer *zb, ZBufferPoint *p1,
|
||||
ZBufferPoint *p2, ZBufferPoint *p3);
|
||||
void ZB_fillTriangleMapping(ZBuffer *zb, ZBufferPoint *p1,
|
||||
|
@ -260,7 +260,9 @@ typedef struct GLContext {
|
||||
float offset_factor;
|
||||
float offset_units;
|
||||
int offset_states;
|
||||
|
||||
|
||||
int shadow_mode;
|
||||
|
||||
/* specular buffer. could probably be shared between contexts,
|
||||
but that wouldn't be 100% thread safe */
|
||||
GLSpecBuf *specbuf_first;
|
||||
|
@ -14,7 +14,7 @@ void ZB_fillTriangleFlat(ZBuffer *zb, ZBufferPoint *p0,
|
||||
#define DRAW_INIT() { \
|
||||
color = RGB_TO_PIXEL(p2->r, p2->g, p2->b); \
|
||||
}
|
||||
|
||||
|
||||
#define PUT_PIXEL(_a) { \
|
||||
zz = z >> ZB_POINT_Z_FRAC_BITS; \
|
||||
if ((ZCMP(zz, pz[_a])) && (ZCMP(z, pz_2[_a]))) { \
|
||||
|
364
engine/tinygl/ztriangle_shadow.cpp
Normal file
364
engine/tinygl/ztriangle_shadow.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
|
||||
#include "engine/tinygl/zbuffer.h"
|
||||
|
||||
#define ZCMP(z, zpix) ((z) >= (zpix))
|
||||
|
||||
void ZB_fillTriangleFlatShadowMask(ZBuffer *zb, ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
|
||||
ZBufferPoint *t, *pr1, *pr2, *l1, *l2;
|
||||
float fdx1, fdx2, fdy1, fdy2, fz;
|
||||
unsigned char *pm1;
|
||||
int part, update_left, update_right;
|
||||
|
||||
int nb_lines, dx1, dy1, tmp, dx2, dy2;
|
||||
|
||||
int error, derror;
|
||||
int x1, dxdy_min, dxdy_max;
|
||||
// warning: x2 is multiplied by 2^16
|
||||
int x2, dx2dy2;
|
||||
|
||||
// we sort the vertex with increasing y
|
||||
if (p1->y < p0->y) {
|
||||
t = p0;
|
||||
p0 = p1;
|
||||
p1 = t;
|
||||
}
|
||||
if (p2->y < p0->y) {
|
||||
t = p2;
|
||||
p2 = p1;
|
||||
p1 = p0;
|
||||
p0 = t;
|
||||
} else if (p2->y < p1->y) {
|
||||
t = p1;
|
||||
p1 = p2;
|
||||
p2 = t;
|
||||
}
|
||||
|
||||
// we compute dXdx and dXdy for all interpolated values
|
||||
|
||||
fdx1 = (float)(p1->x - p0->x);
|
||||
fdy1 = (float)(p1->y - p0->y);
|
||||
|
||||
fdx2 = (float)(p2->x - p0->x);
|
||||
fdy2 = (float)(p2->y - p0->y);
|
||||
|
||||
fz = fdx1 * fdy2 - fdx2 * fdy1;
|
||||
if (fz == 0)
|
||||
return;
|
||||
fz = (float)(1.0 / fz);
|
||||
|
||||
fdx1 *= fz;
|
||||
fdy1 *= fz;
|
||||
fdx2 *= fz;
|
||||
fdy2 *= fz;
|
||||
|
||||
// screen coordinates
|
||||
|
||||
pm1 = zb->shadow_mask_buf + zb->xsize * p0->y;
|
||||
|
||||
for (part = 0; part < 2; part++) {
|
||||
if (part == 0) {
|
||||
if (fz > 0) {
|
||||
update_left = 1;
|
||||
update_right = 1;
|
||||
l1 = p0;
|
||||
l2 = p2;
|
||||
pr1 = p0;
|
||||
pr2 = p1;
|
||||
} else {
|
||||
update_left = 1;
|
||||
update_right = 1;
|
||||
l1 = p0;
|
||||
l2 = p1;
|
||||
pr1 = p0;
|
||||
pr2 = p2;
|
||||
}
|
||||
nb_lines = p1->y - p0->y;
|
||||
} else {
|
||||
// second part
|
||||
if (fz > 0) {
|
||||
update_left = 0;
|
||||
update_right = 1;
|
||||
pr1 = p1;
|
||||
pr2 = p2;
|
||||
} else {
|
||||
update_left = 1;
|
||||
update_right = 0;
|
||||
l1 = p1;
|
||||
l2 = p2;
|
||||
}
|
||||
nb_lines = p2->y - p1->y + 1;
|
||||
}
|
||||
|
||||
// compute the values for the left edge
|
||||
if (update_left) {
|
||||
dy1 = l2->y - l1->y;
|
||||
dx1 = l2->x - l1->x;
|
||||
if (dy1 > 0)
|
||||
tmp = (dx1 << 16) / dy1;
|
||||
else
|
||||
tmp = 0;
|
||||
x1 = l1->x;
|
||||
error = 0;
|
||||
derror = tmp & 0x0000ffff;
|
||||
dxdy_min = tmp >> 16;
|
||||
dxdy_max = dxdy_min + 1;
|
||||
}
|
||||
|
||||
// compute values for the right edge
|
||||
|
||||
if (update_right) {
|
||||
dx2 = (pr2->x - pr1->x);
|
||||
dy2 = (pr2->y - pr1->y);
|
||||
if (dy2 > 0)
|
||||
dx2dy2 = ( dx2 << 16) / dy2;
|
||||
else
|
||||
dx2dy2 = 0;
|
||||
x2 = pr1->x << 16;
|
||||
}
|
||||
|
||||
// we draw all the scan line of the part
|
||||
while (nb_lines > 0) {
|
||||
nb_lines--;
|
||||
// generic draw line
|
||||
{
|
||||
register unsigned char *pm;
|
||||
register int n;
|
||||
|
||||
n = (x2 >> 16) - x1;
|
||||
pm = pm1 + x1;
|
||||
while (n >= 3) {
|
||||
for (int a = 0; a <= 3; a++) {
|
||||
pm[a] = 0xff;
|
||||
}
|
||||
pm += 4;
|
||||
n -= 4;
|
||||
}
|
||||
while (n >= 0) {
|
||||
pm[0] = 0xff;
|
||||
pm += 1;
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// left edge
|
||||
error += derror;
|
||||
if (error > 0) {
|
||||
error -= 0x10000;
|
||||
x1 += dxdy_max;
|
||||
} else {
|
||||
x1 += dxdy_min;
|
||||
}
|
||||
|
||||
// right edge
|
||||
x2 += dx2dy2;
|
||||
|
||||
// screen coordinates
|
||||
pm1 = pm1 + zb->xsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZB_fillTriangleFlatShadow(ZBuffer *zb, ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
|
||||
int color;
|
||||
ZBufferPoint *t, *pr1, *pr2, *l1, *l2;
|
||||
float fdx1, fdx2, fdy1, fdy2, fz, d1, d2;
|
||||
unsigned char *pm1;
|
||||
unsigned short *pz1;
|
||||
unsigned long *pz2;
|
||||
PIXEL *pp1;
|
||||
int part, update_left, update_right;
|
||||
|
||||
int nb_lines, dx1, dy1, tmp, dx2, dy2;
|
||||
|
||||
int error, derror;
|
||||
int x1, dxdy_min, dxdy_max;
|
||||
// warning: x2 is multiplied by 2^16
|
||||
int x2, dx2dy2;
|
||||
|
||||
int z1, dzdx, dzdy, dzdl_min, dzdl_max;
|
||||
|
||||
// we sort the vertex with increasing y
|
||||
if (p1->y < p0->y) {
|
||||
t = p0;
|
||||
p0 = p1;
|
||||
p1 = t;
|
||||
}
|
||||
if (p2->y < p0->y) {
|
||||
t = p2;
|
||||
p2 = p1;
|
||||
p1 = p0;
|
||||
p0 = t;
|
||||
} else if (p2->y < p1->y) {
|
||||
t = p1;
|
||||
p1 = p2;
|
||||
p2 = t;
|
||||
}
|
||||
|
||||
// we compute dXdx and dXdy for all interpolated values
|
||||
|
||||
fdx1 = (float)(p1->x - p0->x);
|
||||
fdy1 = (float)(p1->y - p0->y);
|
||||
|
||||
fdx2 = (float)(p2->x - p0->x);
|
||||
fdy2 = (float)(p2->y - p0->y);
|
||||
|
||||
fz = fdx1 * fdy2 - fdx2 * fdy1;
|
||||
if (fz == 0)
|
||||
return;
|
||||
fz = (float)(1.0 / fz);
|
||||
|
||||
fdx1 *= fz;
|
||||
fdy1 *= fz;
|
||||
fdx2 *= fz;
|
||||
fdy2 *= fz;
|
||||
|
||||
d1 = (float)(p1->z - p0->z);
|
||||
d2 = (float)(p2->z - p0->z);
|
||||
dzdx = (int)(fdy2 * d1 - fdy1 * d2);
|
||||
dzdy = (int)(fdx1 * d2 - fdx2 * d1);
|
||||
|
||||
// screen coordinates
|
||||
|
||||
pp1 = (PIXEL *)((char *)zb->pbuf + zb->linesize * p0->y);
|
||||
pm1 = zb->shadow_mask_buf + p0->y * zb->xsize;
|
||||
pz1 = zb->zbuf + p0->y * zb->xsize;
|
||||
pz2 = zb->zbuf2 + p0->y * zb->xsize;
|
||||
|
||||
color = RGB_TO_PIXEL(zb->shadow_color_r, zb->shadow_color_g, zb->shadow_color_b);
|
||||
|
||||
for (part = 0; part < 2; part++) {
|
||||
if (part == 0) {
|
||||
if (fz > 0) {
|
||||
update_left = 1;
|
||||
update_right = 1;
|
||||
l1 = p0;
|
||||
l2 = p2;
|
||||
pr1 = p0;
|
||||
pr2 = p1;
|
||||
} else {
|
||||
update_left = 1;
|
||||
update_right = 1;
|
||||
l1 = p0;
|
||||
l2 = p1;
|
||||
pr1 = p0;
|
||||
pr2 = p2;
|
||||
}
|
||||
nb_lines = p1->y - p0->y;
|
||||
} else {
|
||||
// second part
|
||||
if (fz > 0) {
|
||||
update_left = 0;
|
||||
update_right = 1;
|
||||
pr1 = p1;
|
||||
pr2 = p2;
|
||||
} else {
|
||||
update_left = 1;
|
||||
update_right = 0;
|
||||
l1 = p1;
|
||||
l2 = p2;
|
||||
}
|
||||
nb_lines = p2->y - p1->y + 1;
|
||||
}
|
||||
|
||||
// compute the values for the left edge
|
||||
|
||||
if (update_left) {
|
||||
dy1 = l2->y - l1->y;
|
||||
dx1 = l2->x - l1->x;
|
||||
if (dy1 > 0)
|
||||
tmp = (dx1 << 16) / dy1;
|
||||
else
|
||||
tmp = 0;
|
||||
x1 = l1->x;
|
||||
error = 0;
|
||||
derror = tmp & 0x0000ffff;
|
||||
dxdy_min = tmp >> 16;
|
||||
dxdy_max = dxdy_min + 1;
|
||||
|
||||
z1 = l1->z;
|
||||
dzdl_min = (dzdy + dzdx * dxdy_min);
|
||||
dzdl_max = dzdl_min + dzdx;
|
||||
}
|
||||
|
||||
// compute values for the right edge
|
||||
|
||||
if (update_right) {
|
||||
dx2 = (pr2->x - pr1->x);
|
||||
dy2 = (pr2->y - pr1->y);
|
||||
if (dy2>0)
|
||||
dx2dy2 = ( dx2 << 16) / dy2;
|
||||
else
|
||||
dx2dy2 = 0;
|
||||
x2 = pr1->x << 16;
|
||||
}
|
||||
|
||||
// we draw all the scan line of the part
|
||||
|
||||
while (nb_lines > 0) {
|
||||
nb_lines--;
|
||||
// generic draw line
|
||||
{
|
||||
register PIXEL *pp;
|
||||
register unsigned char *pm;
|
||||
register int n;
|
||||
register unsigned short *pz;
|
||||
register unsigned long *pz_2;
|
||||
register unsigned int z, zz;
|
||||
|
||||
n = (x2 >> 16) - x1;
|
||||
pp = (PIXEL *)((char *)pp1 + x1 * PSZB);
|
||||
pm = pm1 + x1;
|
||||
pz = pz1 + x1;
|
||||
pz_2 = pz2 + x1;
|
||||
z = z1;
|
||||
while (n >= 3) {
|
||||
for (int a = 0; a < 4; a++) {
|
||||
zz = z >> ZB_POINT_Z_FRAC_BITS;
|
||||
if ((ZCMP(zz, pz[a])) && (ZCMP(z, pz_2[a])) && pm[0]) {
|
||||
pp[a] = color;
|
||||
pz_2[a] = z;
|
||||
}
|
||||
z += dzdx;
|
||||
}
|
||||
pz += 4;
|
||||
pz_2 += 4;
|
||||
pm += 4;
|
||||
pp = (PIXEL *)((char *)pp + 4 * PSZB);
|
||||
n -= 4;
|
||||
}
|
||||
while (n >= 0) {
|
||||
zz = z >> ZB_POINT_Z_FRAC_BITS;
|
||||
if ((ZCMP(zz, pz[0])) && (ZCMP(z, pz_2[0])) && pm[0]) {
|
||||
pp[0] = color;
|
||||
pz_2[0] = z;
|
||||
}
|
||||
pz += 1;
|
||||
pz_2 += 1;
|
||||
pm += 1;
|
||||
pp = (PIXEL *)((char *)pp + PSZB);
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// left edge
|
||||
error += derror;
|
||||
if (error > 0) {
|
||||
error -= 0x10000;
|
||||
x1 += dxdy_max;
|
||||
z1 += dzdl_max;
|
||||
} else {
|
||||
x1 += dxdy_min;
|
||||
z1 += dzdl_min;
|
||||
}
|
||||
|
||||
// right edge
|
||||
x2 += dx2dy2;
|
||||
|
||||
// screen coordinates
|
||||
pp1 = (PIXEL *)((char *)pp1 + zb->linesize);
|
||||
pz1 += zb->xsize;
|
||||
pz2 += zb->xsize;
|
||||
pm1 += zb->xsize;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user