mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
-static int r_frame = 0; // used only by R_GetCurrentTexture
+static int r_frame = 0; ///< used only by R_GetCurrentTexture
//
// screen size info
//
r_refdef_t r_refdef;
+cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.7 recommended"};
+cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
+cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
+cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
+cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
+cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
+cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
+cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
+cvar_t r_motionblur_debug = {0, "r_motionblur_debug", "0", "outputs current motionblur alpha value"};
+
cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
int bloomwidth, bloomheight;
int screentexturewidth, screentextureheight;
- rtexture_t *texture_screen;
+ rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
int bloomtexturewidth, bloomtextureheight;
rtexture_t *texture_bloom;
r_waterstate_t r_waterstate;
-// shadow volume bsp struct with automatically growing nodes buffer
+/// shadow volume bsp struct with automatically growing nodes buffer
svbsp_t r_svbsp;
rtexture_t *r_texture_blanknormalmap;
char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
-// vertex coordinates for a quad that covers the screen exactly
+/// vertex coordinates for a quad that covers the screen exactly
const static float r_screenvertex3f[12] =
{
0, 0, 0,
"#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"
" 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"
" 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"
"#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"
" 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"
typedef enum shaderpermutation_e
{
- SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
- SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
- SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
- SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
- SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
- SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
- SHADERPERMUTATION_SATURATION = 1<<14, // user defined postprocessing
- SHADERPERMUTATION_LIMIT = 1<<15, // size of permutations array
- SHADERPERMUTATION_COUNT = 15 // size of shaderpermutationinfo array
+ SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
+ SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
+ SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
+ SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
+ SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
+ SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
+ SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
+ SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESATURATION\n", " saturation"},
};
-// this enum is multiplied by SHADERPERMUTATION_MODEBASE
+/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
typedef enum shadermode_e
{
- SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
- SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
- SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
- SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
- SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
- SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
- SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
- SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
- SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
- SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
- SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
- SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
+ SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
+ SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
+ SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
+ SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
+ SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
+ SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
+ SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
+ SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
+ SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
+ SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
+ SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
+ SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
SHADERMODE_COUNT
}
shadermode_t;
typedef struct r_glsl_permutation_s
{
- // indicates if we have tried compiling this permutation already
+ /// indicates if we have tried compiling this permutation already
qboolean compiled;
- // 0 if compilation failed
+ /// 0 if compilation failed
int program;
- // locations of detected uniforms in program object, or -1 if not found
+ /// locations of detected uniforms in program object, or -1 if not found
int loc_Texture_First;
int loc_Texture_Second;
int loc_Texture_GammaRamps;
int loc_DiffuseColor;
int loc_SpecularColor;
int loc_LightDir;
- int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
- int loc_GammaCoeff; // 1 / gamma
+ int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
+ int loc_GammaCoeff; ///< 1 / gamma
int loc_DistortScaleRefractReflect;
int loc_ScreenScaleRefractReflect;
int loc_ScreenCenterRefractReflect;
}
r_glsl_permutation_t;
-// information about each possible shader permutation
+/// information about each possible shader permutation
r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
-// currently selected permutation
+/// currently selected permutation
r_glsl_permutation_t *r_glsl_permutation;
static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
+ p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
Cvar_RegisterVariable (&gl_fogend);
Cvar_RegisterVariable (&gl_skyclip);
}
+ Cvar_RegisterVariable(&r_motionblur);
+ Cvar_RegisterVariable(&r_motionblur_maxblur);
+ Cvar_RegisterVariable(&r_motionblur_bmin);
+ Cvar_RegisterVariable(&r_motionblur_vmin);
+ Cvar_RegisterVariable(&r_motionblur_vmax);
+ Cvar_RegisterVariable(&r_motionblur_vcoeff);
+ Cvar_RegisterVariable(&r_motionblur_randomize);
+ Cvar_RegisterVariable(&r_damageblur);
+ Cvar_RegisterVariable(&r_motionblur_debug);
Cvar_RegisterVariable(&r_depthfirst);
Cvar_RegisterVariable(&r_useinfinitefarclip);
Cvar_RegisterVariable(&r_nearclip);
}
}
-// only used if skyrendermasked, and normally returns false
+/// only used if skyrendermasked, and normally returns false
int R_DrawBrushModelsSky (void)
{
int i, sky;
for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
}
- if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
+ if ((r_hdr.integer || r_bloom.integer || r_motionblur.value > 0 || r_damageblur.value > 0) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
{
Cvar_SetValueQuick(&r_hdr, 0);
Cvar_SetValueQuick(&r_bloom, 0);
+ Cvar_SetValueQuick(&r_motionblur, 0);
+ Cvar_SetValueQuick(&r_damageblur, 0);
}
- if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_glsl_saturation.value != 1 || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
+ if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_glsl_saturation.value != 1 || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && r_motionblur.value <= 0 && r_damageblur.value <= 0)
screentexturewidth = screentextureheight = 0;
if (!r_hdr.integer && !r_bloom.integer)
bloomtexturewidth = bloomtextureheight = 0;
{
if (r_bloomstate.texture_screen)
{
- // copy view into the screen texture
+ // make sure the buffer is available
+ if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
+
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
GL_ActiveTexture(0);CHECKGLERROR
+
+ if(r_motionblur.value > 0 || r_damageblur.value > 0)
+ {
+ // declare alpha variable
+ float a;
+ float speed;
+ static float avgspeed;
+
+ speed = VectorLength(cl.movement_velocity);
+
+ a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
+ avgspeed = avgspeed * (1 - a) + speed * a;
+
+ speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
+ speed = bound(0, speed, 1);
+ speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
+
+ // calculate values into a standard alpha
+ a = 1 - exp(-
+ (
+ (r_motionblur.value * speed / 80)
+ +
+ (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
+ )
+ /
+ max(0.0001, cl.time - cl.oldtime) // fps independent
+ );
+
+ a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
+ a = bound(0, a, r_motionblur_maxblur.value);
+
+ // developer debug of current value
+ if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
+
+ // apply the blur
+ if (a > 0)
+ {
+ R_SetupGenericShader(true);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ }
+ }
+
+ // copy view into the screen texture
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
}
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)
// 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;
VectorSubtract(end, start, up);
VectorNormalize(up);
// calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
- //VectorSubtract(rsurface.modelorg, center, forward);
- Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
+ VectorSubtract(rsurface.modelorg, center, forward);
+ //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
VectorNegate(forward, forward);
VectorReflect(forward, 0, up, forward);
VectorNormalize(forward);
float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
{
- float l, d, eyedir[3];
- VectorSubtract(rsurface.modelorg, vertex, eyedir);
- l = 0.5f / VectorLength(eyedir);
- d = DotProduct(normal, eyedir)*2;
- out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
- out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
+
+ float viewer[3], d, reflected[3], worldreflected[3];
+
+ VectorSubtract(rsurface.modelorg, vertex, viewer);
+ // VectorNormalize(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];
+ // note: this is proportinal to viewer, so we can normalize later
+
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
+
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ out_tc[0] = 0.5 + 0.5 * worldreflected[1];
+ out_tc[1] = 0.5 - 0.5 * worldreflected[2];
}
}
rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
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));
R_SetupGenericShader(false);
if(rsurface.texture && rsurface.texture->currentskinframe)
+ {
memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
+ c[3] *= rsurface.texture->currentalpha;
+ }
else
{
c[0] = 1;