if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
- switch(t->tcmod)
+ for (i = 0;i < Q3MAXTCMODS && (t->tcmod[i] || i < 1);i++)
{
- case Q3TCMOD_COUNT:
- case Q3TCMOD_NONE:
- if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
- t->currenttexmatrix = r_waterscrollmatrix;
+ matrix4x4_t matrix;
+ switch(t->tcmod[i])
+ {
+ case Q3TCMOD_COUNT:
+ case Q3TCMOD_NONE:
+ if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
+ matrix = r_waterscrollmatrix;
+ else
+ matrix = identitymatrix;
+ break;
+ case Q3TCMOD_ENTITYTRANSLATE:
+ // this is used in Q3 to allow the gamecode to control texcoord
+ // scrolling on the entity, which is not supported in darkplaces yet.
+ Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
+ break;
+ case Q3TCMOD_ROTATE:
+ Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
+ Matrix4x4_ConcatRotate(&matrix, t->tcmod_parms[i][0] * r_refdef.time, 0, 0, 1);
+ Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
+ break;
+ case Q3TCMOD_SCALE:
+ Matrix4x4_CreateScale3(&matrix, t->tcmod_parms[i][0], t->tcmod_parms[i][1], 1);
+ break;
+ case Q3TCMOD_SCROLL:
+ Matrix4x4_CreateTranslate(&matrix, t->tcmod_parms[i][0] * r_refdef.time, t->tcmod_parms[i][1] * r_refdef.time, 0);
+ break;
+ case Q3TCMOD_STRETCH:
+ f = 1.0f / R_EvaluateQ3WaveFunc(t->tcmod_wavefunc[i], t->tcmod_parms[i]);
+ Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
+ break;
+ case Q3TCMOD_TRANSFORM:
+ VectorSet(tcmat + 0, t->tcmod_parms[i][0], t->tcmod_parms[i][1], 0);
+ VectorSet(tcmat + 3, t->tcmod_parms[i][2], t->tcmod_parms[i][3], 0);
+ VectorSet(tcmat + 6, 0 , 0 , 1);
+ VectorSet(tcmat + 9, t->tcmod_parms[i][4], t->tcmod_parms[i][5], 0);
+ Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
+ break;
+ case Q3TCMOD_TURBULENT:
+ // this is handled in the RSurf_PrepareVertices function
+ matrix = identitymatrix;
+ break;
+ }
+ // either replace or concatenate the transformation
+ if (i < 1)
+ t->currenttexmatrix = matrix;
else
- t->currenttexmatrix = identitymatrix;
- break;
- case Q3TCMOD_ENTITYTRANSLATE:
- // this is used in Q3 to allow the gamecode to control texcoord
- // scrolling on the entity, which is not supported in darkplaces yet.
- Matrix4x4_CreateTranslate(&t->currenttexmatrix, 0, 0, 0);
- break;
- case Q3TCMOD_ROTATE:
- Matrix4x4_CreateTranslate(&t->currenttexmatrix, 0.5, 0.5, 0);
- Matrix4x4_ConcatRotate(&t->currenttexmatrix, t->tcmod_parms[0] * r_refdef.time, 0, 0, 1);
- Matrix4x4_ConcatTranslate(&t->currenttexmatrix, -0.5, -0.5, 0);
- break;
- case Q3TCMOD_SCALE:
- Matrix4x4_CreateScale3(&t->currenttexmatrix, t->tcmod_parms[0], t->tcmod_parms[1], 1);
- break;
- case Q3TCMOD_SCROLL:
- Matrix4x4_CreateTranslate(&t->currenttexmatrix, t->tcmod_parms[0] * r_refdef.time, t->tcmod_parms[1] * r_refdef.time, 0);
- break;
- case Q3TCMOD_STRETCH:
- f = 1.0f / R_EvaluateQ3WaveFunc(t->tcmod_wavefunc, t->tcmod_parms);
- Matrix4x4_CreateFromQuakeEntity(&t->currenttexmatrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
- break;
- case Q3TCMOD_TRANSFORM:
- VectorSet(tcmat + 0, t->tcmod_parms[0], t->tcmod_parms[1], 0);
- VectorSet(tcmat + 3, t->tcmod_parms[2], t->tcmod_parms[3], 0);
- VectorSet(tcmat + 6, 0 , 0 , 1);
- VectorSet(tcmat + 9, t->tcmod_parms[4], t->tcmod_parms[5], 0);
- Matrix4x4_FromArray12FloatGL(&t->currenttexmatrix, tcmat);
- break;
- case Q3TCMOD_TURBULENT:
- // this is handled in the RSurf_PrepareVertices function
- t->currenttexmatrix = identitymatrix;
- break;
+ {
+ matrix4x4_t temp = t->currenttexmatrix;
+ Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
+ }
}
t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
}
// the only tcmod that needs software vertex processing is turbulent, so
// check for it here and apply the changes if needed
- if (rsurface.texture->tcmod == Q3TCMOD_TURBULENT)
+ // and we only support that as the first one
+ // (handling a mixture of turbulent and other tcmods would be problematic
+ // without punting it entirely to a software path)
+ if (rsurface.texture->tcmod[0] == Q3TCMOD_TURBULENT)
{
- amplitude = rsurface.texture->tcmod_parms[1];
- animpos = rsurface.texture->tcmod_parms[2] + r_refdef.time * rsurface.texture->tcmod_parms[3];
+ amplitude = rsurface.texture->tcmod_parms[0][1];
+ animpos = rsurface.texture->tcmod_parms[0][2] + r_refdef.time * rsurface.texture->tcmod_parms[0][3];
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
layer->rgbgen = Q3RGBGEN_IDENTITY;
layer->alphagen = Q3ALPHAGEN_IDENTITY;
layer->tcgen = Q3TCGEN_TEXTURE;
- layer->tcmod = Q3TCMOD_NONE;
layer->blendfunc[0] = GL_ONE;
layer->blendfunc[1] = GL_ZERO;
}
}
else if (numparameters >= 2 && !strcasecmp(parameter[0], "tcmod"))
{
- int i;
+ int i, tcmodindex;
// observed values:
// tcmod rotate #
// tcmod scale # #
// tcmod turb # # # #
// tcmod turb sin # # # # (this is bogus)
// no other values have been observed in real shaders
- for (i = 0;i < numparameters - 2 && i < Q3TCMOD_MAXPARMS;i++)
- layer->tcmod_parms[i] = atof(parameter[i+2]);
- if (!strcasecmp(parameter[1], "entitytranslate")) layer->tcmod = Q3TCMOD_ENTITYTRANSLATE;
- else if (!strcasecmp(parameter[1], "rotate")) layer->tcmod = Q3TCMOD_ROTATE;
- else if (!strcasecmp(parameter[1], "scale")) layer->tcmod = Q3TCMOD_SCALE;
- else if (!strcasecmp(parameter[1], "scroll")) layer->tcmod = Q3TCMOD_SCROLL;
- else if (!strcasecmp(parameter[1], "stretch"))
+ for (tcmodindex = 0;tcmodindex < Q3MAXTCMODS;tcmodindex++)
+ if (!layer->tcmod[tcmodindex])
+ break;
+ if (tcmodindex < Q3MAXTCMODS)
{
- layer->tcmod = Q3TCMOD_STRETCH;
- for (i = 0;i < numparameters - 3 && i < Q3TCMOD_MAXPARMS;i++)
- layer->tcmod_parms[i] = atof(parameter[i+3]);
- layer->tcmod_wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
+ for (i = 0;i < numparameters - 2 && i < Q3TCMOD_MAXPARMS;i++)
+ layer->tcmod_parms[tcmodindex][i] = atof(parameter[i+2]);
+ if (!strcasecmp(parameter[1], "entitytranslate")) layer->tcmod[tcmodindex] = Q3TCMOD_ENTITYTRANSLATE;
+ else if (!strcasecmp(parameter[1], "rotate")) layer->tcmod[tcmodindex] = Q3TCMOD_ROTATE;
+ else if (!strcasecmp(parameter[1], "scale")) layer->tcmod[tcmodindex] = Q3TCMOD_SCALE;
+ else if (!strcasecmp(parameter[1], "scroll")) layer->tcmod[tcmodindex] = Q3TCMOD_SCROLL;
+ else if (!strcasecmp(parameter[1], "stretch"))
+ {
+ layer->tcmod[tcmodindex] = Q3TCMOD_STRETCH;
+ for (i = 0;i < numparameters - 3 && i < Q3TCMOD_MAXPARMS;i++)
+ layer->tcmod_parms[tcmodindex][i] = atof(parameter[i+3]);
+ layer->tcmod_wavefunc[tcmodindex] = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
+ }
+ else if (!strcasecmp(parameter[1], "transform")) layer->tcmod[tcmodindex] = Q3TCMOD_TRANSFORM;
+ else if (!strcasecmp(parameter[1], "turb")) layer->tcmod[tcmodindex] = Q3TCMOD_TURBULENT;
+ else Con_DPrintf("%s parsing warning: unknown tcmod mode %s\n", search->filenames[fileindex], parameter[1]);
}
- else if (!strcasecmp(parameter[1], "transform")) layer->tcmod = Q3TCMOD_TRANSFORM;
- else if (!strcasecmp(parameter[1], "turb")) layer->tcmod = Q3TCMOD_TURBULENT;
- else Con_DPrintf("%s parsing warning: unknown tcmod mode %s\n", search->filenames[fileindex], parameter[1]);
+ else
+ Con_DPrintf("%s parsing warning: too many tcmods on one layer\n", search->filenames[fileindex]);
}
// break out a level if it was }
if (!strcasecmp(com_token, "}"))
texture->rgbgen = shader->primarylayer->rgbgen;
texture->alphagen = shader->primarylayer->alphagen;
texture->tcgen = shader->primarylayer->tcgen;
- texture->tcmod = shader->primarylayer->tcmod;
+ memcpy(texture->tcmod , shader->primarylayer->tcmod , sizeof(texture->tcmod));
memcpy(texture->rgbgen_parms , shader->primarylayer->rgbgen_parms , sizeof(texture->rgbgen_parms));
memcpy(texture->alphagen_parms, shader->primarylayer->alphagen_parms, sizeof(texture->alphagen_parms));
memcpy(texture->tcgen_parms , shader->primarylayer->tcgen_parms , sizeof(texture->tcgen_parms));
memcpy(texture->tcmod_parms , shader->primarylayer->tcmod_parms , sizeof(texture->tcmod_parms));
- texture->tcmod_wavefunc = shader->primarylayer->tcmod_wavefunc;
+ memcpy(texture->tcmod_wavefunc, shader->primarylayer->tcmod_wavefunc, sizeof(texture->tcmod_wavefunc));
// load the textures
texture->numskinframes = shader->primarylayer->numframes;
texture->skinframerate = shader->primarylayer->framerate;