From fc7cb03ae97c24d4c0cfd45589ac4e27c699946e Mon Sep 17 00:00:00 2001 From: divverent Date: Sun, 5 Jul 2009 17:18:52 +0000 Subject: [PATCH] Support a separate texture matrix for the background layer. Example shader stages using it: { map textures/savdm6ish/#lava1.jpg } { map textures/final_rage/lava.blend.tga tcMod rotate 50 tcMod scale 2 2 tcMod scroll 0.05 0.05 alphaGen vertex blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA } NOTE: you still have to specify alphaGen vertex, or DP will not use the secondary stage! To allow static mixing of two textures, the second texture currently must have its own alpha channel. Stuff also possible with this: detail textures... git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9042 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 150 +++++++++++++++++++++++++++---------------------- model_shared.c | 3 + model_shared.h | 2 + r_shadow.c | 2 + 4 files changed, 91 insertions(+), 66 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index cd72658e..b13eb463 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -590,6 +590,9 @@ static const char *builtinshaderstring = "#else // !MODE_GENERIC\n" "\n" "varying vec2 TexCoord;\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +"varying vec2 TexCoord2;\n" +"#endif\n" "varying vec2 TexCoordLightmap;\n" "\n" "#ifdef MODE_LIGHTSOURCE\n" @@ -640,6 +643,9 @@ static const char *builtinshaderstring = " gl_FrontColor = gl_Color;\n" " // copy the surface texcoord\n" " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +" TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n" +"#endif\n" "#ifndef MODE_LIGHTSOURCE\n" "# ifndef MODE_LIGHTDIRECTION\n" " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n" @@ -881,7 +887,7 @@ static const char *builtinshaderstring = " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n" " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n" " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n" -" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n" +" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n" " color.a = 1.0;\n" " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n" "#endif\n" @@ -889,9 +895,9 @@ static const char *builtinshaderstring = "#ifdef USEDIFFUSE\n" " // get the surface normal and the gloss color\n" "# ifdef USEVERTEXTEXTUREBLEND\n" -" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n" +" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n" "# ifdef USESPECULAR\n" -" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n" +" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n" "# endif\n" "# else\n" " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n" @@ -1061,8 +1067,12 @@ static const char *builtinshaderstring = " color *= TintColor;\n" "\n" "#ifdef USEGLOW\n" +"#ifdef USEVERTEXTEXTUREBLEND\n" +" color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n" +"#else\n" " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n" "#endif\n" +"#endif\n" "\n" "#ifdef USECONTRASTBOOST\n" " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n" @@ -4706,14 +4716,70 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) return (float)(parms[0] + parms[1] * f); } -texture_t *R_GetCurrentTexture(texture_t *t) +void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) { int w, h, idx; + float f; + float tcmat[12]; + matrix4x4_t matrix, temp; + switch(tcmod->tcmod) + { + case Q3TCMOD_COUNT: + case Q3TCMOD_NONE: + if (currentmaterialflags & MATERIALFLAG_WATERSCROLL) + 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, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1); + Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0); + break; + case Q3TCMOD_SCALE: + Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1); + break; + case Q3TCMOD_SCROLL: + Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0); + break; + case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures) + w = (int) tcmod->parms[0]; + h = (int) tcmod->parms[1]; + f = r_refdef.scene.time / (tcmod->parms[2] * w * h); + f = f - floor(f); + idx = (int) floor(f * w * h); + Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0); + break; + case Q3TCMOD_STRETCH: + f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms); + Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f); + break; + case Q3TCMOD_TRANSFORM: + VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0); + VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0); + VectorSet(tcmat + 6, 0 , 0 , 1); + VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0); + Matrix4x4_FromArray12FloatGL(&matrix, tcmat); + break; + case Q3TCMOD_TURBULENT: + // this is handled in the RSurf_PrepareVertices function + matrix = identitymatrix; + break; + } + temp = *texmatrix; + Matrix4x4_Concat(texmatrix, &matrix, &temp); +} + +texture_t *R_GetCurrentTexture(texture_t *t) +{ int i; const entity_render_t *ent = rsurface.entity; dp_model_t *model = ent->model; - float f; - float tcmat[12]; q3shaderinfo_layer_tcmod_t *tcmod; if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent) @@ -4807,70 +4873,21 @@ texture_t *R_GetCurrentTexture(texture_t *t) // there is no tcmod if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) + { t->currenttexmatrix = r_waterscrollmatrix; - - for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) + t->currentbackgroundtexmatrix = r_waterscrollmatrix; + } + else { - matrix4x4_t matrix; - switch(tcmod->tcmod) - { - case Q3TCMOD_COUNT: - case Q3TCMOD_NONE: - if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL) - 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, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1); - Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0); - break; - case Q3TCMOD_SCALE: - Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1); - break; - case Q3TCMOD_SCROLL: - Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0); - break; - case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures) - w = (int) tcmod->parms[0]; - h = (int) tcmod->parms[1]; - f = r_refdef.scene.time / (tcmod->parms[2] * w * h); - f = f - floor(f); - idx = (int) floor(f * w * h); - Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0); - break; - case Q3TCMOD_STRETCH: - f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms); - Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f); - break; - case Q3TCMOD_TRANSFORM: - VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0); - VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0); - VectorSet(tcmat + 6, 0 , 0 , 1); - VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[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 - { - matrix4x4_t temp = t->currenttexmatrix; - Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp); - } + Matrix4x4_CreateIdentity(&t->currenttexmatrix); + Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix); } + for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) + R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags); + for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) + R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags); + t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f); t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base; t->glosstexture = r_texture_black; @@ -6270,6 +6287,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t return; R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); + R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix); R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap)); R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture)); R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture)); diff --git a/model_shared.c b/model_shared.c index 60a59cfa..94c3b015 100644 --- a/model_shared.c +++ b/model_shared.c @@ -2012,6 +2012,9 @@ nothing GL_ZERO GL_ONE if (shader->backgroundlayer >= 0) { q3shaderinfo_layer_t* backgroundlayer = shader->layers + shader->backgroundlayer; + // copy over one secondarylayer parameter + memcpy(texture->backgroundtcmods, backgroundlayer->tcmods, sizeof(texture->backgroundtcmods)); + // load the textures texture->backgroundnumskinframes = backgroundlayer->numframes; texture->backgroundskinframerate = backgroundlayer->framerate; for (j = 0;j < backgroundlayer->numframes;j++) diff --git a/model_shared.h b/model_shared.h index cdcc846e..21637f73 100644 --- a/model_shared.h +++ b/model_shared.h @@ -465,12 +465,14 @@ typedef struct texture_s struct texture_s *currentframe; // current texture transform matrix (used for water scrolling) matrix4x4_t currenttexmatrix; + matrix4x4_t currentbackgroundtexmatrix; // various q3 shader features q3shaderinfo_layer_rgbgen_t rgbgen; q3shaderinfo_layer_alphagen_t alphagen; q3shaderinfo_layer_tcgen_t tcgen; q3shaderinfo_layer_tcmod_t tcmods[Q3MAXTCMODS]; + q3shaderinfo_layer_tcmod_t backgroundtcmods[Q3MAXTCMODS]; q3shaderinfo_deform_t deforms[Q3MAXDEFORMS]; qboolean colormapping; diff --git a/r_shadow.c b/r_shadow.c index f1815487..230b8d55 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -1737,6 +1737,7 @@ static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, else R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); + R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix); R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap)); R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture)); R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture)); @@ -1745,6 +1746,7 @@ static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap)); R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture)); R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture)); + R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow)); } //R_Mesh_TexBindCubeMap(GL20TU_CUBE, R_GetTexture(rsurface.rtlight->currentcubemap)); R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation)); -- 2.39.2