Serious-Engine/Sources/Shaders/Common.cpp
Ryan C. Gordon 24cb244d43 First attempt to hand-merge Ryan's Linux and Mac OS X port.
This was a _ton_ of changes, made 15 years ago, so there are probably some
problems to work out still.

Among others: Engine/Base/Stream.* was mostly abandoned and will need to be
re-ported.

Still, this is a pretty good start, and probably holds a world record for
lines of changes or something.  :)
2016-03-28 23:46:13 -04:00

163 lines
5.6 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#include "Shaders/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;
for(ivx=0;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].st.s = fRV(1)*f1oFM +0.5f;
ptcUVMap[ivx].st.t = fRV(2)*f1oFM +0.5f;
}
GFXColor colSrfSpec = shaGetColor(iSpecularColor);
colSrfSpec.AttenuateRGB( (shaGetModelColor()&CT_AMASK)>>CT_ASHIFT);
colSrfSpec.ub.r = ClampUp( (colSrfSpec.ub.r *slLR)>>8, 255L);
colSrfSpec.ub.g = ClampUp( (colSrfSpec.ub.g *slLG)>>8, 255L);
colSrfSpec.ub.b = ClampUp( (colSrfSpec.ub.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].ub.a;
pcolSpec[ivx].ul.abgr = (((colSrfSpec.ub.r)*slShade)>>8)
| (((colSrfSpec.ub.g)*slShade)&0x0000FF00)
|((((colSrfSpec.ub.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].st.s = fRVx*f1oFM +0.5f;
ptcUVMap[ivx].st.t = fRVz*f1oFM +0.5f;
}
GFXColor *pcolReflection = shaGetNewColorArray();
// get model reflection color
GFXColor colSrfRefl;
colSrfRefl.ul.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();
}