📄 tr_shade_calc.c
字号:
c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = c;
}
}
/*
** RB_CalcColorFromOneMinusEntity
*/
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
{
int i;
int *pColors = ( int * ) dstColors;
unsigned char invModulate[3];
int c;
if ( !backEnd.currentEntity )
return;
invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it
c = * ( int * ) invModulate;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = * ( int * ) invModulate;
}
}
/*
** RB_CalcAlphaFromEntity
*/
void RB_CalcAlphaFromEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = backEnd.currentEntity->e.shaderRGBA[3];
}
}
/*
** RB_CalcAlphaFromOneMinusEntity
*/
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
}
}
/*
** RB_CalcWaveColor
*/
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
int *colors = ( int * ) dstColors;
byte color[4];
if ( wf->func == GF_NOISE ) {
glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude;
} else {
glow = EvalWaveForm( wf ) * tr.identityLight;
}
if ( glow < 0 ) {
glow = 0;
}
else if ( glow > 1 ) {
glow = 1;
}
v = myftol( 255 * glow );
color[0] = color[1] = color[2] = v;
color[3] = 255;
v = *(int *)color;
for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
*colors = v;
}
}
/*
** RB_CalcWaveAlpha
*/
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
glow = EvalWaveFormClamped( wf );
v = 255 * glow;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
dstColors[3] = v;
}
}
/*
** RB_CalcModulateColorsByFog
*/
void RB_CalcModulateColorsByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[0] *= f;
colors[1] *= f;
colors[2] *= f;
}
}
/*
** RB_CalcModulateAlphasByFog
*/
void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[3] *= f;
}
}
/*
** RB_CalcModulateRGBAsByFog
*/
void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[0] *= f;
colors[1] *= f;
colors[2] *= f;
colors[3] *= f;
}
}
/*
====================================================================
TEX COORDS
====================================================================
*/
/*
========================
RB_CalcFogTexCoords
To do the clipped fog plane really correctly, we should use
projected textures, but I don't trust the drivers and it
doesn't fit our shader data.
========================
*/
void RB_CalcFogTexCoords( float *st ) {
int i;
float *v;
float s, t;
float eyeT;
qboolean eyeOutside;
fog_t *fog;
vec3_t local;
vec4_t fogDistanceVector, fogDepthVector;
fog = tr.world->fogs + tess.fogNum;
// all fogging distance is based on world Z units
VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local );
fogDistanceVector[0] = -backEnd.or.modelMatrix[2];
fogDistanceVector[1] = -backEnd.or.modelMatrix[6];
fogDistanceVector[2] = -backEnd.or.modelMatrix[10];
fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] );
// scale the fog vectors based on the fog's thickness
fogDistanceVector[0] *= fog->tcScale;
fogDistanceVector[1] *= fog->tcScale;
fogDistanceVector[2] *= fog->tcScale;
fogDistanceVector[3] *= fog->tcScale;
// rotate the gradient vector for this orientation
if ( fog->hasSurface ) {
fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] +
fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2];
fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] +
fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2];
fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] +
fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2];
fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface );
eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3];
} else {
eyeT = 1; // non-surface fog always has eye inside
}
// see if the viewpoint is outside
// this is needed for clipping distance even for constant fog
if ( eyeT < 0 ) {
eyeOutside = qtrue;
} else {
eyeOutside = qfalse;
}
fogDistanceVector[3] += 1.0/512;
// calculate density for each point
for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) {
// calculate the length in fog
s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3];
t = DotProduct( v, fogDepthVector ) + fogDepthVector[3];
// partially clipped fogs use the T axis
if ( eyeOutside ) {
if ( t < 1.0 ) {
t = 1.0/32; // point is outside, so no fogging
} else {
t = 1.0/32 + 30.0/32 * t / ( t - eyeT ); // cut the distance at the fog plane
}
} else {
if ( t < 0 ) {
t = 1.0/32; // point is outside, so no fogging
} else {
t = 31.0/32;
}
}
st[0] = s;
st[1] = t;
st += 2;
}
}
/*
** RB_CalcEnvironmentTexCoords
*/
void RB_CalcEnvironmentTexCoords( float *st )
{
int i;
float *v, *normal;
vec3_t viewer, reflected;
float d;
v = tess.xyz[0];
normal = tess.normal[0];
for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
{
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
VectorNormalizeFast (viewer);
d = DotProduct (normal, viewer);
reflected[0] = normal[0]*2*d - viewer[0];
reflected[1] = normal[1]*2*d - viewer[1];
reflected[2] = normal[2]*2*d - viewer[2];
st[0] = 0.5 + reflected[1] * 0.5;
st[1] = 0.5 - reflected[2] * 0.5;
}
}
/*
** RB_CalcTurbulentTexCoords
*/
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
{
int i;
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
}
}
/*
** RB_CalcScaleTexCoords
*/
void RB_CalcScaleTexCoords( const float scale[2], float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] *= scale[0];
st[1] *= scale[1];
}
}
/*
** RB_CalcScrollTexCoords
*/
void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
{
int i;
float timeScale = tess.shaderTime;
float adjustedScrollS, adjustedScrollT;
adjustedScrollS = scrollSpeed[0] * timeScale;
adjustedScrollT = scrollSpeed[1] * timeScale;
// clamp so coordinates don't continuously get larger, causing problems
// with hardware limits
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] += adjustedScrollS;
st[1] += adjustedScrollT;
}
}
/*
** RB_CalcTransformTexCoords
*/
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
}
}
/*
** RB_CalcRotateTexCoords
*/
void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue;
tmi.matrix[1][0] = -sinValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexCoords( &tmi, st );
}
#if id386 && !( (defined __linux__ || defined __FreeBSD__ ) && (defined __i386__ ) ) // rb010123
long myftol( float f ) {
static int tmp;
__asm fld f
__asm fistp tmp
__asm mov eax, tmp
}
#endif
/*
** RB_CalcSpecularAlpha
**
** Calculates specular coefficient and places it in the alpha channel
*/
vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically
void RB_CalcSpecularAlpha( unsigned char *alphas ) {
int i;
float *v, *normal;
vec3_t viewer, reflected;
float l, d;
int b;
vec3_t lightDir;
int numVertexes;
v = tess.xyz[0];
normal = tess.normal[0];
alphas += 3;
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
float ilength;
VectorSubtract( lightOrigin, v, lightDir );
// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
VectorNormalizeFast( lightDir );
// calculate the specular color
d = DotProduct (normal, lightDir);
// d *= ilength;
// we don't optimize for the d < 0 case since this tends to
// cause visual artifacts such as faceted "snapping"
reflected[0] = normal[0]*2*d - lightDir[0];
reflected[1] = normal[1]*2*d - lightDir[1];
reflected[2] = normal[2]*2*d - lightDir[2];
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
l = DotProduct (reflected, viewer);
l *= ilength;
if (l < 0) {
b = 0;
} else {
l = l*l;
l = l*l;
b = l * 255;
if (b > 255) {
b = 255;
}
}
*alphas = b;
}
}
/*
** RB_CalcDiffuseColor
**
** The basic vertex lighting calc
*/
void RB_CalcDiffuseColor( unsigned char *colors )
{
int i, j;
float *v, *normal;
float incoming;
trRefEntity_t *ent;
int ambientLightInt;
vec3_t ambientLight;
vec3_t lightDir;
vec3_t directedLight;
int numVertexes;
#if idppc_altivec
vector unsigned char vSel = (vector unsigned char)(0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff);
vector float ambientLightVec;
vector float directedLightVec;
vector float lightDirVec;
vector float normalVec0, normalVec1;
vector float incomingVec0, incomingVec1, incomingVec2;
vector float zero, jVec;
vector signed int jVecInt;
vector signed short jVecShort;
vector unsigned char jVecChar, normalPerm;
#endif
ent = backEnd.currentEntity;
ambientLightInt = ent->ambientLightInt;
#if idppc_altivec
// A lot of this could be simplified if we made sure
// entities light info was 16-byte aligned.
jVecChar = vec_lvsl(0, ent->ambientLight);
ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
jVec = vec_ld(11, (vector float *)ent->ambientLight);
ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->directedLight);
directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
jVec = vec_ld(11,(vector float *)ent->directedLight);
directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->lightDir);
lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
jVec = vec_ld(11,(vector float *)ent->lightDir);
lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
zero = (vector float)vec_splat_s8(0);
VectorCopy( ent->lightDir, lightDir );
#else
VectorCopy( ent->ambientLight, ambientLight );
VectorCopy( ent->directedLight, directedLight );
VectorCopy( ent->lightDir, lightDir );
#endif
v = tess.xyz[0];
normal = tess.normal[0];
#if idppc_altivec
normalPerm = vec_lvsl(0,normal);
#endif
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
#if idppc_altivec
normalVec0 = vec_ld(0,(vector float *)normal);
normalVec1 = vec_ld(11,(vector float *)normal);
normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
incomingVec2 = vec_add(incomingVec0,incomingVec1);
incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
incomingVec2 = vec_add(incomingVec2,incomingVec1);
incomingVec0 = vec_splat(incomingVec2,0);
incomingVec0 = vec_max(incomingVec0,zero);
normalPerm = vec_lvsl(12,normal);
jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
jVecInt = vec_cts(jVec,0); // RGBx
jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx
jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color
#else
incoming = DotProduct (normal, lightDir);
if ( incoming <= 0 ) {
*(int *)&colors[i*4] = ambientLightInt;
continue;
}
j = myftol( ambientLight[0] + incoming * directedLight[0] );
if ( j > 255 ) {
j = 255;
}
colors[i*4+0] = j;
j = myftol( ambientLight[1] + incoming * directedLight[1] );
if ( j > 255 ) {
j = 255;
}
colors[i*4+1] = j;
j = myftol( ambientLight[2] + incoming * directedLight[2] );
if ( j > 255 ) {
j = 255;
}
colors[i*4+2] = j;
colors[i*4+3] = 255;
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -