From a8bce569c8a82f5cffacaadea1f5ee9a972f6fda Mon Sep 17 00:00:00 2001 From: divverent Date: Wed, 3 Oct 2007 15:21:48 +0000 Subject: [PATCH] Cleaned up reflection and refraction a bit; added Q3 shader parameters dp_reflect and dp_refract for them; fixed simple reflection. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7603 d7cf8633-e32d-0410-b094-e92efae38249 --- darkplaces.txt | 12 ++++++++++++ gl_rmain.c | 33 ++++++++++++++++----------------- model_brush.c | 8 +++++++- model_shared.c | 33 +++++++++++++++++++++++++++++++++ model_shared.h | 11 +++++++++++ render.h | 1 + 6 files changed, 80 insertions(+), 18 deletions(-) diff --git a/darkplaces.txt b/darkplaces.txt index c5e96e89..6cf3f2d0 100644 --- a/darkplaces.txt +++ b/darkplaces.txt @@ -1308,3 +1308,15 @@ de-we for the great icons. |Rain| for running my favorite anynet IRC server and his bot feh (which although a bit antisocial never seems to grow tired of being my calculator). VorteX for the DP_QC_GETTAGINFO extension. Ludwig Nussel for the ~/.games/darkplaces/ user directory support on non-Windows platforms (allowing games to be installed in a non-writable system location as is the standard on UNIX but still save configs to the user's home directory). + + +Shader parameters for DP's own features: +- dp_reflect + Makes surfaces of this shader reflective with r_glsl_water. Factor is a + reflectiveness factor from 0 to 1, the rest is the color of the reflection. + Unspecified values get set to 1 (that is, standard water parameters). +- dp_refract + Marks a surface as "water" for r_glsl_water, that is, add a refraction + component too. The factor defines how strong the distorts by the refraction + are (default: 1.0). Unspecified values get set to 1 (that is, standard water + parameters). diff --git a/gl_rmain.c b/gl_rmain.c index da1bd813..b1f55d19 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -81,12 +81,6 @@ cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0 cvar_t r_glsl_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"}; cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"}; cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"}; -cvar_t r_glsl_water_refractcolor_r = {CVAR_SAVE, "r_glsl_water_refractcolor_r", "1", "water color tint for refraction"}; -cvar_t r_glsl_water_refractcolor_g = {CVAR_SAVE, "r_glsl_water_refractcolor_g", "1", "water color tint for refraction"}; -cvar_t r_glsl_water_refractcolor_b = {CVAR_SAVE, "r_glsl_water_refractcolor_b", "1", "water color tint for refraction"}; -cvar_t r_glsl_water_reflectcolor_r = {CVAR_SAVE, "r_glsl_water_reflectcolor_r", "1", "water color tint for reflection"}; -cvar_t r_glsl_water_reflectcolor_g = {CVAR_SAVE, "r_glsl_water_reflectcolor_g", "1", "water color tint for reflection"}; -cvar_t r_glsl_water_reflectcolor_b = {CVAR_SAVE, "r_glsl_water_reflectcolor_b", "1", "water color tint for reflection"}; cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"}; cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"}; cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"}; @@ -577,6 +571,7 @@ static const char *builtinshaderstring = "uniform vec4 ScreenCenterRefractReflect;\n" "uniform myhvec3 RefractColor;\n" "uniform myhvec3 ReflectColor;\n" +"uniform myhalf ReflectFactor;\n" "//#else\n" "//# ifdef USEREFLECTION\n" "//uniform vec4 DistortScaleRefractReflect;\n" @@ -784,14 +779,14 @@ static const char *builtinshaderstring = " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n" " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n" " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n" -" myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0));\n" +" myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0)) * ReflectFactor;\n" " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n" "# else\n" "# ifdef USEREFLECTION\n" " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n" " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n" " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n" -" color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw));\n" +" color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)), ReflectFactor);\n" "# endif\n" "# endif\n" "#endif\n" @@ -951,6 +946,7 @@ void R_GLSL_CompilePermutation(const char *filename, int permutation) p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect"); p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor"); p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor"); + p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor"); // initialize the samplers to refer to the texture units we use if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0); if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1); @@ -1272,11 +1268,12 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip); if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value); - if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value, r_glsl_water_refractdistort.value, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value); + if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value * rsurface.texture->refractfactor, r_glsl_water_refractdistort.value * rsurface.texture->refractfactor, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value); if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); - if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_RefractColor, r_glsl_water_refractcolor_r.value, r_glsl_water_refractcolor_g.value, r_glsl_water_refractcolor_b.value); - if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_ReflectColor, r_glsl_water_reflectcolor_r.value, r_glsl_water_reflectcolor_g.value, r_glsl_water_reflectcolor_b.value); + if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor); + if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor); + if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectfactor); CHECKGLERROR return permutation; } @@ -1758,12 +1755,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_glsl_water); Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier); Cvar_RegisterVariable(&r_glsl_water_clippingplanebias); - Cvar_RegisterVariable(&r_glsl_water_refractcolor_r); - Cvar_RegisterVariable(&r_glsl_water_refractcolor_g); - Cvar_RegisterVariable(&r_glsl_water_refractcolor_b); - Cvar_RegisterVariable(&r_glsl_water_reflectcolor_r); - Cvar_RegisterVariable(&r_glsl_water_reflectcolor_g); - Cvar_RegisterVariable(&r_glsl_water_reflectcolor_b); Cvar_RegisterVariable(&r_glsl_water_refractdistort); Cvar_RegisterVariable(&r_glsl_water_reflectdistort); Cvar_RegisterVariable(&r_glsl_deluxemapping); @@ -3826,9 +3817,17 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer)) { t->currentalpha *= r_wateralpha.value; + /* + * FIXME what is this supposed to do? // if rendering refraction/reflection, disable transparency if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA))) t->currentmaterialflags |= MATERIALFLAG_WATERSHADER; + */ + } + if(!r_waterstate.enabled) + { + t->currentmaterialflags &= ~MATERIALFLAG_WATERSHADER; + t->currentmaterialflags &= ~MATERIALFLAG_REFLECTION; } if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; diff --git a/model_brush.c b/model_brush.c index bbef49b5..a2bac292 100644 --- a/model_brush.c +++ b/model_brush.c @@ -1537,7 +1537,13 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) if (strncmp(tx->name,"*lava",5) && strncmp(tx->name,"*teleport",9) && strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture - tx->basematerialflags |= MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW; + { + tx->basematerialflags |= MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW | MATERIALFLAG_WATERSHADER; + VectorSet(tx->reflectcolor, 1, 1, 1); + VectorSet(tx->refractcolor, 1, 1, 1); + tx->reflectfactor = 1; + tx->refractfactor = 1; + } tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW; } else if (!strncmp(tx->name, "sky", 3)) diff --git a/model_shared.c b/model_shared.c index 3b381c58..655132e7 100644 --- a/model_shared.c +++ b/model_shared.c @@ -1133,7 +1133,13 @@ void Mod_LoadQ3Shaders(void) break; } shader = q3shaders_shaders + q3shaders_numshaders++; + memset(shader, 0, sizeof(*shader)); + VectorSet(shader->reflectcolor, 1, 1, 1); + VectorSet(shader->refractcolor, 1, 1, 1); + shader->reflectfactor = 1; + shader->refractfactor = 1; + strlcpy(shader->name, com_token, sizeof(shader->name)); if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{")) { @@ -1490,6 +1496,22 @@ void Mod_LoadQ3Shaders(void) shader->textureflags |= Q3TEXTUREFLAG_NOPICMIP; else if (!strcasecmp(parameter[0], "polygonoffset")) shader->textureflags |= Q3TEXTUREFLAG_POLYGONOFFSET; + else if (!strcasecmp(parameter[0], "dp_reflect")) + { + shader->textureflags |= Q3TEXTUREFLAG_REFLECTION; + if(numparameters >= 2) + shader->reflectfactor = atof(parameter[1]); + if(numparameters >= 5) + VectorSet(shader->reflectcolor, atof(parameter[2]), atof(parameter[3]), atof(parameter[4])); + } + else if (!strcasecmp(parameter[0], "dp_refract")) + { + shader->textureflags |= Q3TEXTUREFLAG_WATERSHADER; + if(numparameters >= 2) + shader->refractfactor = atof(parameter[1]); + if(numparameters >= 5) + VectorSet(shader->refractcolor, atof(parameter[2]), atof(parameter[3]), atof(parameter[4])); + } else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2) { int i, deformindex; @@ -1550,6 +1572,9 @@ void Mod_LoadQ3Shaders(void) shader->primarylayer = shader->layers + 1; } } + // fix up multiple reflection types + if(shader->textureflags & Q3TEXTUREFLAG_WATERSHADER) + shader->textureflags &= ~Q3TEXTUREFLAG_REFLECTION; } Mem_Free(f); } @@ -1605,6 +1630,10 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool texture->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; if (shader->textureflags & Q3TEXTUREFLAG_POLYGONOFFSET) texture->basepolygonoffset -= 2; + if (shader->textureflags & Q3TEXTUREFLAG_REFLECTION) + texture->basematerialflags |= MATERIALFLAG_REFLECTION; + if (shader->textureflags & Q3TEXTUREFLAG_WATERSHADER) + texture->basematerialflags |= MATERIALFLAG_WATERSHADER; texture->customblendfunc[0] = GL_ONE; texture->customblendfunc[1] = GL_ZERO; if (shader->numlayers > 0) @@ -1686,6 +1715,10 @@ nothing GL_ZERO GL_ONE } } memcpy(texture->deforms, shader->deforms, sizeof(texture->deforms)); + texture->reflectfactor = shader->reflectfactor; + texture->refractfactor = shader->refractfactor; + VectorCopy(shader->reflectcolor, texture->reflectcolor); + VectorCopy(shader->refractcolor, texture->refractcolor); } else if (!strcmp(texture->name, "noshader")) { diff --git a/model_shared.h b/model_shared.h index 2c4be375..c4b6fe91 100644 --- a/model_shared.h +++ b/model_shared.h @@ -187,6 +187,8 @@ shadowmesh_t; #define Q3TEXTUREFLAG_TWOSIDED 1 #define Q3TEXTUREFLAG_NOPICMIP 16 #define Q3TEXTUREFLAG_POLYGONOFFSET 32 +#define Q3TEXTUREFLAG_REFLECTION 256 +#define Q3TEXTUREFLAG_WATERSHADER 512 #define Q3PATHLENGTH 64 #define TEXTURE_MAXFRAMES 64 @@ -362,6 +364,10 @@ typedef struct q3shaderinfo_s q3shaderinfo_layer_t layers[Q3SHADER_MAXLAYERS]; char skyboxname[Q3PATHLENGTH]; q3shaderinfo_deform_t deforms[Q3MAXDEFORMS]; + + vec3_t reflectcolor, refractcolor; + float reflectfactor; // amount of reflection (1.0 = full, can't be larger) + float refractfactor; // amount of refraction distort (1.0 = like the cvar specifies; note that reflection distort is not configurable because that's what the bumpmap should do) } q3shaderinfo_t; @@ -474,6 +480,11 @@ typedef struct texture_s int supercontents; int surfaceparms; int textureflags; + + // reflection + vec3_t reflectcolor, refractcolor; + float reflectfactor; // amount of reflection (1.0 = full, can't be larger) + float refractfactor; // amount of refraction distort (1.0 = like the cvar specifies; note that reflection distort is not configurable because that's what the bumpmap should do) } texture_t; diff --git a/render.h b/render.h index 3fd24e90..fa024207 100644 --- a/render.h +++ b/render.h @@ -427,6 +427,7 @@ typedef struct r_glsl_permutation_s int loc_ScreenCenterRefractReflect; int loc_RefractColor; int loc_ReflectColor; + int loc_ReflectFactor; } r_glsl_permutation_t; -- 2.39.2