mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 17:33:05 +00:00
959 lines
27 KiB
C++
959 lines
27 KiB
C++
/* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "graphics/surface.h"
|
|
#include "allfiles.h"
|
|
#include "fileset.h"
|
|
#include "people.h"
|
|
#include "sprites.h"
|
|
#include "moreio.h"
|
|
#include "newfatal.h"
|
|
#include "colours.h"
|
|
#include "backdrop.h"
|
|
#include "sludger.h"
|
|
#include "zbuffer.h"
|
|
#include "debug.h"
|
|
#include "graphics.h"
|
|
#include "imgloader.h"
|
|
#include "shaders.h"
|
|
|
|
namespace Sludge {
|
|
|
|
extern zBufferData zBuffer;
|
|
|
|
#if 0
|
|
extern GLuint backdropTextureName;
|
|
#endif
|
|
|
|
extern inputType input;
|
|
extern int cameraX, cameraY;
|
|
extern float cameraZoom;
|
|
|
|
unsigned char currentBurnR = 0, currentBurnG = 0, currentBurnB = 0;
|
|
|
|
void forgetSpriteBank(spriteBank &forgetme) {
|
|
#if 0
|
|
deleteTextures(forgetme.myPalette.numTextures, forgetme.myPalette.tex_names);
|
|
if (forgetme.isFont) {
|
|
deleteTextures(forgetme.myPalette.numTextures, forgetme.myPalette.burnTex_names);
|
|
delete [] forgetme.myPalette.burnTex_names;
|
|
forgetme.myPalette.burnTex_names = NULL;
|
|
}
|
|
|
|
delete [] forgetme.myPalette.tex_names;
|
|
forgetme.myPalette.tex_names = NULL;
|
|
delete[] forgetme.myPalette.tex_w;
|
|
forgetme.myPalette.tex_w = NULL;
|
|
delete[] forgetme.myPalette.tex_h;
|
|
forgetme.myPalette.tex_h = NULL;
|
|
#endif
|
|
if (forgetme.myPalette.pal) {
|
|
delete[] forgetme.myPalette.pal;
|
|
forgetme.myPalette.pal = NULL;
|
|
delete[] forgetme.myPalette.r;
|
|
forgetme.myPalette.r = NULL;
|
|
delete[] forgetme.myPalette.g;
|
|
forgetme.myPalette.g = NULL;
|
|
delete[] forgetme.myPalette.b;
|
|
forgetme.myPalette.b = NULL;
|
|
}
|
|
|
|
delete forgetme.sprites;
|
|
forgetme.sprites = NULL;
|
|
|
|
// TODO: also remove sprite bank from allLoadedBanks
|
|
// And add a function call for this function to the scripting language
|
|
}
|
|
|
|
bool reserveSpritePal(spritePalette &sP, int n) {
|
|
if (sP.pal) {
|
|
delete[] sP.pal;
|
|
delete[] sP.r;
|
|
delete[] sP.g;
|
|
delete[] sP.b;
|
|
}
|
|
|
|
sP.pal = new unsigned short int[n];
|
|
if (!checkNew(sP.pal))
|
|
return false;
|
|
|
|
sP.r = new unsigned char[n];
|
|
if (!checkNew(sP.r))
|
|
return false;
|
|
sP.g = new unsigned char[n];
|
|
if (!checkNew(sP.g))
|
|
return false;
|
|
sP.b = new unsigned char[n];
|
|
if (!checkNew(sP.b))
|
|
return false;
|
|
sP.total = n;
|
|
return (bool) (sP.pal != NULL) && (sP.r != NULL) && (sP.g != NULL)
|
|
&& (sP.b != NULL);
|
|
}
|
|
|
|
bool loadSpriteBank(int fileNum, spriteBank &loadhere, bool isFont) {
|
|
|
|
int total, picwidth, picheight, spriteBankVersion = 0, howmany = 0, startIndex = 0;
|
|
byte *data;
|
|
|
|
setResourceForFatal(fileNum);
|
|
if (!openFileFromNum(fileNum)) return fatal("Can't open sprite bank / font");
|
|
|
|
loadhere.isFont = isFont;
|
|
|
|
total = bigDataFile->readUint16BE();
|
|
if (!total) {
|
|
spriteBankVersion = bigDataFile->readByte();
|
|
if (spriteBankVersion == 1) {
|
|
total = 0;
|
|
} else {
|
|
total = bigDataFile->readUint16BE();
|
|
}
|
|
}
|
|
|
|
if (total <= 0) return fatal("No sprites in bank or invalid sprite bank file");
|
|
if (spriteBankVersion > 3) return fatal("Unsupported sprite bank file format");
|
|
|
|
loadhere.total = total;
|
|
loadhere.sprites = new sprite [total];
|
|
if (! checkNew(loadhere.sprites)) return false;
|
|
byte **spriteData = new byte * [total];
|
|
if (! checkNew(spriteData)) return false;
|
|
|
|
// version 1, 2, read how many now
|
|
if (spriteBankVersion && spriteBankVersion < 3) {
|
|
howmany = bigDataFile->readByte();
|
|
startIndex = 1;
|
|
}
|
|
|
|
// version 3, sprite is png
|
|
if (spriteBankVersion == 3) {
|
|
for (int i = 0; i < total; i ++) {
|
|
howmany = bigDataFile->readByte();
|
|
startIndex = 1;
|
|
|
|
loadhere.sprites[i].xhot = getSigned(bigDataFile);
|
|
loadhere.sprites[i].yhot = getSigned(bigDataFile);
|
|
|
|
if (!ImgLoader::loadPNGImage(bigDataFile, &loadhere.sprites[i].surface)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// version 0, 1, 2
|
|
for (int i = 0; i < total; i ++) {
|
|
// load sprite width, height, relative position
|
|
if (spriteBankVersion == 2) {
|
|
picwidth = bigDataFile->readUint16BE();
|
|
picheight = bigDataFile->readUint16BE();
|
|
loadhere.sprites[i].xhot = getSigned(bigDataFile);
|
|
loadhere.sprites[i].yhot = getSigned(bigDataFile);
|
|
} else {
|
|
picwidth = (byte)bigDataFile->readByte();
|
|
picheight = (byte)bigDataFile->readByte();
|
|
loadhere.sprites[i].xhot = bigDataFile->readByte();
|
|
loadhere.sprites[i].yhot = bigDataFile->readByte();
|
|
}
|
|
|
|
// init data
|
|
data = (byte *)new byte[picwidth * (picheight + 1)];
|
|
if (!checkNew(data)) return false;
|
|
int ooo = picwidth * picheight;
|
|
for (int tt = 0; tt < picwidth; tt++) {
|
|
data[ooo++] = 0;
|
|
}
|
|
spriteData[i] = data;
|
|
|
|
// read color
|
|
if (spriteBankVersion == 2) {
|
|
unsigned size = picwidth * picheight;
|
|
unsigned pip = 0;
|
|
|
|
while (pip < size) {
|
|
byte col = bigDataFile->readByte();
|
|
int looper;
|
|
if (col > howmany) {
|
|
col -= howmany + 1;
|
|
looper = bigDataFile->readByte() + 1;
|
|
} else looper = 1;
|
|
|
|
while (looper --) {
|
|
data[pip ++] = col;
|
|
}
|
|
}
|
|
} else { // RAW DATA
|
|
size_t bytes_read = bigDataFile->read(data, picwidth * picheight);
|
|
if (bytes_read != picwidth * picheight && bigDataFile->err()) {
|
|
debugOut("Reading error in loadSpriteBank.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
// read howmany for version 0
|
|
if (!spriteBankVersion) {
|
|
howmany = bigDataFile->readByte();
|
|
startIndex = bigDataFile->readByte();
|
|
}
|
|
|
|
// Make palette for version 0, 1, 2
|
|
if (!reserveSpritePal(loadhere.myPalette, howmany + startIndex)) return false;
|
|
for (int i = 0; i < howmany; ++i) {
|
|
loadhere.myPalette.r[i + startIndex] = (byte)bigDataFile->readByte();
|
|
loadhere.myPalette.g[i + startIndex] = (byte)bigDataFile->readByte();
|
|
loadhere.myPalette.b[i + startIndex] = (byte)bigDataFile->readByte();
|
|
loadhere.myPalette.pal[i + startIndex] = makeColour(loadhere.myPalette.r[i + startIndex], loadhere.myPalette.g[i + startIndex], loadhere.myPalette.b[i + startIndex]);
|
|
}
|
|
loadhere.myPalette.originalRed = loadhere.myPalette.originalGreen = loadhere.myPalette.originalBlue = 255;
|
|
|
|
// convert
|
|
for (int i = 0; i < total; i ++) {
|
|
int fromhere = 0;
|
|
int transColour = -1;
|
|
int size = picwidth * picheight;
|
|
while (fromhere < size) {
|
|
unsigned char s = spriteData[i][fromhere++];
|
|
if (s) {
|
|
transColour = s;
|
|
break;
|
|
}
|
|
}
|
|
fromhere = 0;
|
|
|
|
loadhere.sprites[i].surface.create(picwidth, picheight, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
|
|
for (int y = 0; y < picheight; y++) {
|
|
for (int x = 0; x < picwidth; x ++) {
|
|
byte *target = (byte *)loadhere.sprites[i].surface.getBasePtr(x, y);
|
|
if (spriteBankVersion < 3) {
|
|
unsigned char s = spriteData[i][fromhere++];
|
|
if (s) {
|
|
target[0] = (byte)255;
|
|
target[1] = (byte)loadhere.myPalette.b[s];
|
|
target[2] = (byte)loadhere.myPalette.g[s];
|
|
target[3] = (byte)loadhere.myPalette.r[s];
|
|
transColour = s;
|
|
} else if (transColour >= 0) {
|
|
target[0] = (byte)0;
|
|
target[1] = (byte)loadhere.myPalette.b[transColour];
|
|
target[2] = (byte)loadhere.myPalette.g[transColour];
|
|
target[3] = (byte)loadhere.myPalette.r[transColour];
|
|
}
|
|
if (isFont) {
|
|
target = (byte *)loadhere.sprites[i].surface.getBasePtr(x, y);
|
|
if (s)
|
|
target[0] = loadhere.myPalette.r[s];
|
|
target[1] = (byte)255;
|
|
target[2] = (byte)255;
|
|
target[3] = (byte)255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete[] spriteData[i];
|
|
}
|
|
delete[] spriteData;
|
|
spriteData = NULL;
|
|
|
|
finishAccess();
|
|
|
|
setResourceForFatal(-1);
|
|
|
|
return true;
|
|
}
|
|
|
|
void pasteSpriteToBackDrop(int x1, int y1, sprite &single,
|
|
const spritePalette &fontPal) {
|
|
#if 0
|
|
float tx1 = (float)(single.tex_x) / fontPal.tex_w[single.texNum];
|
|
float ty1 = 0.0;
|
|
float tx2 = (float)(single.tex_x + single.width) / fontPal.tex_w[single.texNum];
|
|
float ty2 = (float)(single.height) / fontPal.tex_h[single.texNum];
|
|
|
|
float btx1;
|
|
float btx2;
|
|
float bty1;
|
|
float bty2;
|
|
|
|
int diffX = single.width;
|
|
int diffY = single.height;
|
|
|
|
x1 -= single.xhot;
|
|
y1 -= single.yhot;
|
|
|
|
if (! NPOT_textures) {
|
|
btx1 = backdropTexW * x1 / sceneWidth;
|
|
btx2 = backdropTexW * (x1 + single.width) / sceneWidth;
|
|
bty1 = backdropTexH * y1 / sceneHeight;
|
|
bty2 = backdropTexH * (y1 + single.height) / sceneHeight;
|
|
} else {
|
|
btx1 = (float) x1 / sceneWidth;
|
|
btx2 = (float)(x1 + single.width) / sceneWidth;
|
|
bty1 = (float) y1 / sceneHeight;
|
|
bty2 = (float)(y1 + single.height) / sceneHeight;
|
|
}
|
|
|
|
const GLfloat btexCoords[] = {
|
|
btx1, bty1,
|
|
btx2, bty1,
|
|
btx1, bty2,
|
|
btx2, bty2
|
|
};
|
|
|
|
if (x1 < 0) diffX += x1;
|
|
if (y1 < 0) diffY += y1;
|
|
if (x1 + diffX > sceneWidth) diffX = sceneWidth - x1;
|
|
if (y1 + diffY > sceneHeight) diffY = sceneHeight - y1;
|
|
if (diffX < 0) return;
|
|
if (diffY < 0) return;
|
|
|
|
setPixelCoords(true);
|
|
|
|
int xoffset = 0;
|
|
while (xoffset < diffX) {
|
|
int w = (diffX - xoffset < viewportWidth) ? diffX - xoffset : viewportWidth;
|
|
|
|
int yoffset = 0;
|
|
while (yoffset < diffY) {
|
|
int h = (diffY - yoffset < viewportHeight) ? diffY - yoffset : viewportHeight;
|
|
|
|
// Render the sprite to the backdrop
|
|
// (using mulitexturing, so the backdrop is seen where alpha < 1.0)
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, backdropTextureName);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glUseProgram(shader.paste);
|
|
GLint uniform = glGetUniformLocation(shader.paste, "useLightTexture");
|
|
if (uniform >= 0) glUniform1i(uniform, 0);// No lighting
|
|
|
|
setPMVMatrix(shader.paste);
|
|
|
|
setPrimaryColor(fontPal.originalRed / 255.f, fontPal.originalGreen / 255.f, fontPal.originalBlue / 255.f, 1.0f);
|
|
glBindTexture(GL_TEXTURE_2D, fontPal.tex_names[single.texNum]);
|
|
//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
const GLfloat vertices[] = {
|
|
(GLfloat) - xoffset, (GLfloat) - yoffset, 0.,
|
|
(GLfloat)single.width - xoffset, (GLfloat) - yoffset, 0.,
|
|
(GLfloat) - xoffset, (GLfloat)single.height - yoffset, 0.,
|
|
(GLfloat)single.width - xoffset, (GLfloat)single.height - yoffset, 0.
|
|
};
|
|
|
|
const GLfloat texCoords[] = {
|
|
tx1, ty1,
|
|
tx2, ty1,
|
|
tx1, ty2,
|
|
tx2, ty2
|
|
};
|
|
|
|
drawQuad(shader.paste, vertices, 3, texCoords, NULL, btexCoords);
|
|
|
|
// Copy Our ViewPort To The Texture
|
|
glUseProgram(0);
|
|
|
|
copyTexSubImage2D(GL_TEXTURE_2D, 0, (int)((x1 < 0) ? xoffset : x1 + xoffset), (int)((y1 < 0) ? yoffset : y1 + yoffset), (int)((x1 < 0) ? viewportOffsetX - x1 : viewportOffsetX), (int)((y1 < 0) ? viewportOffsetY - y1 : viewportOffsetY), w, h, backdropTextureName);
|
|
|
|
yoffset += viewportHeight;
|
|
}
|
|
xoffset += viewportWidth;
|
|
}
|
|
#endif
|
|
setPixelCoords(false);
|
|
}
|
|
|
|
void burnSpriteToBackDrop(int x1, int y1, sprite &single,
|
|
const spritePalette &fontPal) {
|
|
#if 0
|
|
float tx1 = (float)(single.tex_x - 0.5) / fontPal.tex_w[single.texNum];
|
|
float ty1 = 0.0;
|
|
float tx2 = (float)(single.tex_x + single.width + 0.5) / fontPal.tex_w[single.texNum];
|
|
float ty2 = (float)(single.height + 2) / fontPal.tex_h[single.texNum];
|
|
|
|
const GLfloat spriteTexCoords[] = {
|
|
tx1, ty1,
|
|
tx2, ty1,
|
|
tx1, ty2,
|
|
tx2, ty2
|
|
};
|
|
|
|
x1 -= single.xhot;
|
|
y1 -= single.yhot - 1;
|
|
|
|
float bx1 = (float)x1 * backdropTexW / sceneWidth;
|
|
float by1 = (float)y1 * backdropTexH / sceneHeight;
|
|
float bx2 = (float)(x1 + single.width - 1) * backdropTexW / sceneWidth;
|
|
float by2 = (float)(y1 + single.height - 1) * backdropTexH / sceneHeight;
|
|
|
|
const GLfloat backdropTexCoords[] = {
|
|
bx1, by1,
|
|
bx2, by1,
|
|
bx1, by2,
|
|
bx2, by2
|
|
};
|
|
|
|
const GLfloat backdropTexCoords2[] = {
|
|
0.0f, 0.0f,
|
|
backdropTexW, 0.0f,
|
|
0.0f, backdropTexH,
|
|
backdropTexW, backdropTexH
|
|
};
|
|
|
|
int diffX = single.width + 1;
|
|
int diffY = single.height + 2;
|
|
|
|
if (x1 < 0) diffX += x1;
|
|
if (y1 < 0) diffY += y1;
|
|
if (x1 + diffX > sceneWidth) diffX = sceneWidth - x1;
|
|
if (y1 + diffY > sceneHeight) diffY = sceneHeight - y1;
|
|
if (diffX < 0) return;
|
|
if (diffY < 0) return;
|
|
|
|
setPixelCoords(true);
|
|
setPrimaryColor(currentBurnR / 255.f, currentBurnG / 255.f, currentBurnB / 255.f, 1.0f);
|
|
|
|
GLfloat xoffset = 0.0f;
|
|
while (xoffset < diffX) {
|
|
int w = (diffX - xoffset < viewportWidth) ? diffX - xoffset : viewportWidth;
|
|
|
|
GLfloat yoffset = 0.0f;
|
|
while (yoffset < diffY) {
|
|
int h = (diffY - yoffset < viewportHeight) ? diffY - yoffset : viewportHeight;
|
|
|
|
const GLfloat backdropVertices[] = {
|
|
-x1 - xoffset, -y1 + yoffset, 0.0f,
|
|
sceneWidth - 1.0f - x1 - xoffset, -y1 + yoffset, 0.0f,
|
|
-x1 - xoffset, sceneHeight - 1.0f - y1 + yoffset, 0.0f,
|
|
sceneWidth - 1.0f - x1 - xoffset, sceneHeight - 1.0f - y1 + yoffset, 0.0f
|
|
};
|
|
|
|
const GLfloat spriteVertices[] = {
|
|
-xoffset, -yoffset, 0.0f,
|
|
single.width - 1 - xoffset, -yoffset, 0.0f,
|
|
-xoffset, single.height - 1 - yoffset, 0.0f,
|
|
single.width - 1 - xoffset, single.height - 1 - yoffset, 0.0f
|
|
};
|
|
|
|
glBindTexture(GL_TEXTURE_2D, backdropTextureName);
|
|
glUseProgram(shader.texture);
|
|
setPMVMatrix(shader.texture);
|
|
|
|
drawQuad(shader.texture, backdropVertices, 1, backdropTexCoords2);
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, backdropTextureName);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glUseProgram(shader.paste);
|
|
GLint uniform = glGetUniformLocation(shader.paste, "useLightTexture");
|
|
if (uniform >= 0) glUniform1i(uniform, 0); // No lighting
|
|
|
|
setPMVMatrix(shader.paste);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, fontPal.burnTex_names[single.texNum]);
|
|
|
|
//FIXME: Test this some more. Also pasting the backdrop again is not strictly necessary but allows using the paste shader.
|
|
drawQuad(shader.paste, spriteVertices, 3, spriteTexCoords, NULL, backdropTexCoords);
|
|
glUseProgram(0);
|
|
|
|
// Copy Our ViewPort To The Texture
|
|
copyTexSubImage2D(GL_TEXTURE_2D, 0, (x1 < 0) ? xoffset : x1 + xoffset, (y1 < 0) ? yoffset : y1 + yoffset, viewportOffsetX, viewportOffsetY, w, h, backdropTextureName);
|
|
|
|
yoffset += viewportHeight;
|
|
}
|
|
xoffset += viewportWidth;
|
|
}
|
|
setPixelCoords(false);
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
extern GLuint backdropTextureName;
|
|
#endif
|
|
|
|
void fontSprite(bool flip, int x, int y, sprite &single,
|
|
const spritePalette &fontPal) {
|
|
#if 0
|
|
float tx1 = (float) (single.tex_x - 0.5) / fontPal.tex_w[single.texNum];
|
|
float ty1 = 0.0;
|
|
float tx2 = (float) (single.tex_x + single.width + (flip ? 1.0 : 0.5))
|
|
/ fontPal.tex_w[single.texNum];
|
|
float ty2 = (float) (single.height + 2) / fontPal.tex_h[single.texNum];
|
|
|
|
float x1 = (float) x - (float) single.xhot / cameraZoom;
|
|
float y1 = (float) y - (float) single.yhot / cameraZoom;
|
|
float x2 = x1 + (float) single.width / cameraZoom;
|
|
float y2 = y1 + (float) single.height / cameraZoom;
|
|
|
|
GLfloat vertices[] = {
|
|
x1, y1, 0.0f,
|
|
x2, y1, 0.0f,
|
|
x1, y2, 0.0f,
|
|
x2, y2, 0.0f
|
|
};
|
|
if (flip) {
|
|
vertices[0] = x2;
|
|
vertices[3] = x1;
|
|
vertices[6] = x2;
|
|
vertices[9] = x1;
|
|
}
|
|
|
|
const GLfloat texCoords[] = {
|
|
tx1, ty1,
|
|
tx2, ty1,
|
|
tx1, ty2,
|
|
tx2, ty2
|
|
};
|
|
|
|
//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // GL_MODULATE instead of decal mixes the colours!
|
|
setPrimaryColor(fontPal.originalRed / 255.f, fontPal.originalGreen / 255.f, fontPal.originalBlue / 255.f, 1.0f);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, fontPal.tex_names[single.texNum]);
|
|
|
|
glUseProgram(shader.smartScaler);
|
|
GLuint uniform = glGetUniformLocation(shader.smartScaler, "useLightTexture");
|
|
if (uniform >= 0) glUniform1i(uniform, 0);
|
|
|
|
setPMVMatrix(shader.smartScaler);
|
|
|
|
if (gameSettings.antiAlias == 1) {
|
|
glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 1);
|
|
} else {
|
|
glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 0);
|
|
}
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
drawQuad(shader.smartScaler, vertices, 1, texCoords);
|
|
|
|
glDisable(GL_BLEND);
|
|
glUseProgram(0);
|
|
#endif
|
|
}
|
|
|
|
void fontSprite(int x, int y, sprite &single, const spritePalette &fontPal) {
|
|
fontSprite(false, x, y, single, fontPal);
|
|
}
|
|
|
|
void flipFontSprite(int x, int y, sprite &single,
|
|
const spritePalette &fontPal) {
|
|
fontSprite(true, x, y, single, fontPal);
|
|
}
|
|
|
|
unsigned char curLight[3];
|
|
|
|
void setDrawMode(onScreenPerson *thisPerson) {
|
|
#if 0
|
|
if (thisPerson->colourmix) {
|
|
//glEnable(GL_COLOR_SUM); FIXME: replace line?
|
|
setSecondaryColor(curLight[0]*thisPerson->r * thisPerson->colourmix / 65025 / 255.f, curLight[1]*thisPerson->g * thisPerson->colourmix / 65025 / 255.f, curLight[2]*thisPerson->b * thisPerson->colourmix / 65025 / 255.f, 1.0f);
|
|
}
|
|
|
|
//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
setPrimaryColor(curLight[0] * (255 - thisPerson->colourmix) / 65025.f, curLight[1] * (255 - thisPerson->colourmix) / 65025.f, curLight[2] * (255 - thisPerson->colourmix) / 65025.f, 1.0f - thisPerson->transparency / 255.f);
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
extern GLuint backdropTextureName;
|
|
#endif
|
|
|
|
bool checkColourChange(bool reset);
|
|
|
|
bool scaleSprite(sprite &single, const spritePalette &fontPal,
|
|
onScreenPerson *thisPerson, bool mirror) {
|
|
#if 0
|
|
float x = thisPerson->x;
|
|
float y = thisPerson->y;
|
|
|
|
float scale = thisPerson-> scale;
|
|
bool light = !(thisPerson->extra & EXTRA_NOLITE);
|
|
|
|
if (scale <= 0.05) return false;
|
|
|
|
float tx1 = (float)(single.tex_x) / fontPal.tex_w[single.texNum];
|
|
float ty1 = (float) 1.0 / fontPal.tex_h[single.texNum];
|
|
float tx2 = (float)(single.tex_x + single.width) / fontPal.tex_w[single.texNum];
|
|
float ty2 = (float)(single.height + 1) / fontPal.tex_h[single.texNum];
|
|
|
|
int diffX = (int)(((float)single.width) * scale);
|
|
int diffY = (int)(((float)single.height) * scale);
|
|
|
|
GLfloat x1, y1, x2, y2;
|
|
|
|
if (thisPerson -> extra & EXTRA_FIXTOSCREEN) {
|
|
x = x / cameraZoom;
|
|
y = y / cameraZoom;
|
|
if (single.xhot < 0)
|
|
x1 = x - (int)((mirror ? (float)(single.width - single.xhot) : (float)(single.xhot + 1)) * scale / cameraZoom);
|
|
else
|
|
x1 = x - (int)((mirror ? (float)(single.width - (single.xhot + 1)) : (float)single.xhot) * scale / cameraZoom);
|
|
y1 = y - (int)((single.yhot - thisPerson->floaty) * scale / cameraZoom);
|
|
x2 = x1 + (int)(diffX / cameraZoom);
|
|
y2 = y1 + (int)(diffY / cameraZoom);
|
|
} else {
|
|
x -= cameraX;
|
|
y -= cameraY;
|
|
if (single.xhot < 0)
|
|
x1 = x - (int)((mirror ? (float)(single.width - single.xhot) : (float)(single.xhot + 1)) * scale);
|
|
else
|
|
x1 = x - (int)((mirror ? (float)(single.width - (single.xhot + 1)) : (float)single.xhot) * scale);
|
|
y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
|
|
x2 = x1 + diffX;
|
|
y2 = y1 + diffY;
|
|
}
|
|
|
|
GLfloat z;
|
|
|
|
if ((!(thisPerson->extra & EXTRA_NOZB)) && zBuffer.numPanels) {
|
|
int i;
|
|
for (i = 1; i < zBuffer.numPanels; i++) {
|
|
if (zBuffer.panel[i] >= y + cameraY) {
|
|
i--;
|
|
break;
|
|
}
|
|
}
|
|
z = 0.999 - (double) i * (1.0 / 128.0);
|
|
} else {
|
|
z = -0.5;
|
|
}
|
|
|
|
float ltx1, ltx2, lty1, lty2;
|
|
if (! NPOT_textures) {
|
|
ltx1 = lightMap.texW * (x1 + cameraX) / sceneWidth;
|
|
ltx2 = lightMap.texW * (x2 + cameraX) / sceneWidth;
|
|
lty1 = lightMap.texH * (y1 + cameraY) / sceneHeight;
|
|
lty2 = lightMap.texH * (y2 + cameraY) / sceneHeight;
|
|
} else {
|
|
ltx1 = (float)(x1 + cameraX) / sceneWidth;
|
|
ltx2 = (float)(x2 + cameraX) / sceneWidth;
|
|
lty1 = (float)(y1 + cameraY) / sceneHeight;
|
|
lty2 = (float)(y2 + cameraY) / sceneHeight;
|
|
}
|
|
|
|
const GLfloat ltexCoords[] = {
|
|
ltx1, lty1,
|
|
ltx2, lty1,
|
|
ltx1, lty2,
|
|
ltx2, lty2
|
|
};
|
|
|
|
if (light && lightMap.data) {
|
|
if (lightMapMode == LIGHTMAPMODE_HOTSPOT) {
|
|
int lx = (int)(x + cameraX);
|
|
int ly = (int)(y + cameraY);
|
|
|
|
if (lx < 0) lx = 0;
|
|
else if (lx >= sceneWidth) lx = sceneWidth - 1;
|
|
if (ly < 0) ly = 0;
|
|
else if (ly >= sceneHeight) ly = sceneHeight - 1;
|
|
|
|
GLubyte *target;
|
|
if (! NPOT_textures) {
|
|
target = lightMap.data + (ly * getNextPOT(sceneWidth) + lx) * 4;
|
|
} else {
|
|
target = lightMap.data + (ly * sceneWidth + lx) * 4;
|
|
}
|
|
curLight[0] = target[0];
|
|
curLight[1] = target[1];
|
|
curLight[2] = target[2];
|
|
} else if (lightMapMode == LIGHTMAPMODE_PIXEL) {
|
|
curLight[0] = curLight[1] = curLight[2] = 255;
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, lightMap.name);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
}
|
|
} else {
|
|
curLight[0] = curLight[1] = curLight[2] = 255;
|
|
}
|
|
#ifndef HAVE_GLES2
|
|
if (!(thisPerson->extra & EXTRA_RECTANGULAR))
|
|
checkColourChange(true);
|
|
#endif
|
|
setDrawMode(thisPerson);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, fontPal.tex_names[single.texNum]);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glUseProgram(shader.smartScaler);
|
|
GLuint uniform = glGetUniformLocation(shader.smartScaler, "useLightTexture");
|
|
if (uniform >= 0) glUniform1i(uniform, light && lightMapMode == LIGHTMAPMODE_PIXEL && lightMap.data);
|
|
|
|
setPMVMatrix(shader.smartScaler);
|
|
|
|
if (gameSettings.antiAlias == 1) {
|
|
glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 1);
|
|
} else {
|
|
glUniform1i(glGetUniformLocation(shader.smartScaler, "antialias"), 0);
|
|
}
|
|
|
|
const GLfloat vertices[] = {
|
|
x1, y1, z,
|
|
x2, y1, z,
|
|
x1, y2, z,
|
|
x2, y2, z
|
|
};
|
|
|
|
if (! mirror) {
|
|
GLfloat tx3 = tx1;
|
|
tx1 = tx2;
|
|
tx2 = tx3;
|
|
}
|
|
const GLfloat texCoords[] = {
|
|
tx2, ty1,
|
|
tx1, ty1,
|
|
tx2, ty2,
|
|
tx1, ty2
|
|
};
|
|
|
|
drawQuad(shader.smartScaler, vertices, 2, texCoords, ltexCoords);
|
|
|
|
glDisable(GL_BLEND);
|
|
glUseProgram(0);
|
|
|
|
if (light && lightMapMode == LIGHTMAPMODE_PIXEL) {
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
}
|
|
|
|
setSecondaryColor(0., 0., 0., 1.);
|
|
//glDisable(GL_COLOR_SUM); FIXME: replace line?
|
|
|
|
// Are we pointing at the sprite?
|
|
if (input.mouseX >= x1 && input.mouseX <= x2 && input.mouseY >= y1 && input.mouseY <= y2) {
|
|
if (thisPerson->extra & EXTRA_RECTANGULAR) return true;
|
|
#ifdef HAVE_GLES2
|
|
return true;
|
|
#else
|
|
return checkColourChange(false);
|
|
#endif
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
// Paste a scaled sprite onto the backdrop
|
|
void fixScaleSprite(int x, int y, sprite &single, const spritePalette &fontPal,
|
|
onScreenPerson *thisPerson, int camX, int camY, bool mirror) {
|
|
#if 0
|
|
float scale = thisPerson-> scale;
|
|
bool useZB = !(thisPerson->extra & EXTRA_NOZB);
|
|
bool light = !(thisPerson->extra & EXTRA_NOLITE);
|
|
|
|
if (scale <= 0.05) return;
|
|
|
|
float tx1 = (float)(single.tex_x) / fontPal.tex_w[single.texNum];
|
|
float ty1 = (float) 1.0 / fontPal.tex_h[single.texNum]; //0.0;
|
|
float tx2 = (float)(single.tex_x + single.width) / fontPal.tex_w[single.texNum];
|
|
float ty2 = (float)(single.height + 1) / fontPal.tex_h[single.texNum];
|
|
|
|
int diffX = (int)(((float)single.width) * scale);
|
|
int diffY = (int)(((float)single.height) * scale);
|
|
int x1;
|
|
if (single.xhot < 0)
|
|
x1 = x - (int)((mirror ? (float)(single.width - single.xhot) : (float)(single.xhot + 1)) * scale);
|
|
else
|
|
x1 = x - (int)((mirror ? (float)(single.width - (single.xhot + 1)) : (float)single.xhot) * scale);
|
|
int y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
|
|
|
|
float spriteWidth = diffX;
|
|
float spriteHeight = diffY;
|
|
if (x1 < 0) diffX += x1;
|
|
if (y1 < 0) diffY += y1;
|
|
if (x1 + diffX > sceneWidth) diffX = sceneWidth - x1;
|
|
if (y1 + diffY > sceneHeight) diffY = sceneHeight - y1;
|
|
if (diffX < 0) return;
|
|
if (diffY < 0) return;
|
|
|
|
GLfloat z;
|
|
|
|
if (useZB && zBuffer.numPanels) {
|
|
int i;
|
|
for (i = 1; i < zBuffer.numPanels; i++) {
|
|
if (zBuffer.panel[i] >= y + cameraY) {
|
|
i--;
|
|
break;
|
|
}
|
|
}
|
|
z = 0.999 - (double) i * (1.0 / 128.0);
|
|
} else {
|
|
z = -0.5;
|
|
}
|
|
|
|
float ltx1, btx1;
|
|
float ltx2, btx2;
|
|
float lty1, bty1;
|
|
float lty2, bty2;
|
|
if (! NPOT_textures) {
|
|
ltx1 = lightMap.texW * x1 / sceneWidth;
|
|
ltx2 = lightMap.texW * (x1 + spriteWidth) / sceneWidth;
|
|
lty1 = lightMap.texH * y1 / sceneHeight;
|
|
lty2 = lightMap.texH * (y1 + spriteHeight) / sceneHeight;
|
|
btx1 = backdropTexW * x1 / sceneWidth;
|
|
btx2 = backdropTexW * (x1 + spriteWidth) / sceneWidth;
|
|
bty1 = backdropTexH * y1 / sceneHeight;
|
|
bty2 = backdropTexH * (y1 + spriteHeight) / sceneHeight;
|
|
} else {
|
|
btx1 = ltx1 = (float) x1 / sceneWidth;
|
|
btx2 = ltx2 = (float)(x1 + spriteWidth) / sceneWidth;
|
|
bty1 = lty1 = (float) y1 / sceneHeight;
|
|
bty2 = lty2 = (float)(y1 + spriteHeight) / sceneHeight;
|
|
}
|
|
|
|
const GLfloat ltexCoords[] = {
|
|
ltx1, lty1,
|
|
ltx2, lty1,
|
|
ltx1, lty2,
|
|
ltx2, lty2
|
|
};
|
|
|
|
const GLfloat btexCoords[] = {
|
|
btx1, bty1,
|
|
btx2, bty1,
|
|
btx1, bty2,
|
|
btx2, bty2
|
|
};
|
|
|
|
if (light && lightMap.data) {
|
|
if (lightMapMode == LIGHTMAPMODE_HOTSPOT) {
|
|
int lx = x + cameraX;
|
|
int ly = y + cameraY;
|
|
if (lx < 0 || ly < 0 || lx >= sceneWidth || ly >= sceneHeight) {
|
|
curLight[0] = curLight[1] = curLight[2] = 255;
|
|
} else {
|
|
GLubyte *target = lightMap.data + (ly * sceneWidth + lx) * 4;
|
|
curLight[0] = target[0];
|
|
curLight[1] = target[1];
|
|
curLight[2] = target[2];
|
|
}
|
|
} else if (lightMapMode == LIGHTMAPMODE_PIXEL) {
|
|
curLight[0] = curLight[1] = curLight[2] = 255;
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, lightMap.name);
|
|
|
|
}
|
|
} else {
|
|
curLight[0] = curLight[1] = curLight[2] = 255;
|
|
}
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, backdropTextureName);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
setPixelCoords(true);
|
|
GLfloat xoffset = 0.0f;
|
|
while (xoffset < diffX) {
|
|
int w = (diffX - xoffset < viewportWidth) ? (int)(diffX - xoffset) : viewportWidth;
|
|
|
|
GLfloat yoffset = 0.0f;
|
|
while (yoffset < diffY) {
|
|
|
|
int h = (diffY - yoffset < viewportHeight) ? (int)(diffY - yoffset) : viewportHeight;
|
|
|
|
// Render the scene - first the old backdrop (so that it'll show through when the z-buffer is active
|
|
//glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
glBindTexture(GL_TEXTURE_2D, backdropTextureName);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
const GLfloat vertices[] = {
|
|
-x1 - xoffset, -y1 - yoffset, 0.0f,
|
|
sceneWidth - x1 - xoffset, -y1 - yoffset, 0.0f,
|
|
-x1 - xoffset, sceneHeight - y1 - yoffset, 0.0f,
|
|
sceneWidth - x1 - xoffset, sceneHeight - y1 - yoffset, 0.0f
|
|
};
|
|
|
|
const GLfloat texCoords[] = {
|
|
0.0f, 0.0f,
|
|
backdropTexW, 0.0f,
|
|
0.0f, backdropTexH,
|
|
backdropTexW, backdropTexH
|
|
};
|
|
|
|
glUseProgram(shader.texture);
|
|
setPMVMatrix(shader.texture);
|
|
|
|
drawQuad(shader.texture, vertices, 1, texCoords);
|
|
|
|
// The z-buffer
|
|
if (useZB) {
|
|
glDepthMask(GL_TRUE);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
drawZBuffer((int)(x1 + xoffset + camX), (int)(y1 + yoffset + camY), false);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
// Then the sprite
|
|
glUseProgram(shader.paste);
|
|
GLint uniform = glGetUniformLocation(shader.paste, "useLightTexture");
|
|
if (uniform >= 0) glUniform1i(uniform, light && lightMapMode == LIGHTMAPMODE_PIXEL && lightMap.data);
|
|
setPMVMatrix(shader.paste);
|
|
|
|
setDrawMode(thisPerson);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, fontPal.tex_names[single.texNum]);
|
|
|
|
const GLfloat vertices2[] = {
|
|
-xoffset, -yoffset, z,
|
|
spriteWidth - xoffset, -yoffset, z,
|
|
-xoffset, spriteHeight - yoffset, z,
|
|
spriteWidth - xoffset, spriteHeight - yoffset, z
|
|
};
|
|
|
|
if (! mirror) {
|
|
GLfloat tx3 = tx1;
|
|
tx1 = tx2;
|
|
tx2 = tx3;
|
|
}
|
|
const GLfloat texCoords2[] = {
|
|
tx2, ty1,
|
|
tx1, ty1,
|
|
tx2, ty2,
|
|
tx1, ty2
|
|
};
|
|
|
|
drawQuad(shader.paste, vertices2, 3, texCoords2, ltexCoords, btexCoords);
|
|
|
|
setSecondaryColor(0., 0., 0., 1.);
|
|
//glDisable(GL_COLOR_SUM); FIXME: replace line?
|
|
// Copy Our ViewPort To The Texture
|
|
glUseProgram(0);
|
|
copyTexSubImage2D(GL_TEXTURE_2D, 0, (int)((x1 < 0) ? xoffset : x1 + xoffset), (int)((y1 < 0) ? yoffset : y1 + yoffset), (int)((x1 < 0) ? viewportOffsetX - x1 : viewportOffsetX), (int)((y1 < 0) ? viewportOffsetY - y1 : viewportOffsetY), w, h, backdropTextureName);
|
|
|
|
yoffset += viewportHeight;
|
|
}
|
|
xoffset += viewportWidth;
|
|
}
|
|
|
|
setPixelCoords(false);
|
|
glUseProgram(0);
|
|
#endif
|
|
}
|
|
|
|
} // End of namespace Sludge
|