2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
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. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
#include "StdH.h"
|
|
|
|
#include <Shaders/Common.h>
|
|
|
|
|
|
|
|
void DoSpecularLayer(INDEX iSpeculaTexture,INDEX iSpecularColor)
|
|
|
|
{
|
|
|
|
GFXVertex4 *paVertices = shaGetVertexArray();
|
|
|
|
GFXNormal *paNormals = shaGetNormalArray();
|
|
|
|
INDEX ctVertices = shaGetVertexCount();
|
|
|
|
FLOAT3D &vLightDir = -shaGetLightDirection().Normalize();
|
|
|
|
COLOR colLight = ByteSwap(shaGetLightColor());
|
|
|
|
COLOR colAmbient = ByteSwap(shaGetAmbientColor());
|
|
|
|
GFXTexCoord *ptcUVMap = shaGetNewTexCoordArray();
|
|
|
|
Matrix12 &mObjToView = *shaGetObjToViewMatrix();
|
|
|
|
shaCalculateLightForSpecular();
|
|
|
|
|
|
|
|
|
|
|
|
// determine multitexturing capability for overbrighting purposes
|
|
|
|
const BOOL bOverbright = shaOverBrightningEnabled();
|
|
|
|
|
|
|
|
// cache light intensities (-1 in case of overbrighting compensation)
|
|
|
|
const INDEX iBright = bOverbright ? 0 : 1;
|
|
|
|
SLONG slLR = (colLight & CT_RMASK)>>(CT_RSHIFT-iBright);
|
|
|
|
SLONG slLG = (colLight & CT_GMASK)>>(CT_GSHIFT-iBright);
|
|
|
|
SLONG slLB = (colLight & CT_BMASK)>>(CT_BSHIFT-iBright);
|
|
|
|
SLONG slAR = (colAmbient & CT_RMASK)>>(CT_RSHIFT-iBright);
|
|
|
|
SLONG slAG = (colAmbient & CT_GMASK)>>(CT_GSHIFT-iBright);
|
|
|
|
SLONG slAB = (colAmbient & CT_BMASK)>>(CT_BSHIFT-iBright);
|
|
|
|
if( bOverbright) {
|
|
|
|
slAR = ClampUp( slAR, 127L);
|
|
|
|
slAG = ClampUp( slAG, 127L);
|
|
|
|
slAB = ClampUp( slAB, 127L);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// for each vertex
|
|
|
|
INDEX ivx=0;
|
|
|
|
for(;ivx<ctVertices;ivx++) {
|
|
|
|
// reflect light vector around vertex normal in object space
|
|
|
|
GFXNormal &nor = paNormals[ivx];
|
|
|
|
FLOAT3D vNot = FLOAT3D(nor.nx,nor.ny,nor.nz);
|
|
|
|
// vNot.Normalize();
|
|
|
|
//ASSERT(vNot.Normalize() == 1.0f);
|
|
|
|
const FLOAT fNL = nor.nx*vLightDir(1) + nor.ny*vLightDir(2) + nor.nz*vLightDir(3);
|
|
|
|
const FLOAT fRx = vLightDir(1) - 2*vNot(1)*fNL;
|
|
|
|
const FLOAT fRy = vLightDir(2) - 2*vNot(2)*fNL;
|
|
|
|
const FLOAT fRz = vLightDir(3) - 2*vNot(3)*fNL;
|
|
|
|
|
|
|
|
FLOAT3D fRV = FLOAT3D(fRx,fRy,fRz);
|
|
|
|
RotateVector(fRV.vector,mObjToView);
|
|
|
|
// map reflected vector to texture
|
|
|
|
const FLOAT f1oFM = 0.5f / sqrt(2+2*fRV(3)); // was 2*sqrt(2+2*fRVz)
|
|
|
|
ptcUVMap[ivx].s = fRV(1)*f1oFM +0.5f;
|
|
|
|
ptcUVMap[ivx].t = fRV(2)*f1oFM +0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
GFXColor colSrfSpec = shaGetColor(iSpecularColor);
|
|
|
|
colSrfSpec.AttenuateRGB( (shaGetModelColor()&CT_AMASK)>>CT_ASHIFT);
|
|
|
|
colSrfSpec.r = ClampUp( (colSrfSpec.r *slLR)>>8, 255L);
|
|
|
|
colSrfSpec.g = ClampUp( (colSrfSpec.g *slLG)>>8, 255L);
|
|
|
|
colSrfSpec.b = ClampUp( (colSrfSpec.b *slLB)>>8, 255L);
|
|
|
|
|
|
|
|
GFXColor *pcolSpec = shaGetNewColorArray();
|
|
|
|
GFXColor *pcolBase = shaGetColorArray();;
|
|
|
|
|
|
|
|
// for each vertex in the surface
|
|
|
|
for(ivx=0;ivx<ctVertices;ivx++) {
|
|
|
|
// set specular color
|
|
|
|
const SLONG slShade = pcolBase[ivx].a;
|
|
|
|
pcolSpec[ivx].abgr = (((colSrfSpec.r)*slShade)>>8)
|
|
|
|
| (((colSrfSpec.g)*slShade)&0x0000FF00)
|
|
|
|
|((((colSrfSpec.b)*slShade)<<8)&0x00FF0000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
shaSetTexCoords(ptcUVMap);
|
|
|
|
shaSetVertexColors(pcolSpec);
|
|
|
|
shaSetTexture(iSpeculaTexture);
|
|
|
|
shaBlendFunc( GFX_INV_SRC_ALPHA, GFX_ONE);
|
|
|
|
shaEnableBlend();
|
|
|
|
shaCullFace(GFX_BACK);
|
|
|
|
shaRender();
|
|
|
|
shaCullFace(GFX_FRONT);
|
|
|
|
shaRender();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DoReflectionLayer(INDEX iReflectionTexture,INDEX iReflectionColor,BOOL bFullBright)
|
|
|
|
{
|
|
|
|
GFXVertex4 *paVertices = NULL;
|
|
|
|
GFXNormal *paNormals = NULL;
|
|
|
|
paVertices = shaGetVertexArray();
|
|
|
|
paNormals = shaGetNormalArray();
|
|
|
|
INDEX ctVertices = shaGetVertexCount();
|
|
|
|
GFXTexCoord *ptcUVMap = shaGetNewTexCoordArray();
|
|
|
|
Matrix12 &mObjToView = *shaGetObjToViewMatrix();
|
|
|
|
Matrix12 &mObjToAbs = *shaGetObjToAbsMatrix();
|
|
|
|
CAnyProjection3D &apr = *shaGetProjection();
|
|
|
|
|
|
|
|
// calculate projection of viewer in absolute space
|
|
|
|
FLOATmatrix3D &mViewer = apr->pr_ViewerRotationMatrix;
|
|
|
|
FLOAT3D vViewer = FLOAT3D(-mViewer(3,1),-mViewer(3,2),-mViewer(3,3));
|
|
|
|
|
|
|
|
|
|
|
|
Matrix12 mTemp,mInvert;
|
|
|
|
MatrixVectorToMatrix12(mTemp,mViewer,FLOAT3D(0,0,0));
|
|
|
|
MatrixTranspose(mInvert,mTemp);
|
|
|
|
// mObjToAbs = !mViewer;
|
|
|
|
|
|
|
|
// for each vertex
|
|
|
|
for(INDEX ivx=0;ivx<ctVertices;ivx++) {
|
|
|
|
// reflect light vector around vertex normal in object space
|
|
|
|
FLOAT3D vNor = FLOAT3D(paNormals[ivx].nx,paNormals[ivx].ny,paNormals[ivx].nz);
|
|
|
|
RotateVector(vNor.vector,mObjToAbs);
|
|
|
|
|
|
|
|
// reflect viewer around normal
|
|
|
|
const FLOAT fNV = vNor(1)*vViewer(1) + vNor(2)*vViewer(2) + vNor(3)*vViewer(3);
|
|
|
|
const FLOAT fRVx = vViewer(1) - 2*vNor(1)*fNV;
|
|
|
|
const FLOAT fRVy = vViewer(2) - 2*vNor(2)*fNV;
|
|
|
|
const FLOAT fRVz = vViewer(3) - 2*vNor(3)*fNV;
|
|
|
|
|
|
|
|
// map reflected vector to texture
|
|
|
|
// NOTE: using X and Z axes, so that singularity gets on -Y axis (where it will least probably be seen)
|
|
|
|
const FLOAT f1oFM = 0.5f / sqrt(2+2*fRVy);
|
|
|
|
ptcUVMap[ivx].s = fRVx*f1oFM +0.5f;
|
|
|
|
ptcUVMap[ivx].t = fRVz*f1oFM +0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
GFXColor *pcolReflection = shaGetNewColorArray();
|
|
|
|
|
|
|
|
// get model reflection color
|
|
|
|
GFXColor colSrfRefl;
|
|
|
|
colSrfRefl.abgr = ByteSwap(shaGetColor(iReflectionColor));
|
|
|
|
colSrfRefl.AttenuateA((shaGetModelColor()&CT_AMASK)>>CT_ASHIFT);
|
|
|
|
|
|
|
|
if(bFullBright) {
|
|
|
|
// just copy reflection color
|
|
|
|
for( INDEX ivx=0;ivx<ctVertices;ivx++) {
|
|
|
|
pcolReflection[ivx] = colSrfRefl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GFXColor *pcolSrfBase = shaGetColorArray();
|
|
|
|
// set reflection color smooth
|
|
|
|
for( INDEX ivx=0;ivx<ctVertices;ivx++) {
|
|
|
|
pcolReflection[ivx].MultiplyRGBCopyA1( colSrfRefl, pcolSrfBase[ivx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shaSetTexCoords(ptcUVMap);
|
|
|
|
shaSetVertexColors(pcolReflection);
|
|
|
|
shaSetTexture(iReflectionTexture);
|
|
|
|
shaBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA);
|
|
|
|
shaEnableBlend();
|
|
|
|
|
|
|
|
BOOL bDoubleSided = shaGetFlags()&BASE_DOUBLE_SIDED;
|
|
|
|
if(bDoubleSided) {
|
|
|
|
shaCullFace(GFX_FRONT);
|
|
|
|
shaRender();
|
|
|
|
}
|
|
|
|
shaCullFace(GFX_BACK);
|
|
|
|
shaRender();
|
|
|
|
}
|