Initial commit
This commit is contained in:
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
36
engines/watchmaker/3d/render/opengl.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl.h"
|
||||
#include "watchmaker/utils.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
//*********************************************************************************************
|
||||
bool rGetStencilBitDepth() {
|
||||
#if 0
|
||||
return gStencilBitDepth;
|
||||
#endif
|
||||
//warning("TODO: Implement rGetStencilBitDepth");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
29
engines/watchmaker/3d/render/opengl.h
Normal file
29
engines/watchmaker/3d/render/opengl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_H
|
||||
#define WATCHMAKER_OPENGL_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_H
|
||||
369
engines/watchmaker/3d/render/opengl_2d.cpp
Normal file
369
engines/watchmaker/3d/render/opengl_2d.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/game.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME)
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/game.h"
|
||||
#include "watchmaker/rect.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/sdl_wrapper.h"
|
||||
#include "watchmaker/tga_util.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
Common::Rect gBlitterExtends;
|
||||
int gStencilBitDepth;
|
||||
|
||||
unsigned int CurLoaderFlags;
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int Renderer::BitmapList::acquirePosition() {
|
||||
unsigned int pos = 1;
|
||||
|
||||
while (!bitmaps[pos].isEmpty()) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos > MAX_BITMAP_LIST)
|
||||
return 0;
|
||||
|
||||
if (pos > _numBitmaps)
|
||||
_numBitmaps = pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapDimX(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].DimX;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapDimY(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].DimY;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapRealDimX(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].RealDimX;
|
||||
}
|
||||
|
||||
unsigned int Renderer::getBitmapRealDimY(int32 id) const {
|
||||
return _bitmapList.bitmaps[id].RealDimY;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rUpdateExtends(int x1, int y1, int x2, int y2) {
|
||||
//Update extends
|
||||
if (x1 < gBlitterExtends.left)
|
||||
gBlitterExtends.left = x1;
|
||||
if (y1 < gBlitterExtends.top)
|
||||
gBlitterExtends.top = y1;
|
||||
if (x2 > gBlitterExtends.right)
|
||||
gBlitterExtends.right = x2;
|
||||
if (y2 > gBlitterExtends.bottom)
|
||||
gBlitterExtends.bottom = y2;
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rGetExtends(int *x1, int *y1, int *x2, int *y2) {
|
||||
*x1 = gBlitterExtends.left;
|
||||
*y1 = gBlitterExtends.top;
|
||||
*x2 = gBlitterExtends.right;
|
||||
*y2 = gBlitterExtends.bottom;
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rResetExtends() {
|
||||
gBlitterExtends.left = SHRT_MAX;
|
||||
gBlitterExtends.top = SHRT_MAX;
|
||||
gBlitterExtends.right = SHRT_MIN;
|
||||
gBlitterExtends.bottom = SHRT_MIN;
|
||||
}
|
||||
|
||||
// TODO: Move this to Renderer
|
||||
extern Common::Rect gBlitterViewport;
|
||||
bool gClipToBlitterViewport(int *sposx, int *sposy, int *sdimx, int *sdimy,
|
||||
int *dposx, int *dposy) {
|
||||
int dwWidth, dwHeight;
|
||||
|
||||
dwWidth = (gBlitterViewport.right - gBlitterViewport.left);
|
||||
dwHeight = (gBlitterViewport.bottom - gBlitterViewport.top);
|
||||
|
||||
if (((*dposx) + (*sdimx)) > dwWidth) {
|
||||
(*sdimx) = (*sdimx) - ((*dposx) + (*sdimx) - dwWidth);
|
||||
}
|
||||
if (((*dposy) + (*sdimy)) > dwHeight) {
|
||||
(*sdimy) = (*sdimy) - ((*dposy) + (*sdimy) - dwHeight);
|
||||
}
|
||||
|
||||
if ((*dposx) < gBlitterViewport.left) {
|
||||
(*sposx) += gBlitterViewport.left - (*dposx);
|
||||
(*sdimx) -= gBlitterViewport.left - (*dposx);
|
||||
(*dposx) = gBlitterViewport.left;
|
||||
}
|
||||
if ((*dposy) < gBlitterViewport.top) {
|
||||
(*sposy) += gBlitterViewport.top - (*dposy);
|
||||
(*sdimy) -= gBlitterViewport.top - (*dposy);
|
||||
(*dposy) = gBlitterViewport.top;
|
||||
}
|
||||
|
||||
if (((*sdimx) <= 0) || ((*sdimy) <= 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void renderTexture(WGame &game, gTexture &bitmap, Common::Rect srcRect, Common::Rect dstRect) {
|
||||
checkGlError("Entering renderTexture");
|
||||
glClearColor(0, 0, 1, 0);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
bitmap._texture->bind();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, 0.0);
|
||||
|
||||
float bottomSrc = ((float)srcRect.bottom) / bitmap.RealDimY;
|
||||
float topSrc = ((float)srcRect.top) / bitmap.RealDimY;
|
||||
float leftSrc = ((float)srcRect.left) / bitmap.RealDimX;
|
||||
float rightSrc = ((float)srcRect.right) / bitmap.RealDimX;
|
||||
|
||||
Common::Rect viewport = game._renderer->_viewport;
|
||||
float bottomDst = 1.0 - ((dstRect.bottom == 0 ? 0 : ((double)dstRect.bottom) / viewport.height()) * 2.0);
|
||||
float topDst = 1.0 - ((dstRect.top == 0 ? 0 : ((double)dstRect.top) / viewport.height()) * 2.0);
|
||||
float leftDst = ((dstRect.left == 0 ? 0 : ((double)dstRect.left) / viewport.width()) * 2.0) - 1.0;
|
||||
float rightDst = ((dstRect.right == 0 ? 0 : ((double)dstRect.right) / viewport.width()) * 2.0) - 1.0;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glTexCoord2f(leftSrc, bottomSrc); // Bottom Left
|
||||
glVertex3f(leftDst, bottomDst, 0.0f);
|
||||
|
||||
glTexCoord2f(rightSrc, bottomSrc); // Bottom Right
|
||||
glVertex3f(rightDst, bottomDst, 0.0f);
|
||||
|
||||
glTexCoord2f(rightSrc, topSrc); // Top Right
|
||||
glVertex3f(rightDst, topDst, 0.0f);
|
||||
|
||||
glTexCoord2f(leftSrc, topSrc); // Top Left
|
||||
glVertex3f(leftDst, topDst, 0.0f);
|
||||
|
||||
glEnd();
|
||||
glFlush();
|
||||
checkGlError("Exiting renderTexture");
|
||||
}
|
||||
|
||||
void gTexture::render(WGame &game, Common::Rect src, Common::Rect dst) {
|
||||
// Render self
|
||||
if (_texture) {
|
||||
renderTexture(game, *this, src, dst);
|
||||
}
|
||||
for (uint i = 0; i < _blitsOnTop.size(); i++) {
|
||||
_blitsOnTop[i].texture->render(game, _blitsOnTop[i].src, _blitsOnTop[i].dst);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::blitScreenBuffer() {
|
||||
checkGlError("Entering rBlitScreenBuffer");
|
||||
g_renderer->enter2Dmode();
|
||||
_bitmapList.bitmaps[BACK_BUFFER].render(*_game, _game->_renderer->_viewport, _game->_renderer->_viewport);
|
||||
g_renderer->exit2Dmode();
|
||||
checkGlError("Exiting rBlitScreenBuffer");
|
||||
}
|
||||
|
||||
void Renderer::clearBitmap(int dst, int dposx, int dposy, int sdimx, int sdimy, unsigned char r, unsigned char g, unsigned char b) {
|
||||
warning("STUBBED: rClear(%d, %d, %d, %d, %d", dst, dposx, dposy, sdimx, sdimy);
|
||||
_bitmapList.bitmaps[dst].clear();
|
||||
}
|
||||
|
||||
//************************************************************************************************************************
|
||||
void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
|
||||
int sposx, int sposy, int sdimx, int sdimy) {
|
||||
auto &bitmapList = game._renderer->_bitmapList.bitmaps;
|
||||
// TODO: This currently gets called a bit too much.
|
||||
warning("TODO: Stubbed rBlitter(%s, %d, %d, %d, %d, %d, %d, %d, %d)", bitmapList[src].name.c_str(), dst, src, dposx, dposy, sposx, sposy, sdimx, sdimy);
|
||||
|
||||
auto &bitmap = bitmapList[src];
|
||||
|
||||
assert(dst == 0);
|
||||
auto &dstBitmap = bitmapList[dst];
|
||||
|
||||
checkGlError("rBlitter Start");
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
int dwWidth, dwHeight;
|
||||
|
||||
dwWidth = game._renderer->_viewport.width();
|
||||
dwHeight = game._renderer->_viewport.height();
|
||||
|
||||
if ((sdimx <= 0)) {
|
||||
sdimx = bitmapList[src].DimX;
|
||||
}
|
||||
if ((sdimy <= 0)) {
|
||||
sdimy = bitmapList[src].DimY;
|
||||
}
|
||||
|
||||
if ((dposx >= dwWidth) || (dposy >= dwHeight) || (sposx >= dwWidth) || (sposy >= dwHeight) ||
|
||||
((dposx + sdimx) <= 0) || ((dposy + sdimy) <= 0) || ((sposx + sdimx) <= 0) || ((sposy + sdimy) <= 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst == 0) {
|
||||
if (!gClipToBlitterViewport(&sposx, &sposy, &sdimx, &sdimy, &dposx, &dposy)) {
|
||||
error("gClipToBlitterViewport report an error");
|
||||
return;
|
||||
}
|
||||
|
||||
rUpdateExtends(dposx, dposy, dposx + sdimx, dposy + sdimy);
|
||||
}
|
||||
|
||||
if ((sdimx == 0) && (sdimy == 0)) {
|
||||
sdimx = bitmapList[src].DimX;
|
||||
sdimy = bitmapList[src].DimY;
|
||||
}
|
||||
|
||||
{
|
||||
Common::Rect srcRect;
|
||||
// Source rect
|
||||
srcRect.top = sposy;
|
||||
srcRect.left = sposx;
|
||||
srcRect.right = sposx + sdimx;
|
||||
srcRect.bottom = sposy + sdimy;
|
||||
|
||||
Common::Rect dstRect;
|
||||
// Destination rect
|
||||
// Convention in dpos is that 0,0 is upper left hand corner, increasing down the y-axis.
|
||||
dstRect.top = dposy;
|
||||
dstRect.left = dposx;
|
||||
dstRect.right = dposx + sdimx;
|
||||
dstRect.bottom = dposy + sdimy;
|
||||
if (((dstRect.bottom - dstRect.top) <= 0) || ((dstRect.right - dstRect.left) <= 0) || ((srcRect.bottom - srcRect.top) <= 0) || ((srcRect.right - srcRect.left) <= 0) ||
|
||||
(dstRect.right <= 0) || (srcRect.right <= 0) || (dstRect.bottom < 0) || (srcRect.bottom < 0)) {
|
||||
// DebugLogWindow("gBlitter: blit not needed: dimx:%d dimy:%d", ( sr.top-sr.bottom ),( sr.left-sr.right ));
|
||||
return;
|
||||
}
|
||||
dstBitmap.blitInto(&bitmap, srcRect, dstRect);
|
||||
}
|
||||
checkGlError("rBlitter End");
|
||||
|
||||
// DebugLogFile("gBlitter(%d %d)",dst,src);
|
||||
//gBlitter(d, s, sposx, sposy, sdimx, sdimy, dposx, dposy, 0);
|
||||
//#endif
|
||||
}
|
||||
|
||||
// Straight from Wintermute:
|
||||
void applyColorKey(Graphics::Surface &surf, byte ckRed, byte ckGreen, byte ckBlue, bool replaceAlpha) {
|
||||
// this is taken from Graphics::TransparentSurface
|
||||
// only difference is that we set the pixel
|
||||
// color to transparent black, like D3DX,
|
||||
// if it matches the color key
|
||||
for (int y = 0; y < surf.h; y++) {
|
||||
for (int x = 0; x < surf.w; x++) {
|
||||
uint32 pix = ((uint32 *)surf.getPixels())[y * surf.w + x];
|
||||
uint8 r, g, b, a;
|
||||
surf.format.colorToARGB(pix, a, r, g, b);
|
||||
if (r == ckRed && g == ckGreen && b == ckBlue) {
|
||||
a = 0;
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
|
||||
} else if (replaceAlpha) {
|
||||
a = 255;
|
||||
((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rLoadBitmapImage(WGame &game, const char *TextName, unsigned char flags) {
|
||||
WorkDirs &workDirs = game.workDirs;
|
||||
if (flags & rTEXTURESURFACE) {
|
||||
warning("TODO: support texture surface loading");
|
||||
// return ((int) gLoadTexture(TextName, flags));
|
||||
}
|
||||
|
||||
assert(TextName);
|
||||
auto stream = workDirs.resolveFile(TextName);
|
||||
if (!stream) {
|
||||
warning("gLoadBitmapImage: Cannot find %s.", TextName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat RGBA32 = Graphics::PixelFormat::createFormatRGBA32();
|
||||
|
||||
unsigned int pos = game._renderer->_bitmapList.acquirePosition();
|
||||
if (pos == 0) {
|
||||
warning("rLoadBitmap: Can't create more bitmaps");
|
||||
return -1;
|
||||
}
|
||||
gTexture *Texture = &game._renderer->_bitmapList.bitmaps[pos];
|
||||
*Texture = gTexture();
|
||||
Texture->Flags = CurLoaderFlags;
|
||||
auto surface = ReadTgaImage(TextName, *stream, RGBA32, Texture->Flags);
|
||||
applyColorKey(*surface, 0, 0, 0, false);
|
||||
auto texData = createTextureFromSurface(*surface, GL_RGBA);
|
||||
Texture->_texture = createGLTexture();
|
||||
Texture->_texture->assignData(*texData);
|
||||
Texture->name = TextName;
|
||||
|
||||
if (flags & rSURFACESTRETCH) { // Also rSURFACEFLIP
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
warning("TODO: rSURFACESTRETCH");
|
||||
warned = true;
|
||||
}
|
||||
// HACK: Just set a dimension at all:
|
||||
Texture->DimX = surface->w;
|
||||
Texture->DimY = surface->h;
|
||||
} else {
|
||||
Texture->DimX = surface->w;
|
||||
Texture->DimY = surface->h;
|
||||
}
|
||||
|
||||
Texture->RealDimX = surface->w;
|
||||
Texture->RealDimY = surface->h;
|
||||
// TODO: Colour-keying
|
||||
return pos;
|
||||
}
|
||||
|
||||
void rSetLoaderFlags(unsigned int NewLoaderFlags) {
|
||||
CurLoaderFlags = NewLoaderFlags;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
36
engines/watchmaker/3d/render/opengl_2d.h
Normal file
36
engines/watchmaker/3d/render/opengl_2d.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL2D_H
|
||||
#define WATCHMAKER_OPENGL2D_H
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern int gStencilBitDepth;
|
||||
|
||||
extern unsigned int CurLoaderFlags;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL2D_H
|
||||
840
engines/watchmaker/3d/render/opengl_3d.cpp
Normal file
840
engines/watchmaker/3d/render/opengl_3d.cpp
Normal file
@@ -0,0 +1,840 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/renderer.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/work_dirs.h"
|
||||
|
||||
#ifdef USE_OPENGL_GAME
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/file_utils.h"
|
||||
#include "watchmaker/tga_util.h"
|
||||
|
||||
#define MAXTEXTURES 2000
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
#define T3D_FASTFILE (1<<23) // fastfile
|
||||
|
||||
// Tecture formats
|
||||
int NumAvailableFormats = 0;
|
||||
gAvailFormat AvailableFormats[50];
|
||||
gAvailFormat *gCurrentFormat;
|
||||
|
||||
// Point VB
|
||||
int g_lpD3DPointsBuffer;
|
||||
unsigned int gNumPointsBuffer;
|
||||
|
||||
// Tecture list
|
||||
gTexture gTextureList[MAXTEXTURES];
|
||||
unsigned int gNumTextureList = 0;
|
||||
|
||||
// {ines array
|
||||
uint16 gLinesArray[MAX_LINES];
|
||||
unsigned int gNumLinesArray = 0;
|
||||
|
||||
// screen traingles
|
||||
Vertex gTriangles[100];
|
||||
unsigned int gNumTrianglesArray = 0;
|
||||
|
||||
// camera info
|
||||
Matrix4x4 rWorldMatrix;
|
||||
Matrix4x4 rProjectionMatrix;
|
||||
float gNearPlane, gFarPlane;
|
||||
|
||||
// saved matrix
|
||||
Matrix4x4 rLinesViewMatrix;
|
||||
|
||||
// user matrix
|
||||
#define MAX_USER_VIEW_MATRICES 2000 // TODO: Why do we get so many of them?
|
||||
Matrix4x4 rUserViewMatrix[MAX_USER_VIEW_MATRICES];
|
||||
unsigned int rNumUserViewMatrices = 0;
|
||||
|
||||
// user vertext buffer
|
||||
void *g_lpD3DUserVertexBuffer = nullptr;
|
||||
unsigned int g_dwD3DUserVertexBufferCounter = 0;
|
||||
|
||||
//***********************************************************************************************
|
||||
uint16 *rGetLinesArrayPtr() {
|
||||
return &gLinesArray[gNumLinesArray];
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rAddLinesArray() {
|
||||
gNumLinesArray++;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void *rLockPointArray() {
|
||||
warning("TODO: Implement rLockPointArray");
|
||||
#if 0
|
||||
HRESULT hResult;
|
||||
LPVOID v;
|
||||
|
||||
if ((hResult = g_lpD3DPointsBuffer->Lock(DDLOCK_SURFACEMEMORYPTR, &v, NULL)) != D3D_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hResult, str, 1);
|
||||
DebugLogFile("rLockPointArray: Unable to lock points vertexbuffer:\r\n%s", str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gVertex *gv = (gVertex *)v;
|
||||
return &gv[rGetNumPointArray()];
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void rAddTrianglesArray(float x, float y, int r, int g, int b, int a) {
|
||||
gTriangles[gNumTrianglesArray].sx = x;
|
||||
gTriangles[gNumTrianglesArray].sy = y;
|
||||
gTriangles[gNumTrianglesArray].sz = 1.0f;
|
||||
gTriangles[gNumTrianglesArray].color = RGBA_MAKE(r, g, b, a);
|
||||
gNumTrianglesArray++;
|
||||
}
|
||||
|
||||
|
||||
//***********************************************************************************************
|
||||
void rUnlockPointArray() {
|
||||
warning("TODO: Implement rUnlockPointArray");
|
||||
#if 0
|
||||
g_lpD3DPointsBuffer->Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
unsigned int rGetNumPointArray() {
|
||||
return gNumPointsBuffer;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rAddPointArray() {
|
||||
gNumPointsBuffer++;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rSetViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
Matrix4x4 rViewMatrix;
|
||||
rViewMatrix.setIdentity();
|
||||
|
||||
rViewMatrix.setValue(1, 1, _00);
|
||||
rViewMatrix.setValue(1, 2, _01);
|
||||
rViewMatrix.setValue(1, 3, _02);
|
||||
rViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rViewMatrix.setValue(2, 1, _03);
|
||||
rViewMatrix.setValue(2, 2, _04);
|
||||
rViewMatrix.setValue(2, 3, _05);
|
||||
rViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rViewMatrix.setValue(3, 1, -_06);
|
||||
rViewMatrix.setValue(3, 2, -_07);
|
||||
rViewMatrix.setValue(3, 3, -_08);
|
||||
rViewMatrix.setValue(3, 4, _tz);
|
||||
|
||||
rViewMatrix.setValue(4, 1, 0.0f);
|
||||
rViewMatrix.setValue(4, 2, 0.0f);
|
||||
rViewMatrix.setValue(4, 3, 0.0f);
|
||||
rViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, rViewMatrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rSetViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
rSetViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, -translation.z);
|
||||
}
|
||||
|
||||
void rSaveViewMatrix() {
|
||||
g_renderer->pushModelView();
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rRestoreViewMatrix() {
|
||||
g_renderer->popModelView();
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rBuildLinesViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
rLinesViewMatrix.setIdentity();
|
||||
|
||||
rLinesViewMatrix.setValue(1, 1, _00);
|
||||
rLinesViewMatrix.setValue(1, 2, _01);
|
||||
rLinesViewMatrix.setValue(1, 3, _02);
|
||||
rLinesViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rLinesViewMatrix.setValue(2, 1, _03);
|
||||
rLinesViewMatrix.setValue(2, 2, _04);
|
||||
rLinesViewMatrix.setValue(2, 3, _05);
|
||||
rLinesViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rLinesViewMatrix.setValue(3, 1, -_06);
|
||||
rLinesViewMatrix.setValue(3, 2, -_07);
|
||||
rLinesViewMatrix.setValue(3, 3, -_08);
|
||||
rLinesViewMatrix.setValue(3, 4, -_tz);
|
||||
|
||||
rLinesViewMatrix.setValue(4, 1, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 2, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 3, 0.0f);
|
||||
rLinesViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int rBuildLinesViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
return rBuildLinesViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, translation.z);
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
int rAddUserViewMatrix(float _00, float _01, float _02,
|
||||
float _03, float _04, float _05,
|
||||
float _06, float _07, float _08,
|
||||
float _tx, float _ty, float _tz) {
|
||||
Matrix4x4 rTempViewMatrix;
|
||||
Matrix4x4 *um;
|
||||
unsigned int i;
|
||||
|
||||
rTempViewMatrix.setIdentity();
|
||||
|
||||
rTempViewMatrix.setValue(1, 1, _00);
|
||||
rTempViewMatrix.setValue(1, 2, _01);
|
||||
rTempViewMatrix.setValue(1, 3, _02);
|
||||
rTempViewMatrix.setValue(1, 4, _tx);
|
||||
|
||||
rTempViewMatrix.setValue(2, 1, _03);
|
||||
rTempViewMatrix.setValue(2, 2, _04);
|
||||
rTempViewMatrix.setValue(2, 3, _05);
|
||||
rTempViewMatrix.setValue(2, 4, _ty);
|
||||
|
||||
rTempViewMatrix.setValue(3, 1, -_06);
|
||||
rTempViewMatrix.setValue(3, 2, -_07);
|
||||
rTempViewMatrix.setValue(3, 3, -_08);
|
||||
rTempViewMatrix.setValue(3, 4, -_tz);
|
||||
|
||||
rTempViewMatrix.setValue(4, 1, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 2, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 3, 0.0f);
|
||||
rTempViewMatrix.setValue(4, 4, 1.0f);
|
||||
|
||||
auto &tmp = rTempViewMatrix;
|
||||
//warning("Adding: ");
|
||||
//tmp.print();
|
||||
for (i = 0, um = &rUserViewMatrix[0]; i < rNumUserViewMatrices; i++, um++) {
|
||||
//warning("Comparing %d", i);
|
||||
//um->print();
|
||||
if (*um == tmp) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= MAX_USER_VIEW_MATRICES) {
|
||||
DebugLogFile("Too many UserViewMatrix %d (MAX is %d)\n", i, MAX_USER_VIEW_MATRICES);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*um = tmp;
|
||||
|
||||
rNumUserViewMatrices ++;
|
||||
return rNumUserViewMatrices - 1;
|
||||
}
|
||||
|
||||
int rAddUserViewMatrix(const t3dM3X3F &viewMatrix, const t3dV3F &translation) {
|
||||
return rAddUserViewMatrix(viewMatrix.M[0], viewMatrix.M[1], viewMatrix.M[2],
|
||||
viewMatrix.M[3], viewMatrix.M[4], viewMatrix.M[5],
|
||||
viewMatrix.M[6], viewMatrix.M[7], viewMatrix.M[8],
|
||||
translation.x, translation.y, translation.z);
|
||||
}
|
||||
|
||||
void rResetPipeline() {
|
||||
gNumLinesArray = 0;
|
||||
gNumPointsBuffer = 0;
|
||||
gNumShadowBoxesList = 0;
|
||||
rNumUserViewMatrices = 0;
|
||||
g_dwD3DUserVertexBufferCounter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void *rGetUserVertexBuffer() {
|
||||
return g_lpD3DUserVertexBuffer;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int rGetUserVertexBufferCounter() {
|
||||
return g_dwD3DUserVertexBufferCounter;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void rSetUserVertexBufferCounter(unsigned int uvbc) {
|
||||
g_dwD3DUserVertexBufferCounter = uvbc;
|
||||
}
|
||||
|
||||
gVertex *rLockVertexPtr(void *vb, int flags) {
|
||||
warning("TODO: Implement rLockVertexPtr");
|
||||
#if 0
|
||||
LPVOID v;
|
||||
DWORD dim, lock_flags;
|
||||
HRESULT hResult;
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuffer1 = (LPDIRECT3DVERTEXBUFFER7)vb;
|
||||
|
||||
lock_flags = DDLOCK_SURFACEMEMORYPTR;
|
||||
if (flags & rVBLOCK_READONLY)
|
||||
lock_flags |= DDLOCK_READONLY;
|
||||
else if (flags & rVBLOCK_WRITEONLY)
|
||||
lock_flags |= DDLOCK_WRITEONLY;
|
||||
if (flags & rVBLOCK_NOSYSLOCK)
|
||||
lock_flags |= DDLOCK_NOSYSLOCK;
|
||||
|
||||
if ((hResult = lpD3DVertexBuffer1->Lock(lock_flags, &v, &dim)) != D3D_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hResult, str, 1);
|
||||
DebugLogFile("Unable to lock vertexbuffer:\r\n%s", str);
|
||||
return NULL;
|
||||
}
|
||||
return (gVertex *)v;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Graphics::Surface *gCreateSurface(int width, int height, void *ptr) {
|
||||
auto surface = new Graphics::Surface();
|
||||
surface->w = width;
|
||||
surface->h = height;
|
||||
surface->pitch = width * 4; // TODO
|
||||
surface->setPixels(ptr);
|
||||
return surface;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool rUnlockVertexPtr(void *vb) {
|
||||
warning("Implement rUnlockVertexPtr");
|
||||
#if 0
|
||||
LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuffer1 = (LPDIRECT3DVERTEXBUFFER7)vb;
|
||||
|
||||
if (lpD3DVertexBuffer1->Unlock() != D3D_OK) {
|
||||
DebugLogFile("VertexBuffer Unlock error");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//***********************************************************************************************
|
||||
void rSetLinesViewMatrix() {
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, rLinesViewMatrix);
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
void rSetUserViewMatrix(int num) {
|
||||
auto &matrix = rUserViewMatrix[num];
|
||||
|
||||
g_renderer->setTransformMatrix(TransformMatrix::VIEW, matrix);
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************************************************
|
||||
unsigned int gGetTextureListPosition() {
|
||||
unsigned int pos = 1;
|
||||
|
||||
while (!gTextureList[pos].isEmpty()) { // TODO: Do we need the surface?
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos > MAXTEXTURES)
|
||||
return 0;
|
||||
|
||||
if (pos > gNumTextureList)
|
||||
gNumTextureList = pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void gBuildAlternateName(char *AltName, const char *Name) {
|
||||
int len, i, j;
|
||||
|
||||
if (!Name || !AltName) return;
|
||||
|
||||
len = strlen(Name);
|
||||
memset(AltName, 0, len + 4);
|
||||
memcpy(AltName, Name, len);
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if ((AltName[i] == '.') && (i < (len - 3))) {
|
||||
AltName[i + 1] = 'd';
|
||||
AltName[i + 2] = 'd';
|
||||
AltName[i + 3] = 's';
|
||||
}
|
||||
if (AltName[i] == '\\' || AltName[i] == '/') {
|
||||
for (j = len; j >= i; j--)
|
||||
AltName[j + 3] = AltName[j];
|
||||
|
||||
AltName[i + 0] = 'D';
|
||||
AltName[i + 1] = 'D';
|
||||
AltName[i + 2] = 'S';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//warning("Build alternate name %s -> %s", Name, AltName);
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void gBuildAlternateName(char *AltName, char *Name) {
|
||||
int len, i, j;
|
||||
|
||||
if (!Name || !AltName) return;
|
||||
|
||||
len = strlen(Name);
|
||||
memset(AltName, 0, len + 4);
|
||||
memcpy(AltName, Name, len);
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if ((AltName[i] == '.') && (i < (len - 3))) {
|
||||
AltName[i + 1] = 'd';
|
||||
AltName[i + 2] = 'd';
|
||||
AltName[i + 3] = 's';
|
||||
}
|
||||
if (AltName[i] == '\\') {
|
||||
for (j = len; j >= i; j--)
|
||||
AltName[j + 3] = AltName[j];
|
||||
|
||||
AltName[i + 0] = 'D';
|
||||
AltName[i + 1] = 'D';
|
||||
AltName[i + 2] = 'S';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
gTexture *gUserTexture(Texture *texture, unsigned int dimx, unsigned int dimy) {
|
||||
gTexture *Texture;
|
||||
int pos;
|
||||
//DDSURFACEDESC2 DDSurfDesc;
|
||||
|
||||
pos = gGetTextureListPosition();
|
||||
if (pos == 0) {
|
||||
DebugLogFile("gUserTexture: Can't create more textures");
|
||||
return nullptr;
|
||||
}
|
||||
Texture = &gTextureList[pos];
|
||||
*Texture = gTexture();
|
||||
Texture->Flags = CurLoaderFlags;
|
||||
|
||||
{
|
||||
#if 0
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
if (gRenderFlags & gAGPSUPPORTED) {
|
||||
//Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
} else {
|
||||
//No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
#endif
|
||||
if (dimx > 8) {
|
||||
if (dimx > 16) {
|
||||
if (dimx > 32) {
|
||||
if (dimx > 64) {
|
||||
if (dimx > 128) {
|
||||
dimx = 256;
|
||||
} else {
|
||||
dimx = 128;
|
||||
}
|
||||
} else {
|
||||
dimx = 64;
|
||||
}
|
||||
} else {
|
||||
dimx = 32;
|
||||
}
|
||||
} else {
|
||||
dimx = 16;
|
||||
}
|
||||
}
|
||||
if (dimy > 8) {
|
||||
if (dimy > 16) {
|
||||
if (dimy > 32) {
|
||||
if (dimy > 64) {
|
||||
if (dimy > 128) {
|
||||
dimy = 256;
|
||||
} else {
|
||||
dimy = 128;
|
||||
}
|
||||
} else {
|
||||
dimy = 64;
|
||||
}
|
||||
} else {
|
||||
dimy = 32;
|
||||
}
|
||||
} else {
|
||||
dimy = 16;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
DDSurfDesc.dwWidth = dimx;
|
||||
DDSurfDesc.dwHeight = dimy;
|
||||
|
||||
if (!(Texture->lpDDSurface = gCreateSurface(&DDSurfDesc, Texture->lpDDSurface))) {
|
||||
DebugLogFile("gCreateSurface FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
strcpy(Texture->Name, "UserTexture");
|
||||
gClear(Texture->lpDDSurface, 0, 0, dimx, dimy, 0, 0, 0);
|
||||
#endif
|
||||
Texture->ID = pos;
|
||||
|
||||
Texture->DimX = dimx;
|
||||
Texture->DimY = dimy;
|
||||
#if 0
|
||||
DDCOLORKEY ddck;
|
||||
ddck.dwColorSpaceLowValue = 0;
|
||||
ddck.dwColorSpaceHighValue = 0;
|
||||
Texture->lpDDSurface->SetColorKey(DDCKEY_SRCBLT, &ddck);
|
||||
#endif
|
||||
}
|
||||
|
||||
Texture->_texture = texture;
|
||||
return Texture;
|
||||
}
|
||||
|
||||
class SurfaceBackedTextureData : public TextureData {
|
||||
bool _owned = true;
|
||||
public:
|
||||
Graphics::Surface *_surface;
|
||||
SurfaceBackedTextureData(Graphics::Surface *surface, bool owned = true) : TextureData(DxtCompression::UNCOMPRESSED), _surface(surface), _owned(owned) {}
|
||||
~SurfaceBackedTextureData() override {
|
||||
if (_owned) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
}
|
||||
}
|
||||
int getWidth() const override {
|
||||
return _surface->w;
|
||||
}
|
||||
int getHeight() const override {
|
||||
return _surface->h;
|
||||
}
|
||||
int getDataSize() const override {
|
||||
return _surface->w * _surface->h * _surface->format.bytesPerPixel;
|
||||
}
|
||||
const void *getData() const override {
|
||||
return _surface->getPixels();
|
||||
}
|
||||
};
|
||||
|
||||
Common::SharedPtr<TextureData> createTextureFromSurface(Graphics::Surface &surface, int texFormat) {
|
||||
return Common::SharedPtr<TextureData>(new SurfaceBackedTextureData(&surface, false));
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
gTexture *gLoadTexture(WorkDirs &workDirs, const char *TextName, unsigned int _LoaderFlags) {
|
||||
//bool bAlpha = FALSE
|
||||
bool bUseAlternate = FALSE;
|
||||
gTexture *texture = nullptr;
|
||||
int32 pos = 0;
|
||||
char AlternateName[500] {};
|
||||
uint32 date1 = 0, date2 = 0, time1 = 0, time2 = 0;
|
||||
//uint32 magic,retv;
|
||||
unsigned long dwWidth = 0, dwHeight = 0;
|
||||
//DDSURFACEDESC2 DDSurfDesc;
|
||||
//Graphics::Surface *lpSSource = nullptr;
|
||||
|
||||
if (!TextName) return nullptr;
|
||||
//lpSSource = nullptr;
|
||||
|
||||
//warning("gLoadTexture(%s)", TextName);
|
||||
// Check if already loaded
|
||||
for (uint32 i = 0; i < gNumTextureList; i++) {
|
||||
if (gTextureList[i].name.equalsIgnoreCase(TextName)) {
|
||||
//Texture already loaded; just assign pointers
|
||||
texture = &gTextureList[i];
|
||||
texture->ID = i;
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
/* VERSIONE ORIGINALE by FAB
|
||||
gBuildAlternateName( AlternateName, TextName );
|
||||
if( ( CurLoaderFlags & T3D_FASTFILE ) || ( !t3dGetFileDate( &date1, &time1, TextName ) ) )
|
||||
bUseAlternate = TRUE;
|
||||
if( !t3dGetFileDate( &date2, &time2, AlternateName ) )
|
||||
{
|
||||
if( bUseAlternate == TRUE )
|
||||
{
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s and alternate %s.\n", TextName, AlternateName );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if( bUseAlternate == FALSE )
|
||||
{
|
||||
if( ( date2 > date1 ) || ( ( date2 == date1 ) && ( time2 >= time1 ) ) )
|
||||
bUseAlternate = TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
gBuildAlternateName(AlternateName, TextName);
|
||||
|
||||
if (!t3dGetFileDate(&date1, &time1, TextName)) // if it doesn't find the .tga texture, try the dds
|
||||
bUseAlternate = TRUE;
|
||||
|
||||
if (!t3dGetFileDate(&date2, &time2, AlternateName)) { //se non trova la texture .dds
|
||||
if (bUseAlternate == TRUE) { // does not find the .dds texture and furthermore the .tga does not exist
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s and alternate %s.\n", TextName, AlternateName);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (bUseAlternate == FALSE) { // if there is the .dds and there is also the .tga see which is newer
|
||||
if ((date2 > date1) || ((date2 == date1) && (time2 >= time1)))
|
||||
bUseAlternate = TRUE;
|
||||
}
|
||||
|
||||
|
||||
if ((pos = gGetTextureListPosition()) == 0) {
|
||||
DebugLogFile("gLoadTexture: Can't create more textures");
|
||||
return nullptr;
|
||||
}
|
||||
texture = &gTextureList[pos];
|
||||
*texture = gTexture();
|
||||
texture->_texture = createGLTexture();
|
||||
|
||||
if (bUseAlternate) {
|
||||
auto stream = workDirs.resolveFile(AlternateName);
|
||||
if (!stream) {
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s.\n", AlternateName);
|
||||
return nullptr;
|
||||
}
|
||||
auto ddsTextureData = loadDdsTexture(*stream);
|
||||
texture->_texture->assignData(*ddsTextureData);
|
||||
dwWidth = ddsTextureData->getWidth();
|
||||
dwHeight = ddsTextureData->getHeight();
|
||||
//lpSSource = nullptr;
|
||||
#if 0
|
||||
if (gRenderFlags & gDXT1SUPPORTED) {
|
||||
/* if( gRenderFlags & gAGPSUPPORTED )
|
||||
{ // Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
lpSSource = Texture->lpDDSurface;
|
||||
} else
|
||||
DDSurfDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||
if (!(lpSSource = gCreateSurface(&DDSurfDesc, lpSSource))) {
|
||||
DebugLogFile("gLoadTexture: gCreateSurface FAILED: Can't create surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((lpSSource->Lock(NULL, &DDSurfDesc, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL))) { // Lock and fill with the dds
|
||||
DebugLogFile("gLoadTexture: Can't lock surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t3dReadData(DDSurfDesc.lpSurface, DDSurfDesc.dwLinearSize);
|
||||
|
||||
if ((lpSSource->Unlock(NULL))) {
|
||||
DebugLogFile("gLoadTexture: Can't unlock surface DDS");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
stream = nullptr;
|
||||
} else { // TGA
|
||||
auto stream = workDirs.resolveFile(TextName);
|
||||
auto image = ReadTgaImage(TextName, *stream, Graphics::PixelFormat::createFormatRGBA32(), 0); // TODO Flags
|
||||
SurfaceBackedTextureData texData(image);
|
||||
|
||||
texture->_texture->assignData(texData);
|
||||
#if 0
|
||||
//warning("TODO: Handle TGA");
|
||||
if (!t3dOpenFile(TextName)) {
|
||||
DebugLogFile("gAddMaterial:gLoadTexture: Cannot find %s.\n", TextName);
|
||||
return NULL;
|
||||
}
|
||||
// Parse the PPM header
|
||||
if (!loadTGAHeader(&dwWidth, &dwHeight)) {
|
||||
t3dCloseFile();
|
||||
DebugLogFile("gAddMaterial: gLoadTexture: Could not load or parse TGA header in %s.\n", TextName);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if 0 // Replaced by createTextureFromSurface
|
||||
if (!(gRenderFlags & gDXT1SUPPORTED) || (bUseAlternate == FALSE)) {
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
/* if (gRenderFlags&gAGPSUPPORTED)
|
||||
{ //Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
DDSurfDesc.dwWidth = dwWidth;
|
||||
DDSurfDesc.dwHeight = dwHeight;
|
||||
if (!(Texture->lpDDSurface = gCreateSurface(&DDSurfDesc, Texture->lpDDSurface))) {
|
||||
DebugLogFile("gLoadTexture: gCreateSurface FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
texture->name = TextName;
|
||||
|
||||
if (bUseAlternate) {
|
||||
#if 0
|
||||
// DebugFile( "Carico |%s|", AlternateName );
|
||||
if (!(gRenderFlags & gDXT1SUPPORTED)) {
|
||||
if (Texture->lpDDSurface->Blt(NULL, lpSSource, NULL, DDBLT_WAIT, NULL) != DD_OK) {
|
||||
DebugLogFile("gLoadTexture: Can't Blit DDS texture");
|
||||
return NULL;
|
||||
}
|
||||
lpSSource->Release();
|
||||
} else
|
||||
Texture->lpDDSurface = lpSSource;
|
||||
#endif
|
||||
} else {
|
||||
#if 0
|
||||
// DebugFile( "Carico |%s|", TextName );
|
||||
Texture->lpDDSurface->Lock(NULL, &DDSurfDesc, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL); //Lock and fill with the tga
|
||||
if (gCurrentFormat->abits)
|
||||
bAlpha = TRUE;
|
||||
|
||||
if (!ReadTgaImage(TextName, &DDSurfDesc, bAlpha)) {
|
||||
DebugLogFile("gLoadTexture: Error reading TGA file");
|
||||
return NULL;
|
||||
}
|
||||
Texture->lpDDSurface->Unlock(NULL);
|
||||
#endif
|
||||
}
|
||||
texture->RealDimX = dwWidth;
|
||||
texture->RealDimY = dwHeight;
|
||||
|
||||
if (_LoaderFlags & rSURFACEHALF) {
|
||||
warning("Half-res loading not implemented");
|
||||
#if 0
|
||||
LPDIRECTDRAWSURFACE7 surf;
|
||||
HRESULT err;
|
||||
|
||||
dwWidth /= 2;
|
||||
dwHeight /= 2;
|
||||
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
/* if (gRenderFlags&gAGPSUPPORTED)
|
||||
{ //Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps= DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
}
|
||||
else
|
||||
*/ { //No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
surf = NULL;
|
||||
DDSurfDesc.dwWidth = dwWidth;
|
||||
DDSurfDesc.dwHeight = dwHeight;
|
||||
if (!(surf = gCreateSurface(&DDSurfDesc, surf))) {
|
||||
DebugLogFile("gLoadTexture (rSURFACEHALF) FAILED: Can't create surface");
|
||||
return NULL;
|
||||
}
|
||||
if ((err = surf->Blt(NULL, Texture->lpDDSurface, NULL, 0, NULL)) != DD_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(err, str, 1);
|
||||
DebugLogFile("gLoadTexture: BltStretch failed.\n%s", str);
|
||||
}
|
||||
|
||||
//Release old texture
|
||||
Texture->lpDDSurface->Release();
|
||||
//Assign the newone
|
||||
Texture->lpDDSurface = surf;
|
||||
#endif
|
||||
}
|
||||
|
||||
texture->ID = pos;
|
||||
|
||||
texture->Flags = CurLoaderFlags;
|
||||
texture->DimX = dwWidth;
|
||||
texture->DimY = dwHeight;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
bool Renderer::addMaterial(gMaterial &material, const Common::String &name, int NumFaces, unsigned int _LoaderFlags) {
|
||||
//warning("AddMaterial(%s)", name.c_str());
|
||||
if (hasFileExtension(name, "avi")) {
|
||||
auto tex = createGLTexture();
|
||||
if ((material.Movie = gLoadMovie(*_workDirs, name.c_str(), tex)) == nullptr)
|
||||
return false;
|
||||
if ((material.Texture = gUserTexture(tex, 64, 128)) == nullptr)
|
||||
// if( (Material->Texture=gUserTexture( Material->Movie->g_psiStreamInfo.rcFrame.right,
|
||||
// Material->Movie->g_psiStreamInfo.rcFrame.bottom)) == NULL )
|
||||
return false;
|
||||
material.addProperty(T3D_MATERIAL_MOVIE);
|
||||
} else {
|
||||
if ((material.Texture = gLoadTexture(*_workDirs, name.c_str(), _LoaderFlags)) == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
//f
|
||||
material.addProperty(T3D_MATERIAL_NOLIGHTMAP);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
67
engines/watchmaker/3d/render/opengl_3d.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_3D_H
|
||||
#define WATCHMAKER_OPENGL_3D_H
|
||||
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
#define MAXTEXTURES 2000
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
struct gAvailFormat {
|
||||
//DDPIXELFORMAT SurfaceDesc;
|
||||
char rbits;
|
||||
char gbits;
|
||||
char bbits;
|
||||
char abits;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float sx, sy, sz, rhw;
|
||||
uint32 color;
|
||||
};
|
||||
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern unsigned int gNumLinesArray;
|
||||
|
||||
extern gAvailFormat *gCurrentFormat;
|
||||
extern int NumAvailableFormats;
|
||||
extern gAvailFormat AvailableFormats[];
|
||||
|
||||
extern gTexture gTextureList[];
|
||||
extern unsigned int gNumTextureList;
|
||||
|
||||
extern uint16 gLinesArray[];
|
||||
extern unsigned int gNumLinesArray;
|
||||
extern unsigned int gNumTrianglesArray;
|
||||
extern Vertex gTriangles[];
|
||||
extern int g_lpD3DPointsBuffer;
|
||||
extern void *g_lpD3DUserVertexBuffer;
|
||||
extern unsigned int g_dwD3DUserVertexBufferCounter;
|
||||
extern unsigned int gNumPointsBuffer;
|
||||
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_3D_H
|
||||
239
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal file
239
engines/watchmaker/3d/render/opengl_renderer.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
|
||||
#if defined(USE_OPENGL_GAME)
|
||||
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "math/glmath.h"
|
||||
|
||||
#include "math/glmath.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
OpenGLRenderer *g_renderer = nullptr;
|
||||
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, Common::SharedPtr<VertexBuffer> VBO, int firstVertex, int numVertices, Common::Array<uint16> faces, uint32 numFaces) {
|
||||
assert(numFaces <= faces.size());
|
||||
|
||||
assert(primitiveType == PrimitiveType::TRIANGLE);
|
||||
|
||||
float fNearPlane = 1.0f;//5000.0f;
|
||||
float fFarPlane = 15000.0f;
|
||||
float width = 1024;
|
||||
float height = 768;
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
float fAspect = 60.0f;//curCamera->FovRad;
|
||||
auto perspectiveMatrix = Math::makePerspectiveMatrix(fAspect, width / height, fNearPlane, fFarPlane);
|
||||
glLoadMatrixf(perspectiveMatrix.getData());
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (uint32 i = 0; i < numFaces; i++) {
|
||||
uint16 index = faces[i];
|
||||
assert(index <= VBO->_buffer.size());
|
||||
auto &vertex = VBO->_buffer[index];
|
||||
//warning("%d/%d %d: [%f, %f, %f], [%f, %f], [%f, %f]", i, numFaces, index, vertex.x, vertex.y, vertex.z, vertex.u1, vertex.v1, vertex.u2, vertex.v2);
|
||||
//glColor4f((float)i/numFaces, 1.0f, 0.0f, 1.0f);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glTexCoord2f(vertex.u1, vertex.v1);
|
||||
glVertex3f(vertex.x, vertex.y, -vertex.z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPrimitives(PrimitiveType primitiveType, Vertex *vertices, int numPrimitives) {
|
||||
assert(primitiveType == PrimitiveType::TRIANGLE);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < numPrimitives; i++) {
|
||||
auto &vertex = vertices[i];
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glVertex3f(vertex.sx, vertex.sy, -vertex.sz);
|
||||
}
|
||||
glEnd();
|
||||
glFlush();
|
||||
}
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, int VBO, int firstVertex, int numVertices, uint16 *faces, uint32 numFaces) {
|
||||
//warning("TODO: Implement drawIndexedPrimitivesVBO");
|
||||
}
|
||||
|
||||
|
||||
void OpenGLRenderer::drawIndexedPrimitivesVBO(PrimitiveType primitiveType, gBatchBlock &bb) {
|
||||
drawIndexedPrimitivesVBO(primitiveType,
|
||||
bb.VBO, 0, bb.NumVerts(),
|
||||
bb.FacesList,
|
||||
bb.NumFaces()/*, 0x0*/
|
||||
);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTransformMatrix(TransformMatrix which, const Matrix4x4 &matrix) {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(matrix.data);
|
||||
glScalef(1.0f, 1.0f, -1.0f);
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::pushModelView() {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::popModelView() {
|
||||
GLint oldMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &oldMatrixMode);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(oldMatrixMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTextureWrapMode(int index, TextureWrapMode mode) {
|
||||
GLint openGlWrapMode = 0;
|
||||
switch (mode) {
|
||||
case TextureWrapMode::WRAP:
|
||||
openGlWrapMode = GL_REPEAT;
|
||||
break;
|
||||
case TextureWrapMode::CLAMP:
|
||||
openGlWrapMode = GL_CLAMP;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, openGlWrapMode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, openGlWrapMode);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setTexture(int stage, void *texture) {
|
||||
if (texture == nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
void OpenGLRenderer::setTexture(int stage, const gTexture &texture) {
|
||||
texture._texture->bind();
|
||||
}
|
||||
|
||||
void setGlFeature(GLint feature, bool state) {
|
||||
if (state) {
|
||||
glEnable(feature);
|
||||
} else {
|
||||
glDisable(feature);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setRenderState(RenderState state, int value) {
|
||||
switch (state) {
|
||||
case RenderState::ZENABLE:
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
setGlFeature(GL_DEPTH_TEST, value);
|
||||
break;
|
||||
case RenderState::ALPHAREF: // ALPHA-func is never changed.
|
||||
glAlphaFunc(GL_ALWAYS, value);
|
||||
// fall through
|
||||
// FIXME: Is this intended?
|
||||
case RenderState::ALPHABLEND:
|
||||
setGlFeature(GL_BLEND, value);
|
||||
break; // TODO
|
||||
|
||||
case RenderState::LIGHT:
|
||||
case RenderState::CLIP:
|
||||
case RenderState::EXTENT:
|
||||
case RenderState::ZWRITE_ENABLE:
|
||||
case RenderState::TEXTUREFACTOR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//warning("TODO: Implement setRenderState");
|
||||
}
|
||||
|
||||
GLenum translateBlendFactorToGL(BlendFactor factor) {
|
||||
switch (factor) {
|
||||
case BlendFactor::ONE:
|
||||
return GL_ONE;
|
||||
case BlendFactor::ZERO:
|
||||
return GL_ZERO;
|
||||
case BlendFactor::SRCALPHA:
|
||||
return GL_SRC_ALPHA;
|
||||
case BlendFactor::INVSRCALPHA:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
case BlendFactor::INVSRCCOLOR:
|
||||
return GL_ONE_MINUS_SRC_COLOR;
|
||||
case BlendFactor::SRCCOLOR:
|
||||
return GL_SRC_COLOR;
|
||||
case BlendFactor::DESTCOLOR:
|
||||
return GL_DST_COLOR;
|
||||
case BlendFactor::INVDESTCOLOR:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
default:
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setBlendFunc(BlendFactor src, BlendFactor dst) {
|
||||
glBlendFunc(translateBlendFactorToGL(src), translateBlendFactorToGL(dst));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::enter2Dmode() {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
checkGlError("Exiting enter2Dmode");
|
||||
}
|
||||
|
||||
void OpenGLRenderer::exit2Dmode() {
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
checkGlError("exit2Dmode");
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
110
engines/watchmaker/3d/render/opengl_renderer.h
Normal file
110
engines/watchmaker/3d/render/opengl_renderer.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_OPENGL_RENDERER_H
|
||||
#define WATCHMAKER_OPENGL_RENDERER_H
|
||||
|
||||
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
enum class TransformMatrix {
|
||||
PROJECTION,
|
||||
VIEW
|
||||
};
|
||||
|
||||
enum class RenderState {
|
||||
LIGHT,
|
||||
CLIP,
|
||||
EXTENT,
|
||||
ALPHABLEND,
|
||||
ALPHAREF, // TODO
|
||||
ZENABLE, // TODO
|
||||
ZWRITE_ENABLE, // TODO
|
||||
TEXTUREFACTOR // TODO
|
||||
};
|
||||
|
||||
enum class BlendFactor {
|
||||
ONE,
|
||||
ZERO,
|
||||
SRCALPHA,
|
||||
INVSRCALPHA,
|
||||
INVSRCCOLOR,
|
||||
SRCCOLOR,
|
||||
DESTCOLOR,
|
||||
INVDESTCOLOR
|
||||
};
|
||||
|
||||
enum class TextureWrapMode {
|
||||
WRAP,
|
||||
CLAMP
|
||||
};
|
||||
|
||||
enum class PrimitiveType {
|
||||
LINE,
|
||||
TRIANGLE
|
||||
};
|
||||
|
||||
Common::SharedPtr<TextureData> createTextureFromSurface(Graphics::Surface &surface, int texFormat);
|
||||
Texture *createGLTexture();
|
||||
|
||||
class OpenGLRenderer {
|
||||
public:
|
||||
void enter2Dmode();
|
||||
void exit2Dmode();
|
||||
|
||||
void pushModelView();
|
||||
void popModelView();
|
||||
void setTransformMatrix(TransformMatrix which, const Matrix4x4 &matrix);
|
||||
// TODO: This should be split.
|
||||
void setRenderState(RenderState state, int value);
|
||||
void setBlendFunc(BlendFactor src, BlendFactor dst);
|
||||
bool error() const {
|
||||
//warning("TODO: Implement error");
|
||||
return false;
|
||||
}
|
||||
Common::String getErrorString() {
|
||||
warning("TODO: Implement getErrorString");
|
||||
return "";
|
||||
}
|
||||
// TODO: This just maps to the D3D way to setting textures
|
||||
void setTexture(int stage, void *texture);
|
||||
void setTexture(int stage, const gTexture &texture);
|
||||
void setTextureWrapMode(int index, TextureWrapMode mode);
|
||||
|
||||
void drawPrimitives(PrimitiveType primitiveType, Vertex *vertices, int numPrimitives);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, int VBO, int firstVertex, int numVertices, uint16 *faces, uint32 numFaces);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, Common::SharedPtr<VertexBuffer> VBO, int firstVertex, int numVertices, Common::Array<uint16> faces, uint32 numFaces);
|
||||
void drawIndexedPrimitivesVBO(PrimitiveType primitiveType, gBatchBlock &bb);
|
||||
bool supportsMultiTexturing() const { // TODO
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
extern OpenGLRenderer *g_renderer;
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_OPENGL_RENDERER_H
|
||||
96
engines/watchmaker/3d/render/opengl_texture.cpp
Normal file
96
engines/watchmaker/3d/render/opengl_texture.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/opengl_texture.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "graphics/opengl/system_headers.h"
|
||||
#include "watchmaker/3d/dds_header.h"
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
#ifdef USE_OPENGL_GAME
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
GLuint dxtCompressionToTextureFormat(DxtCompression compression) {
|
||||
switch (compression) {
|
||||
case DxtCompression::UNCOMPRESSED:
|
||||
default:
|
||||
return GL_RGBA;
|
||||
case DxtCompression::DXT1:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
case DxtCompression::DXT2:
|
||||
error("DXT2 Support is not implemented");
|
||||
case DxtCompression::DXT3:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
case DxtCompression::DXT4:
|
||||
error("DXT4 Support is not implemented");
|
||||
case DxtCompression::DXT5:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
}
|
||||
|
||||
class OpenGLTexture : public Texture {
|
||||
public:
|
||||
unsigned int _texId;
|
||||
OpenGLTexture() {
|
||||
glGenTextures(1, &_texId);
|
||||
}
|
||||
OpenGLTexture(unsigned int texId) : _texId(texId) {}
|
||||
void assignData(const TextureData &data) override {
|
||||
glBindTexture(GL_TEXTURE_2D, _texId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
|
||||
// TODO: Check both compiletime and runtime for the existence of EXT_texture_compression_s3tc
|
||||
GLuint texFormat = dxtCompressionToTextureFormat(data._compression);
|
||||
bool compressed = data._compression != DxtCompression::UNCOMPRESSED;
|
||||
|
||||
if (compressed) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, // target
|
||||
0, // level
|
||||
texFormat, // internalFormat
|
||||
data.getWidth(), // width
|
||||
data.getHeight(), // height
|
||||
0, // border
|
||||
data.getDataSize(),
|
||||
data.getData()
|
||||
);
|
||||
checkGlError("glCompressedTexImage");
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, texFormat, data.getWidth(), data.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.getData());
|
||||
checkGlError("glTexImage2D");
|
||||
}
|
||||
}
|
||||
void bind() override {
|
||||
glBindTexture(GL_TEXTURE_2D, _texId);
|
||||
checkGlError("OpenGLTexture::bind");
|
||||
};
|
||||
};
|
||||
|
||||
Texture *createGLTexture() {
|
||||
return new OpenGLTexture();
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // USE_OPENGL_GAME
|
||||
32
engines/watchmaker/3d/render/opengl_texture.h
Normal file
32
engines/watchmaker/3d/render/opengl_texture.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
#define WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
class Texture;
|
||||
Texture *createGLTexture();
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_3D_OPENGL_TEXTURE_H
|
||||
621
engines/watchmaker/3d/render/render.cpp
Normal file
621
engines/watchmaker/3d/render/render.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/3d/render/opengl_3d.h"
|
||||
#include "watchmaker/render.h"
|
||||
#include "watchmaker/3d/render/opengl_renderer.h"
|
||||
#include "watchmaker/3d/render/opengl_2d.h"
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/ll/ll_regen.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
unsigned int bLightmaps = FALSE; // if lightmaps are activated
|
||||
unsigned int bDisableShadows = FALSE; // if shadows should be disabled
|
||||
unsigned int bDisableMultiTexturing = FALSE; // if multitexturing should be disabled
|
||||
|
||||
gBatchBlock BatchBlockList[MAX_BATCH_BLOCKS];
|
||||
gBatchBlock BatchBlockListSpecial[MAX_BATCH_BLOCKS_SPECIAL];
|
||||
//gBatchBlock BatchBlockListLightmaps[MAX_BATCH_BLOCKS_LIGHTMAPS];
|
||||
gBatchBlock BatchBlockListSky[MAX_BATCH_BLOCKS_SKY];
|
||||
|
||||
unsigned int NumBatchBlocks = 0;
|
||||
unsigned int NumBatchBlocksSpecial = 0;
|
||||
//unsigned int NumBatchBlocksLightmaps=0;
|
||||
unsigned int NumBatchBlocksSky = 0;
|
||||
|
||||
/* -----------------13/08/99 10.34-------------------
|
||||
* Comparazione per BB
|
||||
* --------------------------------------------------*/
|
||||
int cmpbb(const void *a, const void *b) {
|
||||
const gBatchBlock *v1 = (const gBatchBlock *)a;
|
||||
const gBatchBlock *v2 = (const gBatchBlock *)b;
|
||||
|
||||
if (v1->Texture2 < v2->Texture2) return -1;
|
||||
else if (v1->Texture2 > v2->Texture2) return 1;
|
||||
else if (v1->Texture1 < v2->Texture1) return -1;
|
||||
else if (v1->Texture1 > v2->Texture1) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/* -----------------31/05/99 10.12-------------------
|
||||
* Attiva o disattiva lo ZBuffer
|
||||
* --------------------------------------------------*/
|
||||
bool rSetZBufferState(bool state) {
|
||||
g_renderer->setRenderState(RenderState::ZENABLE, state);
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, state);
|
||||
|
||||
return !g_renderer->error();
|
||||
}
|
||||
|
||||
|
||||
/* -----------------25/06/99 11.14-------------------
|
||||
* Renderizza il cielo senza considerare lo zbuffer
|
||||
* --------------------------------------------------*/
|
||||
void RenderSky() {
|
||||
unsigned int i;
|
||||
bool hres;
|
||||
gBatchBlock *bb;
|
||||
|
||||
if (!NumBatchBlocksSky)
|
||||
return;
|
||||
|
||||
if (!rSetZBufferState(false)) {
|
||||
DebugLogFile("Can't rSetZBufferState FALSE");
|
||||
return ;
|
||||
}
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, TRUE);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCALPHA);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bb = &BatchBlockListSky[0];
|
||||
for (i = 0; i < NumBatchBlocksSky; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
if (!rSetZBufferState(true)) {
|
||||
DebugLogFile("Can't rSetZBufferState TRUE");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------31/05/99 10.19-------------------
|
||||
* Renderizza la Geometria
|
||||
* --------------------------------------------------*/
|
||||
void RenderGeometry() {
|
||||
signed short int LastViewMatrixNum, LastTexture1, LastTexture2;
|
||||
gBatchBlock *bb;
|
||||
bool hres = false;
|
||||
|
||||
RenderSky();
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
g_renderer->setTextureWrapMode(1, TextureWrapMode::CLAMP);
|
||||
|
||||
g_renderer->setRenderState(RenderState::TEXTUREFACTOR, 0xFFFFFFFF);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000000);
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, FALSE);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockList[0];
|
||||
qsort(bb, NumBatchBlocks, sizeof(gBatchBlock), cmpbb);
|
||||
for (uint i = 0; i < NumBatchBlocks; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
if ((g_renderer->supportsMultiTexturing()) && (bb->Texture2 != LastTexture2)) {
|
||||
if (bb->Texture2 > 0) {
|
||||
if (LastTexture2 <= 0) {
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
#endif
|
||||
g_renderer->setTextureWrapMode(1, TextureWrapMode::CLAMP);
|
||||
}
|
||||
g_renderer->setTexture(1, gTextureList[bb->Texture2]);
|
||||
} else if (LastTexture2 > 0) {
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
g_renderer->setTexture(1, nullptr);
|
||||
}
|
||||
LastTexture2 = bb->Texture2;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
}
|
||||
//warning("TODO: Texture configuration");
|
||||
#if 0
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
g_renderer->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
#endif
|
||||
|
||||
// 2nd pass: lightmaps, if device doesn't support multi-texturing
|
||||
if ((!g_renderer->supportsMultiTexturing()) && (bLightmaps)) {
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, FALSE);
|
||||
|
||||
#if 0 // TODO
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 1); // use mapping coordinates set 1
|
||||
#endif
|
||||
g_renderer->setBlendFunc(BlendFactor::ZERO, BlendFactor::SRCCOLOR);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, true);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockList[0];
|
||||
for (uint i = 0; i < NumBatchBlocks; i++, bb++) {
|
||||
if (bb->Texture2 <= 0) continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture2 != LastTexture2) {
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture2]);
|
||||
LastTexture2 = bb->Texture2;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, TRUE);
|
||||
#if 0 // TODO
|
||||
g_renderer->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); // mapping coordinates back to set 0
|
||||
#endif
|
||||
}
|
||||
|
||||
// Clipmaps
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, TRUE);
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCALPHA);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
qsort(bb, NumBatchBlocksSpecial, sizeof(gBatchBlock), cmpbb);
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if (!(bb->Flags1 & T3D_MATERIAL_CLIPMAP) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_FLARE) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
// Render Smoke or Flare materials
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000055);
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, FALSE);
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if (!(bb->Flags1 & T3D_MATERIAL_FLARE) &&
|
||||
!(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->Flags1 & T3D_MATERIAL_FLARE_SUN) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVSRCCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_FLARESOFT) {
|
||||
g_renderer->setRenderState(RenderState::ZENABLE, FALSE);
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ONE);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_SMOKE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::SRCALPHA, BlendFactor::ONE);
|
||||
} else {
|
||||
g_renderer->setBlendFunc(BlendFactor::SRCCOLOR, BlendFactor::ONE);
|
||||
}
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
g_renderer->setRenderState(RenderState::ZWRITE_ENABLE, TRUE);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print transparent/translucent materials
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x0000002);
|
||||
|
||||
LastViewMatrixNum = LastTexture1 = LastTexture2 = -2;
|
||||
bb = &BatchBlockListSpecial[0];
|
||||
for (uint i = 0; i < NumBatchBlocksSpecial; i++, bb++) {
|
||||
if (bb->Texture1 < 0) continue;
|
||||
if ((bb->Flags1 & T3D_MATERIAL_FLARE) ||
|
||||
(bb->Flags1 & T3D_MATERIAL_SMOKE))
|
||||
continue;
|
||||
|
||||
if (bb->Flags1 & T3D_MATERIAL_GLASS) {
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ZERO);
|
||||
return;
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_OPACITY) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::SRCCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_BOTTLE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::INVDESTCOLOR);
|
||||
} else if (bb->Flags1 & T3D_MATERIAL_ADDITIVE) {
|
||||
g_renderer->setBlendFunc(BlendFactor::DESTCOLOR, BlendFactor::ONE);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (g_renderer->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bb->ViewMatrixNum != LastViewMatrixNum) {
|
||||
rSetUserViewMatrix(bb->ViewMatrixNum);
|
||||
LastViewMatrixNum = bb->ViewMatrixNum;
|
||||
}
|
||||
if (bb->Texture1 != LastTexture1) {
|
||||
if (bb->Texture1)
|
||||
g_renderer->setTexture(0, gTextureList[bb->Texture1]);
|
||||
else
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
LastTexture1 = bb->Texture1;
|
||||
}
|
||||
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::TRIANGLE, *bb);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
bb->Texture1 = -3;
|
||||
bb->Texture2 = -3;
|
||||
}
|
||||
|
||||
// Render blank materials
|
||||
// ???
|
||||
}
|
||||
|
||||
/* -----------------31/05/99 10.55-------------------
|
||||
* Renderizza la scena
|
||||
* --------------------------------------------------*/
|
||||
bool rRenderScene() {
|
||||
unsigned int i, j;
|
||||
bool hres;
|
||||
//static unsigned int dwFrameCount = 0;
|
||||
|
||||
g_renderer->setRenderState(RenderState::LIGHT, false);
|
||||
g_renderer->setRenderState(RenderState::CLIP, true);
|
||||
g_renderer->setRenderState(RenderState::EXTENT, false);
|
||||
|
||||
// Added:
|
||||
ResetScreenBuffer();
|
||||
|
||||
if (!gStencilBitDepth && !bDisableShadows) {
|
||||
//tb
|
||||
//Render Projected shadow into shadow surface
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
if (bDisableShadows) break;
|
||||
warning("TODO: Shadows");
|
||||
#if 0
|
||||
for (i = 0; i < sb->NumShadowsList; i++) {
|
||||
if (!(hres = RenderProjectiveShadow(&sb->ShadowsList[i]))) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogFile("Unable to RenderProjectiveShadow into a texture: %s | %d %d | %d", str.c_str(), S_OK, DD_OK, hres);
|
||||
bDisableShadows = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sb->ShadowsList[i].ProjectiveTexture.lpDDSurface) {
|
||||
if (hres = sb->ShadowsList[i].ProjectiveTexture.lpDDSurface->BltFast(0, 0, g_pddsShadowBuffer, NULL, DDBLTFAST_NOCOLORKEY) != S_OK) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to blitfast Shadowbuffer into a texture: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/* if (g_pddsBackBuffer && !j)
|
||||
{
|
||||
RECT rect;
|
||||
rect.left=rect.top=0;
|
||||
rect.right=rect.bottom=256;
|
||||
|
||||
if (FAILED(hres=g_pddsBackBuffer->BltFast(0,0,sb->ShadowsList[i].ProjectiveTexture.lpDDSurface,&rect,DDBLTFAST_NOCOLORKEY)))
|
||||
{
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to blit projective texture: %s",str);
|
||||
bDisableShadows=TRUE;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//tb
|
||||
}
|
||||
|
||||
// Begin the scene.
|
||||
#if 0
|
||||
if (FAILED(g_pd3dDevice->BeginScene()))
|
||||
goto closescene;
|
||||
#endif
|
||||
RenderGeometry();
|
||||
|
||||
if (gStencilBitDepth && !bDisableShadows) {
|
||||
//sb
|
||||
rSaveViewMatrix();
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x00000002);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("Unable to SetRenderState for Shadowbuffer: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
}
|
||||
|
||||
//Render Shadows volumes
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
for (i = 0; i < sb->NumShadowsList; i++)
|
||||
RenderShadow(&sb->ShadowsList[i], sb->ShadowsList[i].VB);
|
||||
|
||||
if (i) {
|
||||
RenderShadowBox(sb, sb->VBO);
|
||||
|
||||
unsigned int width, height, bpp;
|
||||
rGetScreenInfos(&width, &height, &bpp);
|
||||
DrawShadow(0, 0, width, height, sb->Intensity);
|
||||
}
|
||||
}
|
||||
rRestoreViewMatrix();
|
||||
//sb
|
||||
} else if (!bDisableShadows) {
|
||||
//tb
|
||||
for (j = 0; j < gNumShadowBoxesList; j++) {
|
||||
SHADOWBOX *sb = ShadowBoxesList[j];
|
||||
rSetUserViewMatrix(sb->ViewMatrixNum);
|
||||
for (i = 0; i < sb->NumShadowsList; i++)
|
||||
if (!(hres = DrawProjectiveShadow(&sb->ShadowsList[i]))) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogFile("Unable to DrawProjectiveShadow: %s", str.c_str());
|
||||
bDisableShadows = TRUE;
|
||||
}
|
||||
}
|
||||
//tb
|
||||
}
|
||||
|
||||
if (gNumLinesArray && gNumPointsBuffer) {
|
||||
rSaveViewMatrix();
|
||||
rSetLinesViewMatrix();
|
||||
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::ZERO);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, false);
|
||||
if (g_renderer->error()) {
|
||||
goto closescene;
|
||||
}
|
||||
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
/*
|
||||
hres=g_pd3dDevice->DrawIndexedPrimitiveVB( D3DPT_LINELIST,
|
||||
g_lpD3DPointsBuffer,0,gNumPointsBuffer,
|
||||
gLinesArray, gNumLinesArray,0);
|
||||
*/
|
||||
g_renderer->drawIndexedPrimitivesVBO(PrimitiveType::LINE, g_lpD3DPointsBuffer, 0, gNumPointsBuffer, gLinesArray, gNumLinesArray/*, 0*/);
|
||||
hres = g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
rRestoreViewMatrix();
|
||||
gNumLinesArray = 0;
|
||||
}
|
||||
|
||||
|
||||
if (gNumTrianglesArray) {
|
||||
rSetZBufferState(FALSE);
|
||||
|
||||
g_renderer->setRenderState(RenderState::ALPHAREF, 0x0000000);
|
||||
g_renderer->setBlendFunc(BlendFactor::ONE, BlendFactor::SRCALPHA);
|
||||
g_renderer->setRenderState(RenderState::ALPHABLEND, true);
|
||||
if (g_renderer->error()) {
|
||||
goto closescene;
|
||||
}
|
||||
|
||||
g_renderer->setTexture(0, nullptr);
|
||||
g_renderer->drawPrimitives(PrimitiveType::TRIANGLE,
|
||||
/*D3DFVF_TLVERTEX,*/ gTriangles,
|
||||
gNumTrianglesArray/*, 0x0*/);
|
||||
hres = !g_renderer->error();
|
||||
if (!hres) {
|
||||
Common::String str = g_renderer->getErrorString();
|
||||
DebugLogWindow("DrawIndexedPrimitiveVB ERROR:\n\r%s", str.c_str());
|
||||
}
|
||||
gNumTrianglesArray = 0;
|
||||
rSetZBufferState(TRUE);
|
||||
}
|
||||
#if 0
|
||||
g_pd3dDevice->EndScene();
|
||||
#endif
|
||||
NumBatchBlocks = 0;
|
||||
NumBatchBlocksSpecial = 0;
|
||||
// NumBatchBlocksLightmaps=0;
|
||||
NumBatchBlocksSky = 0;
|
||||
|
||||
//dwFrameCount++;
|
||||
|
||||
return TRUE;
|
||||
// End the scene.
|
||||
|
||||
closescene:
|
||||
#if 0
|
||||
g_pd3dDevice->EndScene();
|
||||
#endif
|
||||
DebugLogFile("Error during renderscene");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------13/08/99 10.34-------------------
|
||||
* Aggiunge un nuovo BatchBlock
|
||||
* --------------------------------------------------*/
|
||||
gBatchBlock *rNewBatchBlock(signed short int T1, unsigned int F1, signed short int T2, unsigned int F2) {
|
||||
gBatchBlock *bb;
|
||||
|
||||
bb = nullptr;
|
||||
if ((F1 & T3D_MATERIAL_GLASS) ||
|
||||
(F1 & T3D_MATERIAL_OPACITY) ||
|
||||
(F1 & T3D_MATERIAL_CLIPMAP) ||
|
||||
(F1 & T3D_MATERIAL_SMOKE) ||
|
||||
(F1 & T3D_MATERIAL_BOTTLE) ||
|
||||
(F1 & T3D_MATERIAL_FLARE) ||
|
||||
(F1 & T3D_MATERIAL_ADDITIVE)) {
|
||||
if ((NumBatchBlocksSpecial + 1) < MAX_BATCH_BLOCKS_SPECIAL)
|
||||
bb = &BatchBlockListSpecial[NumBatchBlocksSpecial++];
|
||||
else
|
||||
DebugLogFile("Too many BB Special: %d (MAX is %d)!", NumBatchBlocksSpecial, MAX_BATCH_BLOCKS_SPECIAL);
|
||||
}
|
||||
// else if( (T2>0) )
|
||||
// {
|
||||
// if( (NumBatchBlocksLightmaps+1) < MAX_BATCH_BLOCKS_LIGHTMAPS )
|
||||
// bb=&BatchBlockList[NumBatchBlocksLightmaps++];
|
||||
// else
|
||||
// DebugLogFile("Too many BB LightMaps: %d (MAX is %d)!",NumBatchBlocksLightmaps,MAX_BATCH_BLOCKS_LIGHTMAPS);
|
||||
// }
|
||||
else if ((F1 & T3D_MATERIAL_SKY)) {
|
||||
if ((NumBatchBlocksSky + 1) < MAX_BATCH_BLOCKS_SKY)
|
||||
bb = &BatchBlockListSky[NumBatchBlocksSky++];
|
||||
else
|
||||
DebugLogFile("Too many BB Sky: %d (MAX is %d)!", NumBatchBlocksSky, MAX_BATCH_BLOCKS_SKY);
|
||||
} else {
|
||||
if ((NumBatchBlocks + 1) < MAX_BATCH_BLOCKS)
|
||||
bb = &BatchBlockList[NumBatchBlocks++];
|
||||
else
|
||||
DebugLogFile("Too many BB: %d (MAX is %d)!", NumBatchBlocks, MAX_BATCH_BLOCKS);
|
||||
}
|
||||
|
||||
if (!bb) return nullptr;
|
||||
|
||||
*bb = gBatchBlock(T1, T2, F1, F2);
|
||||
return bb;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
29
engines/watchmaker/3d/render/render.h
Normal file
29
engines/watchmaker/3d/render/render.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_3D_RENDER_H
|
||||
#define WATCHMAKER_3D_RENDER_H
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_3D_RENDER_H
|
||||
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
945
engines/watchmaker/3d/render/shadows.cpp
Normal file
@@ -0,0 +1,945 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/3d/render/shadows.h"
|
||||
#include "watchmaker/3d/math/Matrix4x4.h"
|
||||
|
||||
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
SHADOWBOX *ShadowBoxesList[MAX_SHADOW_BOXES];
|
||||
unsigned int gNumShadowBoxesList = 0;
|
||||
|
||||
unsigned int gGetTextureListPosition();
|
||||
extern unsigned int CurLoaderFlags;
|
||||
#if 0
|
||||
#pragma pack(1)
|
||||
struct COLORVERTEX { // vertex structures
|
||||
D3DVECTOR p;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
|
||||
struct TRANSCOLORVERTEX { // transformed vertex
|
||||
D3DVECTOR p;
|
||||
D3DVALUE rhw;
|
||||
D3DCOLOR c;
|
||||
};
|
||||
#pragma pack()
|
||||
#endif
|
||||
#define MAX_SHADOW_BOXES 20 // max shadows
|
||||
|
||||
bool g_bUseOneBitStencil = FALSE; // if Stencil buffer if 1 bit deep only
|
||||
DWORD g_max_StencilVal = 255; // maximum value the stencil buffer will hold
|
||||
#if 0
|
||||
D3DSTENCILOP g_StencDecOp, g_StencIncOp; // increment e decrement functions
|
||||
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowBuffer = NULL;
|
||||
LPDIRECTDRAWSURFACE7 g_pddsShadowZBuffer = NULL;
|
||||
#endif
|
||||
//************************************************************************************************
|
||||
inline void SetIdentityMatrix(Matrix4x4 &m) { // set D3D matrix to identity
|
||||
m.setIdentity();
|
||||
}
|
||||
|
||||
#if 0
|
||||
//************************************************************************************************
|
||||
int ccw(COLORVERTEX *P[], int i, int j, int k) { // for convex-hull
|
||||
double a = P[i]->p.x - P[j]->p.x,
|
||||
b = P[i]->p.y - P[j]->p.y,
|
||||
c = P[k]->p.x - P[j]->p.x,
|
||||
d = P[k]->p.y - P[j]->p.y;
|
||||
return a * d - b * c <= 0; // true if points i, j, k counterclockwise
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmpl(const void *a, const void *b) { // for convex-hull
|
||||
float v;
|
||||
COLORVERTEX **av, **bv;
|
||||
|
||||
av = (COLORVERTEX **)a;
|
||||
bv = (COLORVERTEX **)b;
|
||||
|
||||
v = (*av)->p.x - (*bv)->p.x;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
v = (*bv)->p.y - (*av)->p.y;
|
||||
|
||||
if (v > 0) return 1;
|
||||
if (v < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int cmph(const void *a, const void *b) {
|
||||
return cmpl(b, a); // for convex-hull
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int make_chain(COLORVERTEX *V[], int n, int (*cmp)(const void *, const void *)) { // for convex-hull
|
||||
int i, j, s = 1;
|
||||
COLORVERTEX *t;
|
||||
|
||||
qsort(V, n, sizeof(COLORVERTEX *), cmp);
|
||||
for (i = 2; i < n; i++) {
|
||||
for (j = s; j >= 1 && ccw(V, i, j, j - 1); j--)
|
||||
{}
|
||||
s = j + 1;
|
||||
t = V[s];
|
||||
V[s] = V[i];
|
||||
V[i] = t;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int ch2d(COLORVERTEX *P[], int n) { // for convex-hull
|
||||
int u = make_chain(P, n, cmpl); // make lower hull
|
||||
if (!n) return 0;
|
||||
P[n] = P[0];
|
||||
return u + make_chain(P + u, n - u + 1, cmph); // make upper hull
|
||||
}
|
||||
|
||||
//************************************************************************************************
|
||||
void Find2DConvexHull(DWORD nverts, COLORVERTEX *pntptr, DWORD *cNumOutIdxs, WORD **OutHullIdxs) { // find a convex hull
|
||||
COLORVERTEX **PntPtrs;
|
||||
DWORD i;
|
||||
|
||||
*cNumOutIdxs = 0; //max space needed is n+1 indices
|
||||
*OutHullIdxs = (WORD *)malloc((nverts + 1) * (sizeof(DWORD) + sizeof(COLORVERTEX *)));
|
||||
|
||||
PntPtrs = (COLORVERTEX **) & (*OutHullIdxs)[nverts + 1];
|
||||
|
||||
// alg requires array of ptrs to verts (for qsort) instead of array of verts, so do the conversion
|
||||
for (i = 0; i < nverts; i++) {
|
||||
PntPtrs[i] = &pntptr[i];
|
||||
}
|
||||
|
||||
*cNumOutIdxs = ch2d(PntPtrs, nverts);
|
||||
|
||||
// convert back to array of idxs
|
||||
for (i = 0; i < *cNumOutIdxs; i++) {
|
||||
(*OutHullIdxs)[i] = (WORD)(PntPtrs[i] - &pntptr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -----------------25/08/1999 16.41-----------------
|
||||
* find 2D convex hull for the object
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeShadowVolume(SHADOWBOX *sb, gVertex *InVerts, DWORD nverts, float lightm[9]) {
|
||||
warning("Stubbed: rMakeShadowVolume");
|
||||
#if 0
|
||||
Matrix4x4 matWorld, matView, matProj, IDmat;
|
||||
DWORD i;
|
||||
HRESULT hr;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
unsigned int AlphaVal = 98;
|
||||
SHADOW *shad = &sb->ShadowsList[sb->NumShadowsList++];
|
||||
|
||||
// Get a ptr to the ID3D object to create materials and/or lights. Note:
|
||||
// the Release() call just serves to decrease the ref count.
|
||||
LPDIRECT3D7 pD3D;
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER7 VB_Proj;
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
|
||||
// xyz+color so we can render them in showshadvol mode
|
||||
|
||||
// Create vertex buffer to hold shadow volumes verts
|
||||
if (shad->VB == NULL) {
|
||||
// now form array of indices that will make the tris
|
||||
ZeroMemory(shad, sizeof(SHADOW));
|
||||
shad->num_objverts = nverts;
|
||||
vbDesc.dwNumVertices = nverts * 2; // *2 to hold top of shadvol for infin light source
|
||||
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &shad->VB, 0)))
|
||||
return hr;
|
||||
|
||||
// alloc enough to hold largest-case shadvol (max # of verts in c-hull is nverts)
|
||||
// (nverts+1)*2 for tri mesh to hold shadvol sides + nverts to hold tri-fan
|
||||
shad->pwShadVolIndices = (WORD *)t3dCalloc(sizeof(WORD) * (nverts + 1) * 2);
|
||||
}
|
||||
|
||||
// create VB_Proj vertex buffer as a target for the vertex-projection operation used to compute
|
||||
// the silhouette
|
||||
vbDesc.dwNumVertices = nverts;
|
||||
vbDesc.dwFVF = D3DFVF_XYZRHW;
|
||||
// even though RHW not used, must specify it or ProcessVerts will not consider this as a valid
|
||||
// target to xform verts into
|
||||
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &VB_Proj, NULL)))
|
||||
return hr;
|
||||
|
||||
// must lock VB, then copy verts into its space.
|
||||
COLORVERTEX *VBvertptr;
|
||||
|
||||
shad->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(VOID **) &VBvertptr, NULL);
|
||||
|
||||
// have to copy verts into VB memory. I reformat into COLORVERTEX to do this.
|
||||
// could prevent reformat and do a straight memcpy if Find2DConvexHull used D3DVERTEX tho.
|
||||
COLORVERTEX *cvptr = VBvertptr;
|
||||
gVertex *d3dvptr = InVerts;
|
||||
|
||||
// reformat D3DVERTEX array to COLORVERTEX array
|
||||
for (i = 0; i < nverts; i++) {
|
||||
cvptr->p.x = d3dvptr->x;
|
||||
cvptr->p.y = d3dvptr->y;
|
||||
cvptr->p.z = d3dvptr->z;
|
||||
cvptr->c = RGBA_MAKE(0xff, 0x0, 0x0, 0xff); // shadvol is semi-transparent black
|
||||
cvptr++;
|
||||
d3dvptr++;
|
||||
}
|
||||
|
||||
shad->VB->Unlock();
|
||||
|
||||
// save cur matrices so we can use xform pipeln to project verts supafast
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
|
||||
|
||||
SetIdentityMatrix(IDmat);
|
||||
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &IDmat);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &IDmat);
|
||||
|
||||
// for view matrix, all we want is anything that projects the verts onto a plane
|
||||
// perp to light direction. so any eyepoint is OK (try to make obj near origin though,
|
||||
// so look at one of the verts). dont care what direction is view up vector (y).
|
||||
rSetViewMatrix(lightm[0], lightm[1], lightm[2],
|
||||
lightm[3], lightm[4], lightm[5],
|
||||
lightm[6], lightm[7], lightm[8],
|
||||
0.0f, 0.0f, 0.0f);
|
||||
|
||||
// do the planar projection
|
||||
VB_Proj->ProcessVertices(D3DVOP_TRANSFORM,
|
||||
0, // write new verts at idx 0
|
||||
nverts,
|
||||
shad->VB,
|
||||
0, // read src verts from idx 0
|
||||
pd3dDevice,
|
||||
0x0); // no flags
|
||||
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
|
||||
|
||||
COLORVERTEX *pntptr;
|
||||
|
||||
VB_Proj->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(void **) &pntptr, NULL);
|
||||
|
||||
WORD *OutHullIdxs;
|
||||
DWORD n_idxs;
|
||||
|
||||
Find2DConvexHull(nverts, pntptr, &n_idxs, &OutHullIdxs); // This is the function supplied with dx6
|
||||
|
||||
VB_Proj->Unlock();
|
||||
VB_Proj->Release(); // just needed the indices of hull
|
||||
|
||||
shad->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(void **) &VBvertptr, NULL);
|
||||
|
||||
// make shadow volume by taking hull verts and project them along light dir far enough
|
||||
// to be offscreen
|
||||
|
||||
// add verts to end of VB
|
||||
for (i = 0; i < n_idxs; i++) {
|
||||
VBvertptr[nverts + i].p.x = VBvertptr[OutHullIdxs[i]].p.x - (2000.0f * lightm[6]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].p.y = VBvertptr[OutHullIdxs[i]].p.y - (2000.0f * lightm[7]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].p.z = VBvertptr[OutHullIdxs[i]].p.z - (2000.0f * lightm[8]); // scale factor of 10 should be enough
|
||||
VBvertptr[nverts + i].c = RGBA_MAKE(0x0, 0xff, 0x0, 0xff);
|
||||
}
|
||||
|
||||
shad->totalverts = nverts + n_idxs;
|
||||
|
||||
// now form array of indices that will make the tris
|
||||
// shad vol will have n_idxs square sides
|
||||
|
||||
shad->num_side_indices = (n_idxs + 1) * 2;
|
||||
|
||||
// if shadvol is not capped, shadow may be drawn in place where a backfacing cap is missing even
|
||||
// though no geometry is there
|
||||
|
||||
//f shad->num_cap_indices=n_idxs;
|
||||
shad->num_cap_indices = 0;
|
||||
|
||||
WORD *idxptr;
|
||||
|
||||
idxptr = shad->pwShadVolSideIndices = shad->pwShadVolIndices;
|
||||
|
||||
// tris for all facets but final one
|
||||
for (i = 0; i < n_idxs; i++) {
|
||||
// outhullidx[i] is the index of the ith vertex of the n_idx convex hull verts
|
||||
// nverts+i is the index of the projected vert corresponding to the OutHullIdx[i] vertex
|
||||
*idxptr++ = OutHullIdxs[i];
|
||||
*idxptr++ = (WORD)(nverts + i);
|
||||
}
|
||||
// add tris for final facet (i==n_idxs)
|
||||
*idxptr++ = OutHullIdxs[0];
|
||||
*idxptr++ = (WORD)(nverts + 0);
|
||||
|
||||
//m shad->pwShadVolCapIndices=idxptr;
|
||||
|
||||
free(OutHullIdxs); // allocated by Find2DConvexHull
|
||||
shad->VB->Unlock();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 16.41-----------------
|
||||
* makes a shadow box to avoid stenciled shadows over the object
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeShadowBox(SHADOWBOX *sb, float BoxX, float BoxY, float BoxZ, WORD intens) {
|
||||
warning("Stubbed: rMakeShadowBox");
|
||||
#if 0
|
||||
bool hr;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
// Get a ptr to the ID3D object to create materials and/or lights. Note:
|
||||
// the Release() call just serves to decrease the ref count.
|
||||
LPDIRECT3D7 pD3D;
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
|
||||
// xyz+color so we can render them in showshadvol mode
|
||||
|
||||
// Create vertex buffer to hold shadow volumes verts
|
||||
if (sb->VB == NULL) {
|
||||
sb->NumVerts = 16;
|
||||
sb->NumIndices = 12 * 3;
|
||||
vbDesc.dwNumVertices = sb->NumVerts;
|
||||
if (FAILED(hr = pD3D->CreateVertexBuffer(&vbDesc, &sb->VB, 0)))
|
||||
return hr;
|
||||
|
||||
// alloc enough to hold largest-case shadvol (max # of verts in c-hull is nverts)
|
||||
// (nverts+1)*2 for tri mesh to hold shadvol sides + nverts to hold tri-fan
|
||||
sb->pwIndices = (WORD *)t3dCalloc(sizeof(WORD) * sb->NumIndices);
|
||||
|
||||
WORD *curind = sb->pwIndices;
|
||||
*curind++ = 0;
|
||||
*curind++ = 1;
|
||||
*curind++ = 2; // Base scura
|
||||
*curind++ = 2;
|
||||
*curind++ = 1;
|
||||
*curind++ = 3;
|
||||
*curind++ = 0;
|
||||
*curind++ = 4;
|
||||
*curind++ = 1; // Bordo sinistro scuro
|
||||
*curind++ = 1;
|
||||
*curind++ = 4;
|
||||
*curind++ = 5;
|
||||
*curind++ = 2;
|
||||
*curind++ = 6;
|
||||
*curind++ = 0; // Bordo destro scuro
|
||||
*curind++ = 0;
|
||||
*curind++ = 6;
|
||||
*curind++ = 4;
|
||||
*curind++ = 12;
|
||||
*curind++ = 13;
|
||||
*curind++ = 14; // Testa chiara
|
||||
*curind++ = 14;
|
||||
*curind++ = 13;
|
||||
*curind++ = 15;
|
||||
*curind++ = 11;
|
||||
*curind++ = 15;
|
||||
*curind++ = 9; // Bordo sinistro chiaro
|
||||
*curind++ = 9;
|
||||
*curind++ = 15;
|
||||
*curind++ = 13;
|
||||
*curind++ = 10;
|
||||
*curind++ = 14;
|
||||
*curind++ = 11; // Bordo destro chiaro
|
||||
*curind++ = 11;
|
||||
*curind++ = 14;
|
||||
*curind++ = 15;
|
||||
}
|
||||
sb->NumShadowsList = 0;
|
||||
sb->Intensity = intens;
|
||||
|
||||
// must lock VB, then copy verts into its space.
|
||||
COLORVERTEX *VBvertptr;
|
||||
sb->VB->Lock(DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
|
||||
(VOID **) &VBvertptr, NULL);
|
||||
|
||||
// have to copy verts into VB memory. I reformat into COLORVERTEX to do this.
|
||||
// could prevent reformat and do a straight memcpy if Find2DConvexHull used D3DVERTEX tho.
|
||||
COLORVERTEX *cvptr = VBvertptr;
|
||||
D3DCOLOR cshadow = RGBA_MAKE(0x0, 0x0, 0x0, intens);
|
||||
D3DCOLOR clight = RGBA_MAKE(0x0, 0x0, 0x0, 0);
|
||||
|
||||
// 0: Base Piu' distante scuro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 1: Base Sinistra scuro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 2: Base Destra scuro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 3: Base Piu' vicino scuro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 4: Testa Piu' distante scura
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 5: Testa Sinistra scuro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 6: Testa Destra scuro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 7: Testa Piu' vicino scuro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = cshadow;
|
||||
cvptr ++;
|
||||
// 8: Base Piu' distante chiaro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 9: Base Sinistra chiaro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 10: Base Destra chiaro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 11: Base Piu' vicino chiaro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = 5.0f;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 12: Testa Piu' distante chiaro
|
||||
cvptr->p.x = BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 13: Testa Sinistra chiaro
|
||||
cvptr->p.x = -BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 14: Testa Destra chiaro
|
||||
cvptr->p.x = BoxZ;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxX;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
// 15: Testa Piu' vicino chiaro
|
||||
cvptr->p.x = -BoxX;
|
||||
cvptr->p.y = BoxY;
|
||||
cvptr->p.z = -BoxZ;
|
||||
cvptr->c = clight;
|
||||
cvptr ++;
|
||||
|
||||
sb->VB->Unlock();
|
||||
|
||||
ShadowBoxesList[gNumShadowBoxesList++] = sb;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.24-----------------
|
||||
* renders a stenciled convex hull
|
||||
* --------------------------------------------------*/
|
||||
bool RenderShadow(SHADOW *pShad,
|
||||
void *lpVBuf) {
|
||||
warning("TODO: Stubbed RenderShadow");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetTexture(0, NULL);
|
||||
|
||||
// Turn depth buffer off, and stencil buffer on
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT); // dont want to bother interpolating color
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW);
|
||||
|
||||
// Set up stencil compare fuction, reference value, and masks
|
||||
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
|
||||
|
||||
if (g_bUseOneBitStencil) {
|
||||
// If ztest passes, write !(g_bInvertStencilBufferSense) into stencil buffer
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILMASK, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILWRITEMASK, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_REPLACE);
|
||||
} else {
|
||||
// If ztest passes, inc/decrement stencil buffer value
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILMASK, 0xffffffff);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILWRITEMASK, 0xffffffff);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, g_StencIncOp);
|
||||
}
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this should result in the tri color being completely dropped
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
|
||||
|
||||
// draw front-side of shadow volume in stencil/z only
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLESTRIP, lpVBuf, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0);
|
||||
|
||||
// Now reverse cull order so back sides of shadow volume are written.
|
||||
if (g_bUseOneBitStencil) {
|
||||
// write 0's/1's into stencil buffer to erase pixels beyond back of shadow
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x0);
|
||||
} else {
|
||||
// increment stencil buffer value
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, g_StencDecOp);
|
||||
}
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
|
||||
// Draw back-side of shadow volume in stencil/z only
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLESTRIP, lpVBuf, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
//f pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.25-----------------
|
||||
* renders an object stenciled shadows box
|
||||
* --------------------------------------------------*/
|
||||
bool RenderShadowBox(SHADOWBOX *pSB,
|
||||
int lpVBuf) {
|
||||
warning("TODO: RenderShadowBox");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetTexture(0, NULL);
|
||||
|
||||
// Turn depth buffer off, and stencil buffer on
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
||||
|
||||
// Set up stencil compare fuction, reference value, and masks
|
||||
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_LESSEQUAL);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_ZERO);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_ZERO);
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this should result in the tri color being completely dropped
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, lpVBuf, 0, pSB->NumVerts,
|
||||
pSB->pwIndices,
|
||||
pSB->NumIndices, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.25-----------------
|
||||
* Name: DrawShadow()
|
||||
* Desc: Draws a big grey polygon over scene, and blend it with pixels with
|
||||
* stencil 1, which are in shadow. Could optimize this by keeping track
|
||||
* of rendered 2D extent rect of all shadow vols.
|
||||
* --------------------------------------------------*/
|
||||
bool DrawShadow(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, WORD intens) {
|
||||
warning("Stubbed: DrawShadow");
|
||||
#if 0
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE);
|
||||
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
||||
|
||||
// Since destcolor=SRCBLEND * SRC_COLOR + DESTBLEND * DEST_COLOR,
|
||||
// this results in destcolor= (AlphaSrc) * SRC_COLOR + (1-AlphaSrc)*DestColor
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
// stencil cmp func is defined as (ref cmpfn stencbufval).
|
||||
|
||||
// Only write where stencil val >= 1. (count indicates # of shadows that overlap that pixel)
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, 0x1);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, D3DCMP_LESSEQUAL);
|
||||
|
||||
//f pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP );
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_ZERO);
|
||||
|
||||
// Set the world matrix to identity to draw the big grey square
|
||||
D3DMATRIX matWorld, matIdentity;
|
||||
pd3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
SetIdentityMatrix(matIdentity);
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matIdentity);
|
||||
// pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matIdentity );
|
||||
// pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matIdentity );
|
||||
|
||||
TRANSCOLORVERTEX sqverts[4];
|
||||
WORD sqindices[6];
|
||||
|
||||
sqverts[0].p.z = sqverts[1].p.z = sqverts[2].p.z = sqverts[3].p.z = 0.0f;
|
||||
sqverts[0].rhw = sqverts[1].rhw = sqverts[3].rhw = sqverts[3].rhw = 0.0f;
|
||||
sqverts[0].c = sqverts[1].c = sqverts[2].c = sqverts[3].c = RGBA_MAKE(0x0, 0x0, 0x0, intens);
|
||||
|
||||
sqindices[0] = 0;
|
||||
sqindices[1] = 2;
|
||||
sqindices[2] = 1;
|
||||
sqindices[3] = 0;
|
||||
sqindices[4] = 3;
|
||||
sqindices[5] = 2;
|
||||
|
||||
sqverts[0].p.x = (float)x1;
|
||||
sqverts[0].p.y = (float)y1;
|
||||
sqverts[1].p.x = (float)x2;
|
||||
sqverts[1].p.y = (float)y1;
|
||||
sqverts[2].p.x = (float)x2;
|
||||
sqverts[2].p.y = (float)y2;
|
||||
sqverts[3].p.x = (float)x1;
|
||||
sqverts[3].p.y = (float)y2;
|
||||
|
||||
pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, (D3DFVF_XYZRHW | D3DFVF_DIFFUSE),
|
||||
sqverts, 4, sqindices, 6, 0x0);
|
||||
|
||||
// Restore render states
|
||||
pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
|
||||
pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.28-----------------
|
||||
* prepare shadow for projection to a texture
|
||||
* --------------------------------------------------*/
|
||||
bool rMakeProjectiveShadow(SHADOWBOX *sb, void *InVerts, DWORD nverts) {
|
||||
warning("Stubbed. rMakeProjectiveShadow");
|
||||
#if 0
|
||||
SHADOW *shad = &sb->ShadowsList[0];
|
||||
D3DVERTEXBUFFERDESC vbDesc;
|
||||
LPDIRECT3D7 pD3D;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
int pos;
|
||||
|
||||
if (shad->VB == NULL) {
|
||||
pd3dDevice->GetDirect3D(&pD3D);
|
||||
pD3D->Release();
|
||||
vbDesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
|
||||
vbDesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
|
||||
vbDesc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
|
||||
|
||||
// now form array of indices that will make the tris
|
||||
shad->num_objverts = nverts;
|
||||
vbDesc.dwNumVertices = nverts; // *2 to hold top of shadvol for infin light source
|
||||
|
||||
if (FAILED(pD3D->CreateVertexBuffer(&vbDesc, &shad->VB, 0))) {
|
||||
DebugLogFile("Unable to create VertexBuffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//Alloc indices for triangles
|
||||
shad->pwShadVolSideIndices = (WORD *)t3dCalloc(sizeof(WORD) * (nverts + 1) * 3);
|
||||
}
|
||||
|
||||
if (!g_pddsShadowBuffer) {
|
||||
HRESULT LastError;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
|
||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||||
memcpy(&ddsd, &GraphicsModes[gCurrGraphicsMode].SurfDesc, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE;
|
||||
|
||||
ddsd.dwWidth = 256;
|
||||
ddsd.dwHeight = 256;
|
||||
|
||||
g_pddsShadowBuffer = gCreateSurface(&ddsd, g_pddsShadowBuffer);
|
||||
if (!g_pddsShadowBuffer) {
|
||||
DebugLogFile("Unable to create ShadowBuffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||||
g_pddsZBuffer->GetSurfaceDesc(&ddsd);
|
||||
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
|
||||
ddsd.dwWidth = 256;
|
||||
ddsd.dwHeight = 256;
|
||||
|
||||
g_pddsShadowZBuffer = gCreateSurface(&ddsd, g_pddsZBuffer);
|
||||
if (!g_pddsShadowZBuffer) {
|
||||
char str[200];
|
||||
LastError = 0;
|
||||
GetDDErrorString(LastError, str, 1);
|
||||
|
||||
DebugLogFile("CreateSurface for ShadowBuffer Z-buffer failed.\r\n%s", str);
|
||||
return FALSE;
|
||||
}
|
||||
LastError = g_pddsShadowBuffer->AddAttachedSurface(g_pddsShadowZBuffer);
|
||||
if (LastError != DD_OK) {
|
||||
char str[200];
|
||||
GetDDErrorString(LastError, str, 1);
|
||||
DebugLogFile("AddAttachedBuffer To ShadowBuffer failed for Z-Buffer.%s", str);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shad->ProjectiveTexture.lpDDSurface) {
|
||||
DDSURFACEDESC2 DDSurfDesc;
|
||||
memset(&DDSurfDesc, 0, sizeof(DDSURFACEDESC2));
|
||||
memcpy(&DDSurfDesc.ddpfPixelFormat, &gCurrentFormat->SurfaceDesc, sizeof(DDPIXELFORMAT));
|
||||
memcpy(&DDSurfDesc, &GraphicsModes[gCurrGraphicsMode].SurfDesc, sizeof(DDSURFACEDESC2));
|
||||
DDSurfDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
||||
if (gRenderFlags & gAGPSUPPORTED) {
|
||||
//Alloc texture in AGP
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
|
||||
DDSCAPS_TEXTURE;
|
||||
} else {
|
||||
//No AGP support; alloc in sysmem
|
||||
DDSurfDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
DDSurfDesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
|
||||
}
|
||||
DDSurfDesc.dwWidth = 256;
|
||||
DDSurfDesc.dwHeight = 256;
|
||||
if (!(shad->ProjectiveTexture.lpDDSurface = gCreateSurface(&DDSurfDesc, shad->ProjectiveTexture.lpDDSurface))) {
|
||||
DebugLogFile("rMakeProjectiveShadow: gCreateSurface FAILED: Can't create surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pos = gGetTextureListPosition();
|
||||
if (pos == 0) {
|
||||
DebugLogFile("rMakeProjectiveShadow: Can't create more textures");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&gTextureList[pos], 0, sizeof(gTexture));
|
||||
strcpy(gTextureList[pos].Name, "Texture Buffer Shadow");
|
||||
gTextureList[pos].lpDDSurface = shad->ProjectiveTexture.lpDDSurface;
|
||||
gTextureList[pos].RealDimX = 256;
|
||||
gTextureList[pos].RealDimY = 256;
|
||||
gTextureList[pos].DimX = 256;
|
||||
gTextureList[pos].DimY = 256;
|
||||
gTextureList[pos].Flags = CurLoaderFlags;
|
||||
}
|
||||
|
||||
ShadowBoxesList[gNumShadowBoxesList++] = sb;
|
||||
sb->NumShadowsList = 1;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.28-----------------
|
||||
* renders shadow to a specific texture
|
||||
* --------------------------------------------------*/
|
||||
bool RenderProjectiveShadow(SHADOW *pShad) {
|
||||
warning("Stubbed. RenderPojectiveShadow");
|
||||
#if 0
|
||||
HRESULT hres;
|
||||
LPDIRECT3DDEVICE7 pd3dDevice = g_pd3dDevice;
|
||||
LPDIRECTDRAWSURFACE7 OldRenderTarget;
|
||||
D3DVIEWPORT7 NewViewport;
|
||||
|
||||
memset(&gOldViewport, 0, sizeof(D3DVIEWPORT7));
|
||||
if (hres = pd3dDevice->GetViewport(&gOldViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to get ViewPort2");
|
||||
return hres;
|
||||
}
|
||||
memcpy(&NewViewport, &gOldViewport, sizeof(D3DVIEWPORT7));
|
||||
|
||||
if (hres = pd3dDevice->GetRenderTarget(&OldRenderTarget) != D3D_OK) {
|
||||
DebugLogFile("Can't GetRenderTarget for shadow");
|
||||
return hres;
|
||||
}
|
||||
if (hres = pd3dDevice->SetRenderTarget(g_pddsShadowBuffer, 0) != D3D_OK) {
|
||||
DebugLogFile("Can't SetRenderTarget for shadow");
|
||||
return hres;
|
||||
}
|
||||
|
||||
NewViewport.dwHeight = NewViewport.dwWidth = 256;
|
||||
if (hres = pd3dDevice->SetViewport(&NewViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to set ShadowBuffer viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
D3DRECT rect;
|
||||
rect.x1 = rect.y1 = 0;
|
||||
rect.x2 = 256;
|
||||
rect.y2 = 256;
|
||||
if (hres = pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0) != D3D_OK) {
|
||||
DebugLogFile("Unable to clear2 ShadowBuffer viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->BeginScene() != D3D_OK) {
|
||||
DebugLogFile("Unable to begin Shadow scene");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetTexture(0, NULL)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, D3DZB_FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT)) return hres; // dont want to bother interpolating color
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO)) return hres;
|
||||
|
||||
if (hres = pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, pShad->VB, 0, pShad->totalverts,
|
||||
pShad->pwShadVolSideIndices,
|
||||
pShad->num_side_indices, 0x0) != D3D_OK) {
|
||||
DebugLogFile("Unable to DrawIndexedPrimitive for projected shadow");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->EndScene() != D3D_OK) {
|
||||
DebugLogFile("Unable to end shadow scene");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderTarget(OldRenderTarget, 0) != D3D_OK) {
|
||||
DebugLogFile("Can't SetRenderTarget for shadows");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetViewport(&gOldViewport) != D3D_OK) {
|
||||
DebugLogFile("Unable to restore viewport");
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, D3DZB_TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE)) return hres;
|
||||
if (hres = pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE)) return hres;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -----------------25/08/1999 17.31-----------------
|
||||
* draw projected shadow texture to the room
|
||||
* --------------------------------------------------*/
|
||||
bool DrawProjectiveShadow(SHADOW *pShad) {
|
||||
warning("Stubbed: DrawProjectiveShadow");
|
||||
#if 0
|
||||
bool hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCCOLOR) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetTexture(0, pShad->ProjectiveTexture.lpDDSurface) != DD_OK) return hres;
|
||||
|
||||
if (hres = g_pd3dDevice->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST,
|
||||
pShad->ProjVertsVB, 0, pShad->totalverts,
|
||||
pShad->pwShadVolCapIndices,
|
||||
pShad->num_cap_indices, 0x0) != DD_OK) {
|
||||
char str[255];
|
||||
GetDDErrorString(hres, str, 1);
|
||||
DebugLogFile("DrawIndexedPrimitiveVB ERROR:\n\r%s", str);
|
||||
}
|
||||
pShad->num_cap_indices = 0;
|
||||
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP) != DD_OK) return hres;
|
||||
if (hres = g_pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE) != DD_OK) return hres;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
44
engines/watchmaker/3d/render/shadows.h
Normal file
44
engines/watchmaker/3d/render/shadows.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHMAKER_SHADOWS_H
|
||||
#define WATCHMAKER_SHADOWS_H
|
||||
|
||||
#include "watchmaker/render.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
extern SHADOWBOX *ShadowBoxesList[];
|
||||
extern unsigned int gNumShadowBoxesList;
|
||||
extern void *g_pddsShadowBuffer;
|
||||
extern void *g_pddsShadowZBuffer;
|
||||
|
||||
//extern D3DSTENCILOP g_StencDecOp,g_StencIncOp;
|
||||
bool RenderShadow(SHADOW *pShad, void *lpVBuf);
|
||||
bool RenderShadowBox(SHADOWBOX *pSB, int VBO);
|
||||
bool DrawShadow(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, WORD intens);
|
||||
extern DWORD g_max_StencilVal; // maximum value the stencil buffer will hold
|
||||
extern bool RenderProjectiveShadow(SHADOW *pShad);
|
||||
bool DrawProjectiveShadow(SHADOW *pShad);
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
|
||||
#endif // WATCHMAKER_SHADOWS_H
|
||||
Reference in New Issue
Block a user