diff --git a/engine/client/client.h b/engine/client/client.h index 6c351bea9..5d65fdc7e 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -285,7 +285,6 @@ typedef struct dlight_s } face [6]; int style; //multiply by style values if > 0 float fov; //spotlight - float dist; struct dlight_s *next; } dlight_t; diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index c4558438e..b744b105b 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1826,6 +1826,7 @@ void CLQ2_CalcViewValues (void) q2centity_t *ent; q2frame_t *oldframe; q2player_state_t *ps, *ops; + extern cvar_t gl_cshiftenabled; r_refdef.useperspective = true; @@ -1900,8 +1901,9 @@ void CLQ2_CalcViewValues (void) r_refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov); // don't interpolate blend color - for (i=0 ; i<4 ; i++) + for (i=0 ; i<3 ; i++) sw_blend[i] = ps->blend[i]; + sw_blend[3] = ps->blend[3]*gl_cshiftenabled.value; // add the weapon CLQ2_AddViewWeapon (ps, ops); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index e5addd10e..4e6c983ca 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1942,7 +1942,7 @@ void Surf_SetupFrame(void) leaf = RMod_PointInLeaf (cl.worldmodel, r_origin); r_viewcluster = r_viewcluster2 = leaf->cluster; - r_viewcontents = 0;//leaf->contents; + r_viewcontents = leaf->contents & (FTECONTENTS_LAVA|FTECONTENTS_SLIME|FTECONTENTS_WATER); // check above and below so crossing solid water doesn't draw wrong if (!leaf->contents) diff --git a/engine/client/skin.c b/engine/client/skin.c index 23bc0e01f..624b205d8 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -158,7 +158,7 @@ void Skin_Find (player_info_t *sc) *s = '\0'; #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) - model = Mod_ForName(va("players/%s/tris.mdl", name), false); + model = Mod_ForName(va("players/%s/tris.md2", name), false); else #endif model = NULL;//Mod_ForName(va("models/players/%s.mdl", name), false); diff --git a/engine/common/fs.c b/engine/common/fs.c index bef9d1380..8f38cfc22 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1785,6 +1785,8 @@ void COM_Gamedir (const char *dir) #define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n" /*set some stuff so our regular qw client appears more like hexen2*/ #define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx/hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n" +/*yay q2!*/ +#define Q2CFG "gl_font \":?col=0.44 1 0.2\"\n" /*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/ #define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\n" #define RMQCFG "sv_bigcoords 1\n" @@ -1825,7 +1827,7 @@ const gamemode_info_t gamemode_info[] = { {"-portals", "h2mp", "FTE-H2MP", {"portals/hexen.rc", "portals/pak3.pak"}, HEX2CFG,{"data1", "portals", "fteh2"}, "Hexen II MP"}, {"-hexen2", "hexen2", "FTE-Hexen2", {"data1/pak0.pak"}, HEX2CFG,{"data1", "fteh2"}, "Hexen II"}, - {"-q2", "q2", "FTE-Quake2", {"baseq2/pak0.pak"}, NULL, {"baseq2", "fteq2"}, "Quake II"}, + {"-q2", "q2", "FTE-Quake2", {"baseq2/pak0.pak"}, Q2CFG, {"baseq2", "fteq2"}, "Quake II"}, {"-q3", "q3", "FTE-Quake3", {"baseq3/pak0.pk3"}, Q3CFG, {"baseq3", "fteq3"}, "Quake III Arena"}, //can run in windows, needs diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index bb592f0f4..66e55c024 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1221,7 +1221,7 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac if (out->flags & TI_SKY) snprintf(sname, sizeof(sname), "sky/%s", in->texture); else if (out->flags & (TI_WARP|TI_TRANS33|TI_TRANS66)) - snprintf(sname, sizeof(sname), "%s%s/%s", ((out->flags&TI_WARP)?"warp":"trans"), ((out->flags&TI_TRANS66)?"66":(out->flags&TI_TRANS33?"33":"")), in->texture); + snprintf(sname, sizeof(sname), "%s/%s#ALPHA=%s", ((out->flags&TI_WARP)?"warp":"trans"), in->texture, ((out->flags&TI_TRANS66)?"0.66":(out->flags&TI_TRANS33?"0.33":"1"))); else snprintf(sname, sizeof(sname), "wall/%s", in->texture); diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 7fcba2922..d1020de38 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -70,7 +70,6 @@ enum extern cvar_t r_glsl_offsetmapping, r_noportals; static void BE_SendPassBlendDepthMask(unsigned int sbits); -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); void GLBE_SubmitBatch(batch_t *batch); static qboolean GLBE_RegisterLightShader(int mode); @@ -103,6 +102,7 @@ struct { int fbo_reflection; texid_t tex_reflection; /*basically a portal rendered to texture*/ texid_t tex_refraction; /*the (culled) underwater view*/ + texid_t tex_refractiondepth; /*the (culled) underwater view*/ texid_t tex_ripplemap; /*temp image for waves and things.*/ qboolean force2d; @@ -184,6 +184,7 @@ struct { texid_t lighttexture; texid_t lightcubemap; float lightprojmatrix[16]; /*world space*/ + vec4_t lightshadowmapinfo; }; int wbatch; @@ -940,8 +941,13 @@ void R_IBrokeTheArrays(void) #ifdef RTLIGHTS //called from gl_shadow -void GLBE_SetupForShadowMap(texid_t shadowmaptex) +void GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale) { + shaderstate.lightshadowmapinfo[0] = 1.0/texwidth; + shaderstate.lightshadowmapinfo[1] = 1.0/texwidth; + shaderstate.lightshadowmapinfo[2] = 1.0; + shaderstate.lightshadowmapinfo[3] = shadowscale; + shaderstate.curshadowmap = shadowmaptex; while(shaderstate.lastpasstmus>0) { @@ -1101,6 +1107,9 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) } t = shaderstate.tex_refraction; break; + case T_GEN_REFRACTIONDEPTH: + t = shaderstate.tex_refractiondepth; + break; case T_GEN_RIPPLEMAP: t = shaderstate.tex_ripplemap; break; @@ -2893,6 +2902,9 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, qglUniformMatrix4fvARB(ph, 1, false, t); } break; + case SP_LIGHTSHADOWMAPINFO: + qglUniform4fvARB(ph, 1, shaderstate.lightshadowmapinfo); + break; /*static lighting info*/ case SP_E_L_DIR: @@ -3882,7 +3894,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) if ((batch->shader->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects) { - vrect_t orect = r_refdef.vrect; + vrect_t orect = r_refdef.vrect, oprect = r_refdef.pxrect; if (!shaderstate.tex_reflection.num) { shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth/2, vid.pixelheight/2, 0); @@ -3894,25 +3906,32 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } GL_ForceDepthWritable(); - GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, true); + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, r_nulltex, true); qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); r_refdef.vrect.x = 0; r_refdef.vrect.y = 0; r_refdef.vrect.width = vid.width/2; r_refdef.vrect.height = vid.height/2; + r_refdef.pxrect.x = 0; + r_refdef.pxrect.width = vid.pixelwidth/2; + r_refdef.pxrect.height = vid.pixelheight/2; + r_refdef.pxrect.y = r_refdef.pxrect.height; GL_ForceDepthWritable(); qglClearColor(0, 0, 0, 0); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLR_DrawPortal(batch, cl.worldmodel->batches, 1); - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); r_refdef.vrect = orect; + r_refdef.pxrect = oprect; } - if (batch->shader->flags & SHADER_HASREFRACT) + if (batch->shader->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH)) { if (r_refract_fboival) { - vrect_t orect; + vrect_t ovrect = r_refdef.vrect, oprect = r_refdef.pxrect; + GL_ForceDepthWritable(); + if (!shaderstate.tex_refraction.num) { shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth/2, vid.pixelheight/2, 0); @@ -3923,31 +3942,49 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - GL_ForceDepthWritable(); - GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, true); + if (batch->shader->flags & SHADER_HASREFRACTDEPTH) + { + if (!shaderstate.tex_refractiondepth.num) + { + shaderstate.tex_refractiondepth = GL_AllocNewTexture("***tex_refractiondepth***", vid.pixelwidth/2, vid.pixelheight/2, 0); + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refractiondepth); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, shaderstate.tex_refractiondepth, true); + } + else + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, r_nulltex, true); qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); - orect = r_refdef.vrect; r_refdef.vrect.x = 0; r_refdef.vrect.y = 0; r_refdef.vrect.width = vid.width/2; r_refdef.vrect.height = vid.height/2; + r_refdef.pxrect.x = 0; + r_refdef.pxrect.width = vid.pixelwidth/2; + r_refdef.pxrect.height = vid.pixelheight/2; + r_refdef.pxrect.y = r_refdef.pxrect.height; GL_ForceDepthWritable(); qglClearColor(0, 0, 0, 0); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - GLR_DrawPortal(batch, cl.worldmodel->batches, 2); - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + GLR_DrawPortal(batch, cl.worldmodel->batches, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); - r_refdef.vrect = orect; + r_refdef.vrect = ovrect; + r_refdef.pxrect = oprect; } else GLR_DrawPortal(batch, cl.worldmodel->batches, 3); } if ((batch->shader->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects) { - vrect_t orect; + vrect_t orect = r_refdef.vrect, oprect = r_refdef.pxrect; if (!shaderstate.tex_ripplemap.num) { shaderstate.tex_ripplemap = GL_AllocNewTexture("***tex_ripplemap***", vid.pixelwidth/2, vid.pixelheight/2, 0); @@ -3958,13 +3995,16 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_ripplemap, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_ripplemap, r_nulltex, false); qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2); - orect = r_refdef.vrect; r_refdef.vrect.x = 0; r_refdef.vrect.y = 0; r_refdef.vrect.width = vid.width/2; r_refdef.vrect.height = vid.height/2; + r_refdef.pxrect.x = 0; + r_refdef.pxrect.width = vid.pixelwidth/2; + r_refdef.pxrect.height = vid.pixelheight/2; + r_refdef.pxrect.y = r_refdef.pxrect.height; qglClearColor(0, 0, 0, 0); qglClear(GL_COLOR_BUFFER_BIT); @@ -3974,10 +4014,11 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) r_refdef.recurse = true; //paranoid, should stop potential infinite loops GLBE_SubmitMeshes(true, SHADER_SORT_RIPPLE, SHADER_SORT_RIPPLE); r_refdef.recurse = false; - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); r_refdef.vrect = orect; + r_refdef.pxrect = oprect; } BE_SelectMode(oldbem); } @@ -4084,7 +4125,7 @@ void GLBE_BaseEntTextures(void) } #endif -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth) +void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, texid_t destdepth, qboolean usedepth) { shaderstate.tex_sourcecol = sourcecol; shaderstate.tex_sourcedepth = sourcedepth; @@ -4109,11 +4150,12 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco } else { + qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth/2, vid.pixelheight/2); + qglGenRenderbuffersEXT(1, &shaderstate.rb_stencil); + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, shaderstate.rb_stencil); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, vid.pixelwidth/2, vid.pixelheight/2); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, shaderstate.rb_stencil); - - qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth/2, vid.pixelheight/2); } qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, shaderstate.rb_depth); @@ -4122,6 +4164,11 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco } else qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse); + + if (destdepth.num) + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, destdepth.num, 0); + else + qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, shaderstate.rb_depth); } else { @@ -4303,6 +4350,11 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis) R_DestroyTexture(shaderstate.tex_refraction); shaderstate.tex_refraction = r_nulltex; } + if (shaderstate.tex_refractiondepth.num) + { + R_DestroyTexture(shaderstate.tex_refractiondepth); + shaderstate.tex_refractiondepth = r_nulltex; + } if (shaderstate.temptexture.num) { R_DestroyTexture(shaderstate.temptexture); diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 63f01b2af..205b0042a 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -60,8 +60,6 @@ static int texwidth[MAXLEVELS], texheight[MAXLEVELS]; -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); - void R_BloomRegister(void) { Cvar_Register (&r_bloom, "bloom"); @@ -194,13 +192,13 @@ void R_BloomBlend (void) qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.y - r_refdef.pxrect.height, r_refdef.pxrect.width, r_refdef.pxrect.height); /*filter the screen into a downscaled image*/ - GLBE_RenderToTexture(scrtex, r_nulltex, pingtex[0][0], false); + GLBE_RenderToTexture(scrtex, r_nulltex, pingtex[0][0], r_nulltex, false); qglViewport (0, 0, texwidth[0], texheight[0]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter); /*and downscale that multiple times*/ for (i = 1; i < MAXLEVELS; i++) { - GLBE_RenderToTexture(pingtex[0][i-1], r_nulltex, pingtex[0][i], false); + GLBE_RenderToTexture(pingtex[0][i-1], r_nulltex, pingtex[0][i], r_nulltex, false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale); } @@ -211,7 +209,7 @@ void R_BloomBlend (void) /*must be 1.2th of a pixel*/ r_worldentity.glowmod[0] = 1.2 / texwidth[i]; r_worldentity.glowmod[1] = 0; - GLBE_RenderToTexture(pingtex[0][i], r_nulltex, pingtex[1][i], false); + GLBE_RenderToTexture(pingtex[0][i], r_nulltex, pingtex[1][i], r_nulltex, false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); } @@ -219,7 +217,7 @@ void R_BloomBlend (void) { r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[1] = 1.2 / texheight[i]; - GLBE_RenderToTexture(pingtex[1][i], r_nulltex, pingtex[0][i], false); + GLBE_RenderToTexture(pingtex[1][i], r_nulltex, pingtex[0][i], r_nulltex, false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); } @@ -227,7 +225,7 @@ void R_BloomBlend (void) GL_Set2D(false); /*combine them onto the screen*/ - GLBE_RenderToTexture(scrtex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(scrtex, r_nulltex, r_nulltex, r_nulltex, false); R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y + r_refdef.vrect.height, r_refdef.vrect.width, -r_refdef.vrect.height, bloomfinal); } void R_InitBloomTextures(void) diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index df48bae6b..84adac4bd 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -194,6 +194,7 @@ typedef struct font_s void *membuf; #endif struct font_s *alt; + vec3_t alttint; } font_t; typedef struct { @@ -962,6 +963,8 @@ struct font_s *Font_LoadFont(int vheight, char *fontfilename) f->charheight = height; Q_strncpyz(f->name, fontfilename, sizeof(f->name)); + VectorSet(f->alttint, 1.16, 0.54, 0.41); + #ifdef DOOMWADS if (!*fontfilename) { @@ -1087,7 +1090,17 @@ struct font_s *Font_LoadFont(int vheight, char *fontfilename) if (aname) { *aname = 0; - f->alt = Font_LoadFont(vheight, aname+1); + if (!strncmp(aname+1, "?col=", 5)) + { + char *t = aname+6; + f->alttint[0] = strtod(t, &t); + if (*t == ' ') t++; + f->alttint[1] = strtod(t, &t); + if (*t == ' ') t++; + f->alttint[2] = strtod(t, &t); + } + else + f->alt = Font_LoadFont(vheight, aname+1); } if (!Font_LoadFreeTypeFont(f, height, fontfilename)) { @@ -1507,9 +1520,9 @@ int Font_DrawChar(int px, int py, unsigned int charcode) if (charcode & CON_2NDCHARSETTEXT) { - font_forecolour[0] = min(font_forecolour[0]*1.16, 255); - font_forecolour[1] *= 0.54; - font_forecolour[2] *= 0.41; + font_forecolour[0] = min(font_forecolour[0]*font->alttint[0], 255); + font_forecolour[1] = min(font_forecolour[1]*font->alttint[1], 255); + font_forecolour[2] = min(font_forecolour[2]*font->alttint[2], 255); } } } @@ -1678,9 +1691,9 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode) if (charcode & CON_2NDCHARSETTEXT) { - font_forecolour[0] = min(font_forecolour[0]*1.16, 255); - font_forecolour[1] *= 0.54; - font_forecolour[2] *= 0.41; + font_forecolour[0] = min(font_forecolour[0]*font->alttint[0], 255); + font_forecolour[1] = min(font_forecolour[1]*font->alttint[1], 255); + font_forecolour[2] = min(font_forecolour[2]*font->alttint[2], 255); } } } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index ca3326f95..b0695af07 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -153,8 +153,8 @@ void GL_SetupSceneProcessingTextures (void) if (!gl_config.arb_shader_objects) return; - TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0)); - TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0)); + TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, IF_NOMIPMAP|IF_NOGAMMA)); + TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, IF_NOMIPMAP|IF_NOGAMMA)); // init warp texture - this specifies offset in for (y=0; y=100)//gl_nv_range_clamp) @@ -1058,7 +1064,6 @@ void GLR_SetupFog (void) } #endif -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); static void R_RenderMotionBlur(void) { int vwidth = 1, vheight = 1; @@ -1097,10 +1102,10 @@ static void R_RenderMotionBlur(void) "}\n" "}\n" ); - GLBE_RenderToTexture(sceneblur_texture, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(sceneblur_texture, r_nulltex, r_nulltex, r_nulltex, false); R2D_ImageColours(1, 1, 1, gl_motionblur.value); R2D_Image(0, 0, vid.width, vid.height, cs-vs, ct+vt, cs+vs, ct-vt, shader); - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); //grab the current image so we can feed that back into the next frame. GL_MTBind(0, GL_TEXTURE_2D, sceneblur_texture); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index f133bf454..7773e42a0 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -169,7 +169,26 @@ skipwhite: return com_token; } +static float Shader_FloatArgument(shader_t *shader, char *arg) +{ + char *var; + int arglen = strlen(arg); + //grab an argument instead, otherwise 0 + var = shader->name; + while(var = strchr(var, '#')) + { + if (!strnicmp(var, arg, arglen)) + { + if (var[arglen] == '=') + return strtod(var+arglen+1, NULL); + if (var[arglen] == '#' || !var[arglen]) + return 1; //present, but no value + } + var++; + } + return 0; //not present. +} @@ -207,11 +226,10 @@ void *shader_active_hash_mem; //static float r_skyheight; char *Shader_Skip( char *ptr ); -static qboolean Shader_Parsetok( shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, - char *token, char **ptr ); -static void Shader_ParseFunc( char **args, shaderfunc_t *func ); -static void Shader_MakeCache( char *path ); -static void Shader_GetPathAndOffset( char *name, char **path, unsigned int *offset ); +static qboolean Shader_Parsetok(shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, char *token, char **ptr); +static void Shader_ParseFunc(shader_t *shader, char **args, shaderfunc_t *func); +static void Shader_MakeCache(char *path); +static void Shader_GetPathAndOffset(char *name, char **path, unsigned int *offset); static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode); //=========================================================================== @@ -230,24 +248,26 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) if (*token == '$') { token++; - if (!Q_stricmp(token, "lpp")) + if (*token == '#') + conditiontrue = conditiontrue == !!Shader_FloatArgument(shader, token); + else if (!Q_stricmp(token, "lpp")) conditiontrue = conditiontrue == r_lightprepass.ival; else if (!Q_stricmp(token, "lightmap")) conditiontrue = conditiontrue == !r_fullbright.value; - else if (!Q_stricmp(token, "deluxmap") ) + else if (!Q_stricmp(token, "deluxmap")) conditiontrue = conditiontrue == r_deluxemapping.ival; //normalmaps are generated if they're not already known. - else if (!Q_stricmp(token, "normalmap") ) + else if (!Q_stricmp(token, "normalmap")) conditiontrue = conditiontrue == r_loadbumpmapping; - else if (!Q_stricmp(token, "opengl") ) + else if (!Q_stricmp(token, "opengl")) conditiontrue = conditiontrue == (qrenderer == QR_OPENGL); - else if (!Q_stricmp(token, "d3d9") ) + else if (!Q_stricmp(token, "d3d9")) conditiontrue = conditiontrue == (qrenderer == QR_DIRECT3D9); - else if (!Q_stricmp(token, "d3d11") ) + else if (!Q_stricmp(token, "d3d11")) conditiontrue = conditiontrue == (qrenderer == QR_DIRECT3D11); - else if (!Q_stricmp(token, "gles") ) + else if (!Q_stricmp(token, "gles")) { #ifdef GLQUAKE conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && !!gl_config.gles); @@ -255,7 +275,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) conditiontrue = conditiontrue == false; #endif } - else if (!Q_stricmp(token, "nofixed") ) + else if (!Q_stricmp(token, "nofixed")) { switch(qrenderer) { @@ -274,7 +294,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) break; } } - else if (!Q_stricmp(token, "glsl") ) + else if (!Q_stricmp(token, "glsl")) { #ifdef GLQUAKE conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && gl_config.arb_shader_objects); @@ -282,7 +302,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) conditiontrue = conditiontrue == false; #endif } - else if (!Q_stricmp(token, "hlsl") ) + else if (!Q_stricmp(token, "hlsl")) { switch(qrenderer) { @@ -301,11 +321,11 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) break; } } - else if (!Q_stricmp(token, "haveprogram") ) + else if (!Q_stricmp(token, "haveprogram")) { conditiontrue = conditiontrue == !!shader->prog; } - else if (!Q_stricmp(token, "programs") ) + else if (!Q_stricmp(token, "programs")) { switch(qrenderer) { @@ -329,15 +349,15 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) break; } } - else if (!Q_stricmp(token, "diffuse") ) + else if (!Q_stricmp(token, "diffuse")) conditiontrue = conditiontrue == true; - else if (!Q_stricmp(token, "specular") ) + else if (!Q_stricmp(token, "specular")) conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "fullbright") ) + else if (!Q_stricmp(token, "fullbright")) conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "topoverlay") ) + else if (!Q_stricmp(token, "topoverlay")) conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "loweroverlay") ) + else if (!Q_stricmp(token, "loweroverlay")) conditiontrue = conditiontrue == false; else { @@ -396,27 +416,23 @@ static char *Shader_ParseExactString(char **ptr) { char *token; - if ( !ptr || !(*ptr) ) { + if (!ptr || !(*ptr)) return ""; - } - if ( !**ptr || **ptr == '}' ) { + if (!**ptr || **ptr == '}') return ""; - } token = COM_ParseExt(ptr, false, false); return token; } -static char *Shader_ParseString ( char **ptr ) +static char *Shader_ParseString(char **ptr) { char *token; - if ( !ptr || !(*ptr) ) { + if (!ptr || !(*ptr)) return ""; - } - if ( !**ptr || **ptr == '}' ) { + if (!**ptr || **ptr == '}') return ""; - } token = COM_ParseExt(ptr, false, true); Q_strlwr ( token ); @@ -424,52 +440,53 @@ static char *Shader_ParseString ( char **ptr ) return token; } -static char *Shader_ParseSensString ( char **ptr ) +static char *Shader_ParseSensString(char **ptr) { char *token; - if ( !ptr || !(*ptr) ) { + if (!ptr || !(*ptr)) return ""; - } - if ( !**ptr || **ptr == '}' ) { + if (!**ptr || **ptr == '}') return ""; - } token = COM_ParseExt(ptr, false, true); return token; } -static float Shader_ParseFloat(char **ptr) +static float Shader_ParseFloat(shader_t *shader, char **ptr) { char *token; if (!ptr || !(*ptr)) - { return 0; - } if (!**ptr || **ptr == '}') - { return 0; - } token = COM_ParseExt(ptr, false, true); if (*token == '$') { - cvar_t *var; - var = Cvar_FindVar(token+1); - if (var) - return var->value; + if (token[1] == '#') + { + return Shader_FloatArgument(shader, token+1); + } + else + { + cvar_t *var; + var = Cvar_FindVar(token+1); + if (var) + return var->value; + } } return atof(token); } -static void Shader_ParseVector ( char **ptr, vec3_t v ) +static void Shader_ParseVector(shader_t *shader, char **ptr, vec3_t v) { char *scratch; char *token; qboolean bracket; - token = Shader_ParseString ( ptr ); + token = Shader_ParseString(ptr); if (*token == '$') { cvar_t *var; @@ -485,20 +502,23 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) ptr = &scratch; scratch = var->string; - token = Shader_ParseString ( ptr ); + token = Shader_ParseString( ptr); } - if ( !Q_stricmp (token, "(") ) { + if (!Q_stricmp (token, "(")) + { bracket = true; - token = Shader_ParseString ( ptr ); - } else if ( token[0] == '(' ) { + token = Shader_ParseString(ptr); + } + else if (token[0] == '(') + { bracket = true; token = &token[1]; - } else { - bracket = false; } + else + bracket = false; v[0] = atof ( token ); - v[1] = Shader_ParseFloat ( ptr ); + v[1] = Shader_ParseFloat (shader, ptr ); token = Shader_ParseString ( ptr ); if ( !token[0] ) { @@ -582,29 +602,28 @@ qboolean Shader_ParseSkySides (char *shadername, char *texturename, texid_t *ima return allokay; } -static void Shader_ParseFunc ( char **ptr, shaderfunc_t *func ) +static void Shader_ParseFunc (shader_t *shader, char **ptr, shaderfunc_t *func) { char *token; - token = Shader_ParseString ( ptr ); - if ( !Q_stricmp (token, "sin") ) { + token = Shader_ParseString (ptr); + if (!Q_stricmp (token, "sin")) func->type = SHADER_FUNC_SIN; - } else if ( !Q_stricmp (token, "triangle") ) { + else if (!Q_stricmp (token, "triangle")) func->type = SHADER_FUNC_TRIANGLE; - } else if ( !Q_stricmp (token, "square") ) { + else if (!Q_stricmp (token, "square")) func->type = SHADER_FUNC_SQUARE; - } else if ( !Q_stricmp (token, "sawtooth") ) { + else if (!Q_stricmp (token, "sawtooth")) func->type = SHADER_FUNC_SAWTOOTH; - } else if (!Q_stricmp (token, "inversesawtooth") ) { + else if (!Q_stricmp (token, "inversesawtooth")) func->type = SHADER_FUNC_INVERSESAWTOOTH; - } else if (!Q_stricmp (token, "noise") ) { + else if (!Q_stricmp (token, "noise")) func->type = SHADER_FUNC_NOISE; - } - func->args[0] = Shader_ParseFloat ( ptr ); - func->args[1] = Shader_ParseFloat ( ptr ); - func->args[2] = Shader_ParseFloat ( ptr ); - func->args[3] = Shader_ParseFloat ( ptr ); + func->args[0] = Shader_ParseFloat (shader, ptr); + func->args[1] = Shader_ParseFloat (shader, ptr); + func->args[2] = Shader_ParseFloat (shader, ptr); + func->args[3] = Shader_ParseFloat (shader, ptr); } //=========================================================================== @@ -697,46 +716,52 @@ static void Shader_DeformVertexes ( shader_t *shader, shaderpass_t *pass, char * char *token; deformv_t *deformv; - if ( shader->numdeforms >= SHADER_DEFORM_MAX ) { + if ( shader->numdeforms >= SHADER_DEFORM_MAX ) return; - } deformv = &shader->deforms[shader->numdeforms]; token = Shader_ParseString ( ptr ); - if ( !Q_stricmp (token, "wave") ) { + if ( !Q_stricmp (token, "wave") ) + { deformv->type = DEFORMV_WAVE; - deformv->args[0] = Shader_ParseFloat ( ptr ); - if ( deformv->args[0] ) { + deformv->args[0] = Shader_ParseFloat (shader, ptr); + if (deformv->args[0]) deformv->args[0] = 1.0f / deformv->args[0]; - } - - Shader_ParseFunc ( ptr, &deformv->func ); - } else if ( !Q_stricmp (token, "normal") ) { + Shader_ParseFunc (shader, ptr, &deformv->func ); + } + else if ( !Q_stricmp (token, "normal") ) + { deformv->type = DEFORMV_NORMAL; - deformv->args[0] = Shader_ParseFloat ( ptr ); - deformv->args[1] = Shader_ParseFloat ( ptr ); - } else if ( !Q_stricmp (token, "bulge") ) { + deformv->args[0] = Shader_ParseFloat (shader, ptr ); + deformv->args[1] = Shader_ParseFloat (shader, ptr ); + } + else if ( !Q_stricmp (token, "bulge") ) + { deformv->type = DEFORMV_BULGE; - - Shader_ParseVector ( ptr, deformv->args ); + Shader_ParseVector (shader, ptr, deformv->args ); shader->flags |= SHADER_DEFORMV_BULGE; - } else if ( !Q_stricmp (token, "move") ) { + } + else if ( !Q_stricmp (token, "move") ) + { deformv->type = DEFORMV_MOVE; - - Shader_ParseVector ( ptr, deformv->args ); - Shader_ParseFunc ( ptr, &deformv->func ); - } else if ( !Q_stricmp (token, "autosprite") ) { + Shader_ParseVector (shader, ptr, deformv->args ); + Shader_ParseFunc (shader, ptr, &deformv->func ); + } + else if ( !Q_stricmp (token, "autosprite") ) + { deformv->type = DEFORMV_AUTOSPRITE; shader->flags |= SHADER_AUTOSPRITE; - } else if ( !Q_stricmp (token, "autosprite2") ) { + } + else if ( !Q_stricmp (token, "autosprite2") ) + { deformv->type = DEFORMV_AUTOSPRITE2; shader->flags |= SHADER_AUTOSPRITE; - } else if ( !Q_stricmp (token, "projectionShadow") ) { - deformv->type = DEFORMV_PROJECTION_SHADOW; - } else { - return; } + else if ( !Q_stricmp (token, "projectionShadow") ) + deformv->type = DEFORMV_PROJECTION_SHADOW; + else + return; shader->numdeforms++; } @@ -759,7 +784,7 @@ static void Shader_SkyParms(shader_t *shader, shaderpass_t *pass, char **ptr) boxname = Shader_ParseString(ptr); Shader_ParseSkySides(shader->name, boxname, skydome->farbox_textures); - skyheight = Shader_ParseFloat(ptr); + skyheight = Shader_ParseFloat(shader, ptr); if (!skyheight) { skyheight = 512.0f; @@ -782,7 +807,7 @@ static void Shader_FogParms ( shader_t *shader, shaderpass_t *pass, char **ptr ) // else div = 1.0f; - Shader_ParseVector ( ptr, color ); + Shader_ParseVector (shader, ptr, color ); VectorScale ( color, div, color ); ColorNormalize ( color, fcolor ); @@ -790,7 +815,7 @@ static void Shader_FogParms ( shader_t *shader, shaderpass_t *pass, char **ptr ) shader->fog_color[1] = FloatToByte ( fcolor[1] ); shader->fog_color[2] = FloatToByte ( fcolor[2] ); shader->fog_color[3] = 255; - shader->fog_dist = Shader_ParseFloat ( ptr ); + shader->fog_dist = Shader_ParseFloat (shader, ptr ); if ( shader->fog_dist <= 0.0f ) { shader->fog_dist = 128.0f; @@ -1519,14 +1544,14 @@ void Shader_WriteOutGenerics_f(void) if (sbuiltins[i].qrtype == QR_OPENGL) { if (sbuiltins[i].apiver == 100) - name = va("gles/%s.glsl", sbuiltins[i].name); + name = va("gles/eg_%s.glsl", sbuiltins[i].name); else - name = va("glsl/%s.glsl", sbuiltins[i].name); + name = va("glsl/eg_%s.glsl", sbuiltins[i].name); } else if (sbuiltins[i].qrtype == QR_DIRECT3D9) - name = va("hlsl/%s.hlsl", sbuiltins[i].name); + name = va("hlsl/eg_%s.hlsl", sbuiltins[i].name); else if (sbuiltins[i].qrtype == QR_DIRECT3D11) - name = va("hlsl11/%s.hlsl", sbuiltins[i].name); + name = va("hlsl11/eg_%s.hlsl", sbuiltins[i].name); if (name) { @@ -1609,6 +1634,7 @@ struct shader_field_names_s shader_unif_names[] = {"l_lightcolourscale", SP_LIGHTCOLOURSCALE}, {"l_projmatrix", SP_LIGHTPROJMATRIX}, {"l_cubematrix", SP_LIGHTCUBEMATRIX}, + {"l_shadowmapinfo", SP_LIGHTSHADOWMAPINFO}, {"e_rendertexturescale", SP_RENDERTEXTURESCALE}, {NULL} @@ -2195,6 +2221,12 @@ static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *t pass->texgen = T_GEN_REFRACTION; pass->tcgen = TC_GEN_BASE; //FIXME: moo! } + else if (!Q_stricmp (tname, "$refractiondepth")) + { + shader->flags |= SHADER_HASREFRACT; + pass->texgen = T_GEN_REFRACTIONDEPTH; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } else if (!Q_stricmp (tname, "$ripplemap")) { shader->flags |= SHADER_HASRIPPLEMAP; @@ -2238,7 +2270,7 @@ static void Shaderpass_AnimMap (shader_t *shader, shaderpass_t *pass, char **ptr pass->tcgen = TC_GEN_BASE; pass->flags |= SHADER_PASS_ANIMMAP; pass->texgen = T_GEN_ANIMMAP; - pass->anim_fps = (int)Shader_ParseFloat (ptr); + pass->anim_fps = (int)Shader_ParseFloat (shader, ptr); pass->anim_numframes = 0; for ( ; ; ) @@ -2340,7 +2372,7 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr) else if (!Q_stricmp (token, "wave")) { pass->rgbgen = RGB_GEN_WAVE; - Shader_ParseFunc ( ptr, &pass->rgbgen_func); + Shader_ParseFunc (shader, ptr, &pass->rgbgen_func); } else if (!Q_stricmp(token, "entity")) pass->rgbgen = RGB_GEN_ENTITY; @@ -2359,7 +2391,7 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr) pass->rgbgen = RGB_GEN_CONST; pass->rgbgen_func.type = SHADER_FUNC_CONSTANT; - Shader_ParseVector (ptr, pass->rgbgen_func.args); + Shader_ParseVector (shader, ptr, pass->rgbgen_func.args); } else if (!Q_stricmp (token, "topcolor")) pass->rgbgen = RGB_GEN_TOPCOLOR; @@ -2375,7 +2407,7 @@ static void Shaderpass_AlphaGen (shader_t *shader, shaderpass_t *pass, char **pt if (!Q_stricmp (token, "portal")) { pass->alphagen = ALPHA_GEN_PORTAL; - shader->portaldist = Shader_ParseFloat(ptr); + shader->portaldist = Shader_ParseFloat(shader, ptr); if (!shader->portaldist) shader->portaldist = 256; shader->flags |= SHADER_AGEN_PORTAL; @@ -2392,7 +2424,7 @@ static void Shaderpass_AlphaGen (shader_t *shader, shaderpass_t *pass, char **pt { pass->alphagen = ALPHA_GEN_WAVE; - Shader_ParseFunc (ptr, &pass->alphagen_func); + Shader_ParseFunc (shader, ptr, &pass->alphagen_func); } else if ( !Q_stricmp (token, "lightingspecular")) { @@ -2402,7 +2434,7 @@ static void Shaderpass_AlphaGen (shader_t *shader, shaderpass_t *pass, char **pt { pass->alphagen = ALPHA_GEN_CONST; pass->alphagen_func.type = SHADER_FUNC_CONSTANT; - pass->alphagen_func.args[0] = fabs(Shader_ParseFloat(ptr)); + pass->alphagen_func.args[0] = fabs(Shader_ParseFloat(shader, ptr)); } } static void Shaderpass_AlphaShift (shader_t *shader, shaderpass_t *pass, char **ptr) //for alienarena @@ -2419,9 +2451,9 @@ static void Shaderpass_AlphaShift (shader_t *shader, shaderpass_t *pass, char ** //arg2 = timeshift //arg3 = timescale - speed = Shader_ParseFloat(ptr); - min = Shader_ParseFloat(ptr); - max = Shader_ParseFloat(ptr); + speed = Shader_ParseFloat(shader, ptr); + min = Shader_ParseFloat(shader, ptr); + max = Shader_ParseFloat(shader, ptr); pass->alphagen_func.args[0] = min + (max - min)/2; pass->alphagen_func.args[1] = (max - min)/2; @@ -2597,7 +2629,7 @@ static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) token = Shader_ParseString (ptr); if (!Q_stricmp (token, "rotate")) { - tcmod->args[0] = -Shader_ParseFloat(ptr) / 360.0f; + tcmod->args[0] = -Shader_ParseFloat(shader, ptr) / 360.0f; if (!tcmod->args[0]) { return; @@ -2607,21 +2639,21 @@ static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) } else if ( !Q_stricmp (token, "scale") ) { - tcmod->args[0] = Shader_ParseFloat (ptr); - tcmod->args[1] = Shader_ParseFloat (ptr); + tcmod->args[0] = Shader_ParseFloat (shader, ptr); + tcmod->args[1] = Shader_ParseFloat (shader, ptr); tcmod->type = SHADER_TCMOD_SCALE; } else if ( !Q_stricmp (token, "scroll") ) { - tcmod->args[0] = Shader_ParseFloat (ptr); - tcmod->args[1] = Shader_ParseFloat (ptr); + tcmod->args[0] = Shader_ParseFloat (shader, ptr); + tcmod->args[1] = Shader_ParseFloat (shader, ptr); tcmod->type = SHADER_TCMOD_SCROLL; } else if (!Q_stricmp(token, "stretch")) { shaderfunc_t func; - Shader_ParseFunc(ptr, &func); + Shader_ParseFunc(shader, ptr, &func); tcmod->args[0] = func.type; for (i = 1; i < 5; ++i) @@ -2631,13 +2663,13 @@ static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) else if (!Q_stricmp (token, "transform")) { for (i = 0; i < 6; ++i) - tcmod->args[i] = Shader_ParseFloat (ptr); + tcmod->args[i] = Shader_ParseFloat (shader, ptr); tcmod->type = SHADER_TCMOD_TRANSFORM; } else if (!Q_stricmp (token, "turb")) { for (i = 0; i < 4; i++) - tcmod->args[i] = Shader_ParseFloat (ptr); + tcmod->args[i] = Shader_ParseFloat (shader, ptr); tcmod->type = SHADER_TCMOD_TURB; } else @@ -2658,10 +2690,10 @@ static void Shaderpass_Scale ( shader_t *shader, shaderpass_t *pass, char **ptr tcmod->type = SHADER_TCMOD_SCALE; - token = Shader_ParseString ( ptr ); + token = Shader_ParseString (ptr); if (!strcmp(token, "static")) { - tcmod->args[0] = Shader_ParseFloat ( ptr ); + tcmod->args[0] = Shader_ParseFloat (shader, ptr); } else { @@ -2673,10 +2705,10 @@ static void Shaderpass_Scale ( shader_t *shader, shaderpass_t *pass, char **ptr if (**ptr == ',') *ptr+=1; - token = Shader_ParseString ( ptr ); + token = Shader_ParseString (ptr); if (!strcmp(token, "static")) { - tcmod->args[1] = Shader_ParseFloat ( ptr ); + tcmod->args[1] = Shader_ParseFloat (shader, ptr); } else { @@ -2686,7 +2718,7 @@ static void Shaderpass_Scale ( shader_t *shader, shaderpass_t *pass, char **ptr pass->numtcmods++; } -static void Shaderpass_Scroll ( shader_t *shader, shaderpass_t *pass, char **ptr ) +static void Shaderpass_Scroll (shader_t *shader, shaderpass_t *pass, char **ptr) { //seperate x and y char *token; @@ -2698,7 +2730,7 @@ static void Shaderpass_Scroll ( shader_t *shader, shaderpass_t *pass, char **ptr if (!strcmp(token, "static")) { tcmod->type = SHADER_TCMOD_SCROLL; - tcmod->args[0] = Shader_ParseFloat ( ptr ); + tcmod->args[0] = Shader_ParseFloat (shader, ptr ); } else { @@ -2710,7 +2742,7 @@ static void Shaderpass_Scroll ( shader_t *shader, shaderpass_t *pass, char **ptr if (!strcmp(token, "static")) { tcmod->type = SHADER_TCMOD_SCROLL; - tcmod->args[1] = Shader_ParseFloat ( ptr ); + tcmod->args[1] = Shader_ParseFloat (shader, ptr ); } else { @@ -2767,22 +2799,22 @@ static void Shaderpass_NoLightMap ( shader_t *shader, shaderpass_t *pass, char * static void Shaderpass_Red(shader_t *shader, shaderpass_t *pass, char **ptr) { pass->rgbgen = RGB_GEN_CONST; - pass->rgbgen_func.args[0] = Shader_ParseFloat(ptr); + pass->rgbgen_func.args[0] = Shader_ParseFloat(shader, ptr); } static void Shaderpass_Green(shader_t *shader, shaderpass_t *pass, char **ptr) { pass->rgbgen = RGB_GEN_CONST; - pass->rgbgen_func.args[1] = Shader_ParseFloat(ptr); + pass->rgbgen_func.args[1] = Shader_ParseFloat(shader, ptr); } static void Shaderpass_Blue(shader_t *shader, shaderpass_t *pass, char **ptr) { pass->rgbgen = RGB_GEN_CONST; - pass->rgbgen_func.args[2] = Shader_ParseFloat(ptr); + pass->rgbgen_func.args[2] = Shader_ParseFloat(shader, ptr); } static void Shaderpass_Alpha(shader_t *shader, shaderpass_t *pass, char **ptr) { pass->alphagen = ALPHA_GEN_CONST; - pass->alphagen_func.args[0] = Shader_ParseFloat(ptr); + pass->alphagen_func.args[0] = Shader_ParseFloat(shader, ptr); } static void Shaderpass_MaskColor(shader_t *shader, shaderpass_t *pass, char **ptr) { @@ -2806,7 +2838,7 @@ static void Shaderpass_MaskAlpha(shader_t *shader, shaderpass_t *pass, char **pt } static void Shaderpass_AlphaTest(shader_t *shader, shaderpass_t *pass, char **ptr) { - if (Shader_ParseFloat(ptr) == 0.5) + if (Shader_ParseFloat(shader, ptr) == 0.5) pass->shaderbits |= SBITS_ATEST_GE128; else Con_Printf("unsupported alphatest value\n"); @@ -4171,6 +4203,7 @@ void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args) char *Shader_DefaultBSPWater(char *shortname) { int wstyle; + if (r_wateralpha.value == 0) wstyle = -1; else if (r_fastturb.ival) @@ -4184,118 +4217,137 @@ char *Shader_DefaultBSPWater(char *shortname) else wstyle = 1; - { #ifdef GLQUAKE - if (wstyle > 2 && !gl_config.ext_framebuffer_objects) - wstyle = 2; + if (wstyle > 2 && !gl_config.ext_framebuffer_objects) + wstyle = 2; #endif - switch(wstyle) - { - case -1: //invisible - return ( + switch(wstyle) + { + case -1: //invisible + return ( + "{\n" + "surfaceparm nodraw\n" + "surfaceparm nodlight\n" + "}\n" + ); + case 0: //fastturb + return ( + "{\n" "{\n" - "surfaceparm nodraw\n" - "surfaceparm nodlight\n" + "map $whiteimage\n" + "rgbgen const $r_fastturbcolour\n" "}\n" - ); - case 0: //fastturb - return ( + "surfaceparm nodlight\n" + "}\n" + ); + default: + case 1: //vanilla style + return ( + "{\n" + "program defaultwarp\n" "{\n" - "{\n" - "map $whiteimage\n" - "rgbgen const $r_fastturbcolour\n" - "}\n" - "surfaceparm nodlight\n" - "}\n" - ); - default: - case 1: //vanilla style - return ( - "{\n" - "program defaultwarp\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0.02 0.1 0.5 0.1\n" - "if r_wateralpha != 1\n" + "map $diffuse\n" + "tcmod turb 0.02 0.1 0.5 0.1\n" + "if !$#ALPHA\n" + "[\n" + "if r_wateralpha < 1\n" "[\n" "alphagen const $r_wateralpha\n" "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" "]\n" - "}\n" - "surfaceparm nodlight\n" + "][\n" + "if $#ALPHA < 1\n" + "[\n" + "alphagen const $#ALPHA\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" + "]\n" + "]\n" "}\n" - ); - case 2: //refraction of the underwater surface, with a fresnel - return ( + "surfaceparm nodlight\n" + "}\n" + ); + case 2: //refraction of the underwater surface, with a fresnel + return ( + "{\n" + "surfaceparm nodlight\n" "{\n" - "surfaceparm nodlight\n" - "{\n" - "map $refraction\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $diffuse\n" - "}\n" - "program altwater#FRESNEL=4\n" + "map $refraction\n" "}\n" - ); - case 3: //reflections - return ( "{\n" - "surfaceparm nodlight\n" - "{\n" - "map $refraction\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $reflection\n" - "}\n" - "program altwater#REFLECT#FRESNEL=4\n" + "map $normalmap\n" "}\n" - ); - case 4: //ripples - return ( "{\n" - "surfaceparm nodlight\n" - "{\n" - "map $refraction\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $diffuse\n" - "}\n" - "{\n" - "map $ripplemap\n" - "}\n" - "program altwater#RIPPLEMAP#FRESNEL=4\n" + "map $diffuse\n" "}\n" - ); - case 5: //ripples+reflections - return ( +// "{\n" +// "map $refractiondepth\n" +// "}\n" + "program altwater#FRESNEL=4\n" + "}\n" + ); + case 3: //reflections + return ( + "{\n" + "surfaceparm nodlight\n" "{\n" - "surfaceparm nodlight\n" - "{\n" - "map $refraction\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $reflection\n" - "}\n" - "{\n" - "map $ripplemap\n" - "}\n" - "program altwater#REFLECT#RIPPLEMAP#FRESNEL=4\n" + "map $refraction\n" "}\n" - ); - } + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $reflection\n" + "}\n" +// "{\n" +// "map $refractiondepth\n" +// "}\n" + "program altwater#REFLECT#FRESNEL=4\n" + "}\n" + ); + case 4: //ripples + return ( + "{\n" + "surfaceparm nodlight\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" +// "{\n" +// "map $refractiondepth\n" +// "}\n" + "{\n" + "map $ripplemap\n" + "}\n" + "program altwater#RIPPLEMAP#FRESNEL=4\n" + "}\n" + ); + case 5: //ripples+reflections + return ( + "{\n" + "surfaceparm nodlight\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $reflection\n" + "}\n" +// "{\n" +// "map $refractiondepth\n" +// "}\n" + "{\n" + "map $ripplemap\n" + "}\n" + "program altwater#REFLECT#RIPPLEMAP#FRESNEL=4\n" + "}\n" + ); } } @@ -4310,62 +4362,16 @@ void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args) "}\n" ); } - else if (!strncmp(shortname, "warp/", 5)) + else if (!strncmp(shortname, "warp/", 5) || !strncmp(shortname, "warp33/", 7) || !strncmp(shortname, "warp66/", 7)) { Shader_DefaultScript(shortname, s, Shader_DefaultBSPWater(shortname)); } - else if (!strncmp(shortname, "warp33/", 7)) - { + else if (!strncmp(shortname, "trans/", 6)) Shader_DefaultScript(shortname, s, "{\n" "{\n" "map $diffuse\n" - "tcmod turb 0 0.01 0.5 0\n" - "alphagen const 0.333\n" - "blendfunc blend\n" - "}\n" - "}\n" - ); - } - else if (!strncmp(shortname, "warp66/", 7)) - { - Shader_DefaultScript(shortname, s, - "{\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0 0.01 0.5 0\n" - "alphagen const 0.666\n" - "blendfunc blend\n" - "}\n" - "}\n" - ); - } - else if (!strncmp(shortname, "trans/", 7)) - Shader_DefaultScript(shortname, s, - "{\n" - "{\n" - "map $diffuse\n" - "alphagen const 1\n" - "blendfunc blend\n" - "}\n" - "}\n" - ); - else if (!strncmp(shortname, "trans33/", 7)) - Shader_DefaultScript(shortname, s, - "{\n" - "{\n" - "map $diffuse\n" - "alphagen const 0.333\n" - "blendfunc blend\n" - "}\n" - "}\n" - ); - else if (!strncmp(shortname, "trans66/", 7)) - Shader_DefaultScript(shortname, s, - "{\n" - "{\n" - "map $diffuse\n" - "alphagen const 0.666\n" + "alphagen const $#ALPHA\n" "blendfunc blend\n" "}\n" "}\n" @@ -4798,8 +4804,15 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena if (!*name) name = "gfx/white"; - *(int*)shortname = 0; - COM_StripExtension ( name, shortname, sizeof(shortname)); + if (strchr(name, '#')) + { + Q_strncpyz(shortname, name, sizeof(shortname)); + } + else + { + *(int*)shortname = 0; + COM_StripExtension ( name, shortname, sizeof(shortname)); + } COM_CleanUpPath(shortname); diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index e9a56b07b..e37427cb5 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1940,15 +1940,13 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) } } -static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float proj[16]) +static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int smsize, float proj[16]) { qboolean oxv; vec3_t t1,t2, t3; texture_t *tex; int tno; - int smsize = SHADOWMAP_SIZE; - //FIXME: figure out the four lines bounding the light cone by just adding its +forward+/-right+/-up values. if any point towards a plane (and starts outside that plane), and the point of intersection with that line and the frustum side plane is infront of the near clip plane, then that light frustum needs to be rendered... switch(face) { @@ -1998,7 +1996,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p qglViewport (0, 0, smsize, smsize); else { - qglViewport ((face%3 * smsize), ((face>=3)*smsize), smsize, smsize); + qglViewport ((face%3 * SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2, ((face>=3)*SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2, smsize, smsize); } //fixme @@ -2082,22 +2080,22 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) { if (isspot) { - shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize, smsize, 0); + shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dspot***", SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0); GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]); #ifdef DBG_COLOURNOTDEPTH qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #else - qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); #endif } else { - shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize*3, smsize*2, 0); + shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dcube***", SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0); GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]); #ifdef DBG_COLOURNOTDEPTH qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize*3, smsize*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #else - qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize*3, smsize*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); #endif } @@ -2121,7 +2119,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) /*set framebuffer*/ GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]); - GLBE_SetupForShadowMap(shadowmap[isspot]); + GLBE_SetupForShadowMap(shadowmap[isspot], isspot?smsize:smsize*3, isspot?smsize:smsize*2, smsize / (float)SHADOWMAP_SIZE); qglViewport(0, 0, smsize*3, smsize*2); qglClear (GL_DEPTH_BUFFER_BIT); @@ -2135,17 +2133,19 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) if (l->fov) { Matrix4x4_CM_Projection_Far(r_refdef.m_projection, l->fov, l->fov, nearplane, l->radius); - qglMatrixMode(GL_PROJECTION); - qglLoadMatrixf(r_refdef.m_projection); - qglMatrixMode(GL_MODELVIEW); + if (!gl_config.nofixedfunc) + { + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(r_refdef.m_projection); + qglMatrixMode(GL_MODELVIEW); + } /*single face*/ - Sh_GenShadowFace(l, smesh, 0, r_refdef.m_projection); + Sh_GenShadowFace(l, smesh, 0, smsize, r_refdef.m_projection); } else { Matrix4x4_CM_Projection_Far(r_refdef.m_projection, 90, 90, nearplane, l->radius); - if (!gl_config.nofixedfunc) { qglMatrixMode(GL_PROJECTION); @@ -2156,7 +2156,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) /*generate faces*/ for (f = 0; f < 6; f++) { - Sh_GenShadowFace(l, smesh, f, r_refdef.m_projection); + Sh_GenShadowFace(l, smesh, f, smsize, r_refdef.m_projection); } } /*end framebuffer*/ @@ -2210,7 +2210,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) if (vvis) { - if (l->worldshadowmesh) + if (!l->rebuildcache && l->worldshadowmesh) { lvis = l->worldshadowmesh->litleaves; //fixme: check head node first? @@ -2831,7 +2831,6 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop); -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) { @@ -2903,19 +2902,19 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) Sh_ScissorOff(); - GLBE_RenderToTexture(r_nulltex, r_nulltex, crepuscular_texture_id, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, crepuscular_texture_id, r_nulltex, false); BE_SelectMode(BEM_CREPUSCULAR); BE_SelectDLight(dl, colours); GLBE_SubmitMeshes(true, SHADER_SORT_PORTAL, SHADER_SORT_BLEND); - GLBE_RenderToTexture(crepuscular_texture_id, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(crepuscular_texture_id, r_nulltex, r_nulltex, r_nulltex, false); BE_SelectMode(BEM_STANDARD); GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0); - GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); #endif } diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 5b0b4cbd3..ae51e15a3 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -27,6 +27,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifndef TINT\n" "#define TINT vec3(0.7, 0.8, 0.7)\n" "#endif\n" +"#ifndef FOGTINT\n" +"#define FOGTINT vec3(0.2, 0.3, 0.2)\n" +"#endif\n" "varying vec2 tc;\n" "varying vec4 tf;\n" @@ -49,17 +52,27 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform sampler2D s_t0; //refract\n" "uniform sampler2D s_t1; //normalmap\n" "uniform sampler2D s_t2; //diffuse/reflection\n" +"#ifdef DEPTH\n" +"uniform sampler2D s_t3; //refraction depth\n" +"#ifdef RIPPLEMAP\n" +"uniform sampler2D s_t4; //ripplemap\n" +"#endif\n" +"#else\n" "#ifdef RIPPLEMAP\n" "uniform sampler2D s_t3; //ripplemap\n" "#endif\n" +"#endif\n" "uniform float e_time;\n" "void main (void)\n" "{\n" "vec2 stc, ntc;\n" -"vec3 n, refr, refl, fres;\n" -"float f;\n" +"vec3 n, refr, refl;\n" +"float fres;\n" +"float depth;\n" "stc = (1.0 + (tf.xy / tf.w)) * 0.5;\n" +//hack the texture coords slightly so that there are no obvious gaps +"stc.t -= 1.5*norm.z/1080.0;\n" //apply q1-style warp, just for kicks "ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" @@ -71,25 +84,61 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "n -= 1.0 - 4.0/256.0;\n" "#ifdef RIPPLEMAP\n" -"n += texture2D(s_t3, stc).rgb*3.0;\n" +"n += texture2D(s_t4, stc).rgb*3.0;\n" "#endif\n" //the fresnel term decides how transparent the water should be -"f = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n" +"fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n" +"#ifdef DEPTH\n" +"float far = #include \"cvar/gl_maxdist\";\n" +"float near = #include \"cvar/gl_mindist\";\n" +//get depth value at the surface +"float sdepth = gl_FragCoord.z;\n" +"sdepth = (2.0*near) / (far + near - sdepth * (far - near));\n" +"sdepth = mix(near, far, sdepth);\n" + +//get depth value at the ground beyond the surface. +"float gdepth = texture2D(s_t3, stc).x;\n" +"gdepth = (2.0*near) / (far + near - gdepth * (far - near));\n" +"if (gdepth >= 0.5)\n" +"{\n" +"gdepth = sdepth;\n" +"depth = 0.0;\n" +"}\n" +"else\n" +"{\n" +"gdepth = mix(near, far, gdepth);\n" +"depth = gdepth - sdepth;\n" +"}\n" + +//reduce the normals in shallow water (near walls, reduces the pain of linear sampling) +"if (depth < 100)\n" +"n *= depth/100.0;\n" +"#else\n" +"depth = 1;\n" +"#endif \n" + + +//refraction image (and water fog, if possible) "refr = texture2D(s_t0, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT;\n" +"#ifdef DEPTH\n" +"refr = mix(refr, FOGTINT, min(depth/4096, 1));\n" +"#endif\n" + +//reflection/diffuse "#ifdef REFLECT\n" "refl = texture2D(s_t2, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb;\n" "#else\n" "refl = texture2D(s_t2, ntc).xyz;\n" "#endif\n" -// refl += 0.1*pow(dot(n, vec3(0.0,0.0,1.0)), 64.0); +//FIXME: add specular -"fres = refr * (1.0-f) + refl*f;\n" +//interplate by fresnel +"refr = mix(refr, refl, fres);\n" -// fres = texture2D(s_t2, stc).xyz; - -"gl_FragColor = vec4(fres, 1.0);\n" +//done +"gl_FragColor = vec4(refr, 1.0);\n" "}\n" "#endif\n" }, @@ -1090,14 +1139,19 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D s_t0;\n" "uniform float e_time;\n" +"#ifndef ALPHA\n" "uniform float cvar_r_wateralpha;\n" +"#define USEALPHA cvar_r_wateralpha\n" +"#else\n" +"#define USEALPHA float(ALPHA)\n" +"#endif\n" "void main ()\n" "{\n" "vec2 ntc;\n" "ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" "ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" "vec3 ts = vec3(texture2D(s_t0, ntc));\n" -"gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha));\n" +"gl_FragColor = fog4(vec4(ts, USEALPHA));\n" "}\n" "#endif\n" }, @@ -1584,6 +1638,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform float l_lightradius;\n" "uniform vec3 l_lightcolour;\n" "uniform vec3 l_lightcolourscale;\n" +"#ifdef PCF\n" +"uniform vec4 l_shadowmapinfo; //xy are the texture scale, z is 1, w is the scale.\n" +"#endif\n" @@ -1593,12 +1650,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "float ShadowmapFilter(void)\n" "{\n" -"#ifdef SPOT\n" -"const vec3 texscale = vec3(1.0/512.0, 1.0/512.0, 1.0);\n" -"#else\n" -"const vec3 texscale = vec3(1.0/(512.0*3.0), 1.0/(512.0*2.0), 1.0);\n" -"#endif\n" - //dehomogonize input "vec3 shadowcoord = (vtexprojcoord.xyz / vtexprojcoord.w);\n" @@ -1644,6 +1695,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "vec4 nsc =l_projmatrix*vec4(t, 1.0);\n" "shadowcoord = (nsc.xyz / nsc.w);\n" +//scale to match the light's precision and pinch inwards, so we never sample over the edge +"shadowcoord.st *= l_shadowmapinfo.w * (1.0-l_shadowmapinfo.st);\n" + //now bias and relocate it "shadowcoord = (shadowcoord + axis.xyz) * vec3(0.5/3.0, 0.5/2.0, 0.5);\n" "#endif\n" @@ -1663,7 +1717,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n" "#else\n" -"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*texscale.xyz)).r\n" +"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapinfo.xyz)).r\n" "float s = 0.0;\n" "s += dosamp(-1.0, -1.0);\n" "s += dosamp(-1.0, 0.0);\n" @@ -1854,18 +1908,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform float cvar_r_waterwarp;\n" "void main ()\n" "{\n" -"float amptemp;\n" -"vec3 edge;\n" -"edge = texture2D( s_t2, v_edge ).rgb;\n" -"amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x;\n" -"vec3 offset;\n" -"offset = texture2D( s_t1, v_warp ).rgb;\n" -"offset.x = (offset.x - 0.5) * 2.0;\n" -"offset.y = (offset.y - 0.5) * 2.0;\n" -"vec2 temp;\n" -"temp.x = v_stc.x + offset.x * amptemp;\n" -"temp.y = v_stc.y + offset.y * amptemp;\n" -"gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st );\n" +"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;\n" +"vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;\n" +"vec2 temp = v_stc + offset.xy * amp;\n" +"gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);\n" "}\n" "#endif\n" }, diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 4c905217c..61bb3e993 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -229,6 +229,7 @@ typedef struct shaderpass_s { T_GEN_REFLECTION, //reflection image (mirror-as-fbo) T_GEN_REFRACTION, //refraction image (portal-as-fbo) + T_GEN_REFRACTIONDEPTH, //refraction image (portal-as-fbo) T_GEN_RIPPLEMAP, //ripplemap image (water surface distortions-as-fbo) T_GEN_SOURCECUBE, //used for render-to-texture targets @@ -337,6 +338,7 @@ typedef struct { SP_LIGHTSCREEN, SP_LIGHTPROJMATRIX, SP_LIGHTCUBEMATRIX, + SP_LIGHTSHADOWMAPINFO, //things that are set immediatly SP_FIRSTIMMEDIATE, //never set @@ -430,9 +432,10 @@ struct shader_s SHADER_STATICDATA = 1 << 18, //set if true: no deforms, no tcgen, rgbgen=identitylighting, alphagen=identity, tmu0=st + tmu1=lm(if available) for every pass, no norms SHADER_HASREFLECT = 1 << 19, //says that we need to generate a reflection image first SHADER_HASREFRACT = 1 << 20, //says that we need to generate a refraction image first - SHADER_HASNORMALMAP = 1 << 21, //says that we need to load a normalmap texture - SHADER_HASRIPPLEMAP = 1 << 22, //water surface disturbances for water splashes - SHADER_HASGLOSS = 1 << 23, // + SHADER_HASREFRACTDEPTH = 1 << 21, //refraction generation needs to generate a depth texture too. + SHADER_HASNORMALMAP = 1 << 22, //says that we need to load a normalmap texture + SHADER_HASRIPPLEMAP = 1 << 23, //water surface disturbances for water splashes + SHADER_HASGLOSS = 1 << 24, // } flags; program_t *prog; @@ -510,6 +513,7 @@ qboolean GLBE_LightCullModel(vec3_t org, model_t *model); void GLBE_SelectEntity(entity_t *ent); void GLBE_SelectDLight(dlight_t *dl, vec3_t colour); void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop); +void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, texid_t destdepth, qboolean usedepth); #endif #ifdef D3D9QUAKE void D3D9BE_Init(void); @@ -566,7 +570,7 @@ void BE_GenerateProgram(shader_t *shader); // void GLBE_PushOffsetShadow(qboolean foobar); //sets up gl for depth-only FIXME -void GLBE_SetupForShadowMap(texid_t shadowmaptex); +void GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale); //Called from shadowmapping code into backend void GLBE_BaseEntTextures(void); void D3D9BE_BaseEntTextures(void); diff --git a/engine/shaders/glsl/altwater.glsl b/engine/shaders/glsl/altwater.glsl index b3cc932c0..d5cfbaea3 100644 --- a/engine/shaders/glsl/altwater.glsl +++ b/engine/shaders/glsl/altwater.glsl @@ -20,6 +20,9 @@ uniform float cvar_r_glsl_turbscale; #ifndef TINT #define TINT vec3(0.7, 0.8, 0.7) #endif +#ifndef FOGTINT +#define FOGTINT vec3(0.2, 0.3, 0.2) +#endif varying vec2 tc; varying vec4 tf; @@ -42,17 +45,27 @@ void main (void) uniform sampler2D s_t0; //refract uniform sampler2D s_t1; //normalmap uniform sampler2D s_t2; //diffuse/reflection +#ifdef DEPTH +uniform sampler2D s_t3; //refraction depth +#ifdef RIPPLEMAP +uniform sampler2D s_t4; //ripplemap +#endif +#else #ifdef RIPPLEMAP uniform sampler2D s_t3; //ripplemap #endif +#endif uniform float e_time; void main (void) { vec2 stc, ntc; - vec3 n, refr, refl, fres; - float f; + vec3 n, refr, refl; + float fres; + float depth; stc = (1.0 + (tf.xy / tf.w)) * 0.5; + //hack the texture coords slightly so that there are no obvious gaps + stc.t -= 1.5*norm.z/1080.0; //apply q1-style warp, just for kicks ntc.s = tc.s + sin(tc.t+e_time)*0.125; @@ -64,24 +77,60 @@ void main (void) n -= 1.0 - 4.0/256.0; #ifdef RIPPLEMAP - n += texture2D(s_t3, stc).rgb*3.0; + n += texture2D(s_t4, stc).rgb*3.0; #endif //the fresnel term decides how transparent the water should be - f = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL)); + fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL)); +#ifdef DEPTH + float far = #include "cvar/gl_maxdist"; + float near = #include "cvar/gl_mindist"; + //get depth value at the surface + float sdepth = gl_FragCoord.z; + sdepth = (2.0*near) / (far + near - sdepth * (far - near)); + sdepth = mix(near, far, sdepth); + + //get depth value at the ground beyond the surface. + float gdepth = texture2D(s_t3, stc).x; + gdepth = (2.0*near) / (far + near - gdepth * (far - near)); + if (gdepth >= 0.5) + { + gdepth = sdepth; + depth = 0.0; + } + else + { + gdepth = mix(near, far, gdepth); + depth = gdepth - sdepth; + } + + //reduce the normals in shallow water (near walls, reduces the pain of linear sampling) + if (depth < 100) + n *= depth/100.0; +#else + depth = 1; +#endif + + + //refraction image (and water fog, if possible) refr = texture2D(s_t0, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT; +#ifdef DEPTH + refr = mix(refr, FOGTINT, min(depth/4096, 1)); +#endif + + //reflection/diffuse #ifdef REFLECT refl = texture2D(s_t2, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb; #else refl = texture2D(s_t2, ntc).xyz; #endif -// refl += 0.1*pow(dot(n, vec3(0.0,0.0,1.0)), 64.0); + //FIXME: add specular - fres = refr * (1.0-f) + refl*f; + //interplate by fresnel + refr = mix(refr, refl, fres); -// fres = texture2D(s_t2, stc).xyz; - - gl_FragColor = vec4(fres, 1.0); + //done + gl_FragColor = vec4(refr, 1.0); } #endif diff --git a/engine/shaders/glsl/defaultwarp.glsl b/engine/shaders/glsl/defaultwarp.glsl index c2005933c..df120aac9 100644 --- a/engine/shaders/glsl/defaultwarp.glsl +++ b/engine/shaders/glsl/defaultwarp.glsl @@ -17,13 +17,18 @@ void main () #ifdef FRAGMENT_SHADER uniform sampler2D s_t0; uniform float e_time; +#ifndef ALPHA uniform float cvar_r_wateralpha; +#define USEALPHA cvar_r_wateralpha +#else +#define USEALPHA float(ALPHA) +#endif void main () { vec2 ntc; ntc.s = tc.s + sin(tc.t+e_time)*0.125; ntc.t = tc.t + sin(tc.s+e_time)*0.125; vec3 ts = vec3(texture2D(s_t0, ntc)); - gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha)); + gl_FragColor = fog4(vec4(ts, USEALPHA)); } #endif diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl index 83ba78e20..fce8ec589 100644 --- a/engine/shaders/glsl/rtlight.glsl +++ b/engine/shaders/glsl/rtlight.glsl @@ -106,6 +106,9 @@ uniform vec3 e_uppercolour; uniform float l_lightradius; uniform vec3 l_lightcolour; uniform vec3 l_lightcolourscale; +#ifdef PCF +uniform vec4 l_shadowmapinfo; //xy are the texture scale, z is 1, w is the scale. +#endif @@ -115,12 +118,6 @@ uniform vec3 l_lightcolourscale; float ShadowmapFilter(void) { -#ifdef SPOT - const vec3 texscale = vec3(1.0/512.0, 1.0/512.0, 1.0); -#else - const vec3 texscale = vec3(1.0/(512.0*3.0), 1.0/(512.0*2.0), 1.0); -#endif - //dehomogonize input vec3 shadowcoord = (vtexprojcoord.xyz / vtexprojcoord.w); @@ -166,6 +163,9 @@ float ShadowmapFilter(void) vec4 nsc =l_projmatrix*vec4(t, 1.0); shadowcoord = (nsc.xyz / nsc.w); + //scale to match the light's precision and pinch inwards, so we never sample over the edge + shadowcoord.st *= l_shadowmapinfo.w * (1.0-l_shadowmapinfo.st); + //now bias and relocate it shadowcoord = (shadowcoord + axis.xyz) * vec3(0.5/3.0, 0.5/2.0, 0.5); #endif @@ -185,7 +185,7 @@ float ShadowmapFilter(void) return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds. #else - #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*texscale.xyz)).r + #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapinfo.xyz)).r float s = 0.0; s += dosamp(-1.0, -1.0); s += dosamp(-1.0, 0.0); diff --git a/engine/shaders/glsl/underwaterwarp.glsl b/engine/shaders/glsl/underwaterwarp.glsl index 2c16b341e..266443c75 100644 --- a/engine/shaders/glsl/underwaterwarp.glsl +++ b/engine/shaders/glsl/underwaterwarp.glsl @@ -29,17 +29,9 @@ uniform vec4 e_rendertexturescale; uniform float cvar_r_waterwarp; void main () { - float amptemp; - vec3 edge; - edge = texture2D( s_t2, v_edge ).rgb; - amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x; - vec3 offset; - offset = texture2D( s_t1, v_warp ).rgb; - offset.x = (offset.x - 0.5) * 2.0; - offset.y = (offset.y - 0.5) * 2.0; - vec2 temp; - temp.x = v_stc.x + offset.x * amptemp; - temp.y = v_stc.y + offset.y * amptemp; - gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st ); + vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg; + vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0; + vec2 temp = v_stc + offset.xy * amp; + gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st); } #endif