diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 535f09484..c020de99a 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -514,15 +514,18 @@ void M_Menu_Preset_f (void) { MB_REDTEXT("Please Choose Preset", false), MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false), - MB_CONSOLECMD("286 untextured", "fps_preset 286;menupop\n", "Lacks textures, particles, pretty much everything."), - MB_CONSOLECMD("fast deathmatch", "fps_preset fast;menupop\n", "Fullscreen effects off to give consistant framerates"), - MB_CONSOLECMD("normal faithful", "fps_preset normal;menupop\n", "This is for Quake purists!"), - MB_CONSOLECMD("nice dynamic", "fps_preset nice;menupop\n", "For people who like nice things, but still want to actually play"), - MB_CONSOLECMD("realtime all on", "fps_preset realtime;menupop\n", "For people who value pretty over fast/smooth. Not viable for deathmatch."), + MB_CONSOLECMD("286 (untextured)", "fps_preset 286;menupop\n", "Lacks textures, particles, pretty much everything."), + MB_CONSOLECMD("fast (deathmatch)", "fps_preset fast;menupop\n", "Fullscreen effects off to give consistant framerates"), + MB_CONSOLECMD("normal (faithful)", "fps_preset normal;menupop\n", "This is for Quake purists!"), + MB_CONSOLECMD("nice (dynamic)", "fps_preset nice;menupop\n", "For people who like nice things, but still want to actually play"), + MB_CONSOLECMD("realtime (all on)", "fps_preset realtime;menupop\n", "For people who value pretty over fast/smooth. Not viable for deathmatch."), MB_END() }; menu = M_Options_Title(&y, 0); MC_AddBulk(menu, bulk, 16, 216, y); + //bottoms up! highlight 'fast' as the default option + menu->selecteditem = menu->options->common.next->common.next->common.next->common.next; + menu->cursoritem->common.posy = menu->selecteditem->common.posy; } void FPS_Preset_f (void) diff --git a/engine/client/render.h b/engine/client/render.h index 759693ae2..c90311fcf 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -410,6 +410,8 @@ extern cvar_t r_shadow_realtime_dlight, r_shadow_realtime_dlight_shadows; extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows; extern cvar_t r_mirroralpha; extern cvar_t r_wateralpha; +extern cvar_t r_water_refract; +extern cvar_t r_water_reflect; extern cvar_t r_dynamic; extern cvar_t r_novis; extern cvar_t r_netgraph; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 3341cfe81..510c36843 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -326,6 +326,8 @@ cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_sha cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0", 0); cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8"); cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE); +cvar_t r_water_refract = CVARF ("r_water_refract", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM); +cvar_t r_water_reflect = CVARF ("r_water_reflect", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM); cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0"); @@ -576,6 +578,8 @@ void Renderer_Init(void) Cvar_Register (&r_shadow_realtime_world_lightmaps, GRAPHICALNICETIES); Cvar_Register (&r_sun_dir, GRAPHICALNICETIES); Cvar_Register (&r_sun_colour, GRAPHICALNICETIES); + Cvar_Register (&r_water_refract, GRAPHICALNICETIES); + Cvar_Register (&r_water_reflect, GRAPHICALNICETIES); Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 7658b9f8a..3d6acf4df 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -413,9 +413,13 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception Sys_Printf("GL_NORMAL_ARRAY: %s (%lx)\n", glIsEnabled(GL_NORMAL_ARRAY)?"en":"dis", (int) ptr); // glGetPointerv(GL_SECONDARY_COLOR_ARRAY_POINTER, &ptr); // Sys_Printf("GL_SECONDARY_COLOR_ARRAY: %i (%lx)\n", (int) glIsEnabled(GL_SECONDARY_COLOR_ARRAY), (int) ptr); - glGetIntegerv(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &rval); - glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr); - Sys_Printf("GL_TEXTURE_COORD_ARRAY: %s %i:%p\n", glIsEnabled(GL_TEXTURE_COORD_ARRAY)?"en":"dis", rval, ptr); + for (i = 0; i < 4; i++) + { + qglClientActiveTextureARB(mtexid0 + i); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &rval); + glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr); + Sys_Printf("GL_TEXTURE_COORD_ARRAY %i: %s %i:%p\n", i, glIsEnabled(GL_TEXTURE_COORD_ARRAY)?"en":"dis", rval, ptr); + } glGetIntegerv(GL_VERTEX_ARRAY_BUFFER_BINDING, &rval); glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr); Sys_Printf("GL_VERTEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_VERTEX_ARRAY)?"en":"dis", rval, ptr); diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index 18f7665a9..938bfacf1 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -277,7 +277,7 @@ static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *file #ifdef ANDROID { - vfsfile_t *f = VFSSTDIO_Open(netpath, "rb"); + vfsfile_t *f = VFSSTDIO_Open(netpath, "rb", NULL); if (!f) return false; len = VFS_GETLEN(f); diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 463ec1ea6..3188dfbd5 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -347,7 +347,6 @@ Global {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.Build.0 = Release|Win32 @@ -383,7 +382,6 @@ Global {873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|Win32.Build.0 = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|x64.ActiveCfg = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 - {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|Win32.Build.0 = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|x64.ActiveCfg = Debug|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.ActiveCfg = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.Build.0 = Release|Win32 diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 35826a73c..e1de560fb 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -175,6 +175,7 @@ struct { struct { backendmode_t mode; unsigned int flags; + int oldwidth, oldheight; vbo_t *sourcevbo; const shader_t *curshader; @@ -3107,10 +3108,6 @@ static void BE_LegacyLighting(void) mesh_t *mesh; unsigned int attr = (1u<bump.num) - { + if (shaderstate.curtexnums->bump.num && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_dot3 && gl_config.arb_texture_env_combine && be_maxpasses >= 4) + { //we could get this down to 2 tmus by arranging for the dot3 result to be written the alpha buffer. But then we'd need to have an alpha buffer too. attr |= (1u<<(VATTR_LEG_TMU0)) | (1u<<(VATTR_LEG_TMU0+1)) | (1u<<(VATTR_LEG_TMU0+2)); + if (!shaderstate.normalisationcubemap.num) + shaderstate.normalisationcubemap = GenerateNormalisationCubeMap(); + //tmu0: normalmap+replace+regular tex coords GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.curtexnums->bump); BE_SetPassBlendMode(0, PBM_REPLACE); @@ -3613,11 +3613,12 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist) shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth, vid.pixelheight); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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); } + GL_ForceDepthWritable(); GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, true); GL_ForceDepthWritable(); qglClear(GL_DEPTH_BUFFER_BIT); @@ -3636,6 +3637,7 @@ 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); GL_ForceDepthWritable(); qglClear(GL_DEPTH_BUFFER_BIT); @@ -3762,6 +3764,7 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, drb); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth, vid.pixelheight); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb); +// qglDeleteRenderbuffersEXT(1, &drb); qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); qglReadBuffer(GL_NONE); @@ -3935,6 +3938,39 @@ void GLBE_DrawWorld (qbyte *vis) shaderstate.wbatch = 0; } + if (shaderstate.oldwidth != vid.pixelwidth || shaderstate.oldheight != vid.pixelheight) + { + if (shaderstate.tex_reflection.num) + { + R_DestroyTexture(shaderstate.tex_reflection); + shaderstate.tex_reflection = r_nulltex; + } + if (shaderstate.tex_refraction.num) + { + R_DestroyTexture(shaderstate.tex_refraction); + shaderstate.tex_refraction = r_nulltex; + } + if (shaderstate.temptexture.num) + { + R_DestroyTexture(shaderstate.temptexture); + shaderstate.temptexture = r_nulltex; + } + if (shaderstate.fbo_diffuse) + { + qglDeleteFramebuffersEXT(1, &shaderstate.fbo_diffuse); + shaderstate.fbo_diffuse = 0; + } + shaderstate.oldwidth = vid.pixelwidth; + shaderstate.oldheight = vid.pixelheight; + + while(shaderstate.lastpasstmus>0) + { + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); + } +#ifdef RTLIGHTS + Sh_Shutdown(); +#endif + } BE_GenModelBatches(batches); R_GenDlightBatches(batches); shaderstate.curentity = &r_worldentity; diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 0f92cd0c8..afad8d481 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -44,7 +44,9 @@ http://prideout.net/archive/bloom/ contains some sample code #ifdef GLQUAKE #include "shader.h" #include "glquake.h" -cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects)"); +cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects). Fractional values reduce the amount shown."); +cvar_t r_bloom_filter = CVARD("r_bloom_filter", "0.5 0.5 0.5", "Controls how bright the image must get before it will bloom (3 separate values, in RGB order)."); +cvar_t r_bloom_scale = CVARD("r_bloom_scale", "0.5", "Controls the initial downscale size. Smaller values will bloom further but be more random."); static shader_t *bloomfilter; static shader_t *bloomrescale; static shader_t *bloomblur; @@ -63,17 +65,21 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco void R_BloomRegister(void) { Cvar_Register (&r_bloom, "bloom"); + Cvar_Register (&r_bloom_filter, "bloom"); + Cvar_Register (&r_bloom_scale, "bloom"); } static void R_SetupBloomTextures(int w, int h) { int i, j; char name[64]; - if (w == scrwidth && h == scrheight) + if (w == scrwidth && h == scrheight && !r_bloom_scale.modified) return; + r_bloom_scale.modified = false; scrwidth = w; scrheight = h; - w /= 2; - h /= 2; + //I'm depending on npot here + w *= r_bloom_scale.value; + h *= r_bloom_scale.value; for (i = 0; i < MAXLEVELS; i++) { w /= 2; @@ -94,8 +100,8 @@ static void R_SetupBloomTextures(int w, int h) GL_MTBind(0, GL_TEXTURE_2D, scrtex); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); /*top level uses nearest sampling*/ - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -173,6 +179,8 @@ void R_BloomBlend (void) return; if (!gl_config.arb_shader_objects) return; + if (!gl_config.arb_texture_non_power_of_two) + return; /*whu?*/ if (!r_refdef.pxrect.width || !r_refdef.pxrect.height) diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index ae3938f27..d23a6d675 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -209,6 +209,8 @@ void GL_DestroyTexture(texid_t tex) if (!tex.ref) return; + //FIXME: unlink the old one + qglDeleteTextures(1, &tex.num); } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 127e312fc..c092428ce 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -1051,6 +1051,134 @@ void Mod_FinishTexture(texture_t *tx, texnums_t tn) R_BuildDefaultTexnums(&tn, tx->shader); } +#define LMT_DIFFUSE 1 +#define LMT_FULLBRIGHT 2 +#define LMT_BUMP 4 +#define LMT_SPEC 8 +void RMod_LoadMiptex(texture_t *tx, miptex_t *mt, texnums_t *tn, int maps) +{ + char altname[256]; + qbyte *base; + qboolean alphaed; + int j; + int pixels = mt->width*mt->height/64*85; + + if (!Q_strncmp(mt->name,"sky",3)) + { + if (maps & LMT_DIFFUSE) + R_InitSky (tn, tx, (char *)mt + mt->offsets[0]); + } + else + { +/* + RMod_LoadAdvancedTexture(tx->name, &tn.base, &tn.bump, &tn.fullbright, &tn.specular, NULL, NULL); + if (tn.base) + continue; +*/ + + base = (qbyte *)(mt+1); + + if (loadmodel->fromgame == fg_halflife) + {//external textures have already been filtered. + if (maps & LMT_DIFFUSE) + { + base = W_ConvertWAD3Texture(mt, &mt->width, &mt->height, &alphaed); //convert texture to 32 bit. + tx->alphaed = alphaed; + tn->base = R_LoadReplacementTexture(mt->name, loadname, alphaed?0:IF_NOALPHA); + if (!TEXVALID(tn->base)) + { + tn->base = R_LoadReplacementTexture(mt->name, "bmodels", alphaed?0:IF_NOALPHA); + if (!TEXVALID(tn->base)) + tn->base = R_LoadTexture32 (mt->name, tx->width, tx->height, (unsigned int *)base, (alphaed?0:IF_NOALPHA)); + } + } + + *tx->name = *mt->name; + } + else + { + qbyte *mipbase; + unsigned int mipwidth, mipheight; + extern cvar_t gl_miptexLevel; + if ((unsigned int)gl_miptexLevel.ival < 4 && mt->offsets[gl_miptexLevel.ival]) + { + mipbase = (qbyte*)mt + mt->offsets[gl_miptexLevel.ival]; + mipwidth = tx->width>>gl_miptexLevel.ival; + mipheight = tx->height>>gl_miptexLevel.ival; + } + else + { + mipbase = base; + mipwidth = tx->width; + mipheight = tx->height; + } + + if (maps & LMT_DIFFUSE) + { + tn->base = R_LoadReplacementTexture(mt->name, loadname, ((*mt->name == '{')?0:IF_NOALPHA)|IF_SUBDIRONLY|IF_MIPCAP); + if (!TEXVALID(tn->base)) + { + tn->base = R_LoadReplacementTexture(mt->name, "bmodels", ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP); + if (!TEXVALID(tn->base)) + tn->base = R_LoadTexture8 (mt->name, mipwidth, mipheight, mipbase, ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP, 1); + } + } + + if (maps & LMT_FULLBRIGHT) + { + snprintf(altname, sizeof(altname)-1, "%s_luma", mt->name); + if (gl_load24bit.value) + { + tn->fullbright = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); + if (!TEXVALID(tn->fullbright)) + tn->fullbright = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); + } + if ((*mt->name != '{') && !TEXVALID(tn->fullbright)) //generate one (if possible). + tn->fullbright = R_LoadTextureFB(altname, mipwidth, mipheight, mipbase, IF_NOGAMMA|IF_MIPCAP); + } + } + + if (maps & LMT_BUMP) + { + snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); + tn->bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); + if (!TEXVALID(tn->bump)) + tn->bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); + if (!TEXVALID(tn->bump)) + { + if (gl_load24bit.value) + { + snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); + tn->bump = R_LoadBumpmapTexture(altname, loadname); + if (!TEXVALID(tn->bump)) + tn->bump = R_LoadBumpmapTexture(altname, "bmodels"); + } + else + snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); + } + + if (!TEXVALID(tn->bump) && loadmodel->fromgame != fg_halflife)// && gl_bump_fallbacks.ival) + { + //no mip levels here, would be absurd. + base = (qbyte *)(mt+1); //convert to greyscale. + for (j = 0; j < pixels; j++) + base[j] = (host_basepal[base[j]*3] + host_basepal[base[j]*3+1] + host_basepal[base[j]*3+2]) / 3; + + tn->bump = R_LoadTexture8BumpPal(altname, tx->width, tx->height, base, true); //normalise it and then bump it. + } + + //don't do any complex quake 8bit -> glossmap. It would likly look a little ugly... + if (gl_specular.value && gl_load24bit.value) + { + snprintf(altname, sizeof(altname)-1, "%s_gloss", mt->name); + tn->specular = R_LoadHiResTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); + if (!TEXVALID(tn->specular)) + tn->specular = R_LoadHiResTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); + } + } + } +} + /* ================= Mod_LoadTextures @@ -1058,16 +1186,14 @@ Mod_LoadTextures */ qboolean RMod_LoadTextures (lump_t *l) { - int i, j, pixels, num, max, altmax; + int i, j, num, max, altmax; miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10]; texture_t *altanims[10]; - char altname[256]; dmiptexlump_t *m; - qboolean alphaed; - qbyte *base; texnums_t tn; + int maps; TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); @@ -1125,8 +1251,7 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); Con_Printf (CON_WARNING "Warning: Texture %s is not 16 aligned", mt->name); if (mt->width < 1 || mt->height < 1) Con_Printf (CON_WARNING "Warning: Texture %s has no size", mt->name); - pixels = mt->width*mt->height/64*85; - tx = Hunk_AllocName (sizeof(texture_t)/* +pixels*/, loadname ); + tx = Hunk_AllocName (sizeof(texture_t), loadname ); loadmodel->textures[i] = tx; memcpy (tx->name, mt->name, sizeof(tx->name)); @@ -1140,115 +1265,18 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); memset(&tn, 0, sizeof(tn)); - if (!Q_strncmp(mt->name,"sky",3)) - { - R_InitSky (&tn, tx, (char *)mt + mt->offsets[0]); - } - else - { -/* - RMod_LoadAdvancedTexture(tx->name, &tn.base, &tn.bump, &tn.fullbright, &tn.specular, NULL, NULL); - if (tn.base) - continue; -*/ + maps = LMT_DIFFUSE; + if (r_fb_bmodels.ival) + maps |= LMT_FULLBRIGHT; + if (r_loadbumpmapping) + maps |= LMT_BUMP; - base = (qbyte *)(mt+1); - - if (loadmodel->fromgame == fg_halflife) - {//external textures have already been filtered. - base = W_ConvertWAD3Texture(mt, &mt->width, &mt->height, &alphaed); //convert texture to 32 bit. - tx->alphaed = alphaed; - tn.base = R_LoadReplacementTexture(mt->name, loadname, alphaed?0:IF_NOALPHA); - if (!TEXVALID(tn.base)) - { - tn.base = R_LoadReplacementTexture(mt->name, "bmodels", alphaed?0:IF_NOALPHA); - if (!TEXVALID(tn.base)) - tn.base = R_LoadTexture32 (mt->name, tx->width, tx->height, (unsigned int *)base, (alphaed?0:IF_NOALPHA)); - } - - *tx->name = *mt->name; - } - else - { - qbyte *mipbase; - unsigned int mipwidth, mipheight; - extern cvar_t gl_miptexLevel; - if ((unsigned int)gl_miptexLevel.ival < 4 && mt->offsets[gl_miptexLevel.ival]) - { - mipbase = (qbyte*)mt + mt->offsets[gl_miptexLevel.ival]; - mipwidth = tx->width>>gl_miptexLevel.ival; - mipheight = tx->height>>gl_miptexLevel.ival; - } - else - { - mipbase = base; - mipwidth = tx->width; - mipheight = tx->height; - } - - tn.base = R_LoadReplacementTexture(mt->name, loadname, ((*mt->name == '{')?0:IF_NOALPHA)|IF_SUBDIRONLY|IF_MIPCAP); - if (!TEXVALID(tn.base)) - { - tn.base = R_LoadReplacementTexture(mt->name, "bmodels", ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP); - if (!TEXVALID(tn.base)) - tn.base = R_LoadTexture8 (mt->name, mipwidth, mipheight, mipbase, ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP, 1); - } - - if (r_fb_bmodels.value) - { - snprintf(altname, sizeof(altname)-1, "%s_luma", mt->name); - if (gl_load24bit.value) - { - tn.fullbright = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); - if (!TEXVALID(tn.fullbright)) - tn.fullbright = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); - } - if ((*mt->name != '{') && !TEXVALID(tn.fullbright)) //generate one (if possible). - tn.fullbright = R_LoadTextureFB(altname, mipwidth, mipheight, mipbase, IF_NOGAMMA|IF_MIPCAP); - } - } - - tn.bump = r_nulltex; - if (r_loadbumpmapping) - { - snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); - tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); - if (!TEXVALID(tn.bump)) - tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); - if (!TEXVALID(tn.bump)) - { - if (gl_load24bit.value) - { - snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); - tn.bump = R_LoadBumpmapTexture(altname, loadname); - if (!TEXVALID(tn.bump)) - tn.bump = R_LoadBumpmapTexture(altname, "bmodels"); - } - else - snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); - } - - if (!TEXVALID(tn.bump) && loadmodel->fromgame != fg_halflife)// && gl_bump_fallbacks.ival) - { - //no mip levels here, would be absurd. - base = (qbyte *)(mt+1); //convert to greyscale. - for (j = 0; j < pixels; j++) - base[j] = (host_basepal[base[j]*3] + host_basepal[base[j]*3+1] + host_basepal[base[j]*3+2]) / 3; - - tn.bump = R_LoadTexture8BumpPal(altname, tx->width, tx->height, base, true); //normalise it and then bump it. - } - - //don't do any complex quake 8bit -> glossmap. It would likly look a little ugly... - if (gl_specular.value && gl_load24bit.value) - { - snprintf(altname, sizeof(altname)-1, "%s_gloss", mt->name); - tn.specular = R_LoadHiResTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); - if (!TEXVALID(tn.specular)) - tn.specular = R_LoadHiResTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); - } - } - } + RMod_LoadMiptex(tx, mt, &tn, maps); + Mod_FinishTexture(tx, tn); + + if ((tx->shader->flags & SHADER_HASNORMALMAP) && !(maps & LMT_BUMP)) + RMod_LoadMiptex(tx, mt, &tx->shader->defaulttextures, LMT_BUMP); } // // sequence the animations diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 7e3b533f0..319253ab7 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1180,7 +1180,7 @@ void GLR_RenderView (void) if (r_refdef.flags & Q2RDF_NOWORLDMODEL) return; - if (r_bloom.ival) + if (r_bloom.value) R_BloomBlend(); // SCENE POST PROCESSING diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 8d3f7cfd9..4f8caa1db 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -105,7 +105,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //negative x bytePtr=data; @@ -128,7 +128,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //positive y bytePtr=data; @@ -151,7 +151,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //negative y bytePtr=data; @@ -174,7 +174,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //positive z bytePtr=data; @@ -197,7 +197,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //negative z bytePtr=data; @@ -220,7 +220,7 @@ texid_t GenerateNormalisationCubeMap(void) } } qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, - 0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + 0, GL_RGBA, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 15c6cc552..310c07861 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -914,6 +914,10 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip memcpy(permutationdefines[nummodifiers]+8, start, end - start); memcpy(permutationdefines[nummodifiers]+8+(end-start), "\n", 2); + start = strchr(permutationdefines[nummodifiers]+8, '='); + if (start) + *start = ' '; + for (start = permutationdefines[nummodifiers]+8; *start; start++) *start = toupper(*start); nummodifiers++; @@ -1446,6 +1450,8 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) { unsigned int i; void *file; + char basicname[MAX_QPATH]; + char *h; sgeneric_t *g; @@ -1469,24 +1475,30 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) g->prog.refs = 1; - if (strchr(name, '/') || strchr(name, '.')) - FS_LoadFile(name, &file); + basicname[1] = 0; + Q_strncpyz(basicname, name, sizeof(basicname)); + h = strchr(basicname+1, '#'); + if (h) + *h = '\0'; + + if (strchr(basicname, '/') || strchr(basicname, '.')) + FS_LoadFile(basicname, &file); else if (qrenderer == QR_DIRECT3D) - FS_LoadFile(va("hlsl/%s.hlsl", name), &file); + FS_LoadFile(va("hlsl/%s.hlsl", basicname), &file); else if (qrenderer == QR_OPENGL) { #ifdef GLQUAKE if (gl_config.gles) - FS_LoadFile(va("gles/%s.glsl", name), &file); + FS_LoadFile(va("gles/%s.glsl", basicname), &file); else #endif - FS_LoadFile(va("glsl/%s.glsl", name), &file); + FS_LoadFile(va("glsl/%s.glsl", basicname), &file); } else file = NULL; if (file) { - Con_DPrintf("Loaded %s from disk\n", name); + Con_DPrintf("Loaded %s from disk\n", basicname); g->failed = !Shader_LoadPermutations(name, &g->prog, file, qrtype, 0); FS_FreeFile(file); @@ -1495,16 +1507,10 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) } else { - int matchlen; int ver; - char *h = strchr(name, '#'); - if (h) - matchlen = h - name; - else - matchlen = strlen(name) + 1; for (i = 0; *sbuiltins[i].name; i++) { - if (sbuiltins[i].qrtype == qrenderer && !strncmp(sbuiltins[i].name, name, matchlen)) + if (sbuiltins[i].qrtype == qrenderer && !strcmp(sbuiltins[i].name, basicname)) { ver = sbuiltins[i].apiver; #ifdef GLQUAKE @@ -2133,6 +2139,7 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t { pass->texgen = T_GEN_NORMALMAP; pass->tcgen = TC_GEN_BASE; + shader->flags |= SHADER_HASNORMALMAP; } else if (!Q_stricmp (tname, "$specular")) { @@ -4189,8 +4196,33 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) if (!builtin && (*shortname == '*')) { + if ((r_water_refract.ival || r_water_reflect.ival) && !r_fastturb.ival && strncmp(shortname, "*lava", 5)) + { + builtin = ( + "{\n" + "{\n" + "map $currentrender\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" + "if r_water_reflect\n" + "[\n" + "{\n" + "map $reflection\n" + "}\n" + "program altwater#REFLECT#FRESNEL=4\n" + "][\n" + "program altwater#FRESNEL=4\n" + "]\n" + "}\n" + ); + } //q1 water - if (r_wateralpha.value == 0) + else if (r_wateralpha.value == 0) { builtin = ( "{\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index c1c0eccad..5aade016d 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -52,6 +52,11 @@ void Sh_Shutdown(void) qglDeleteRenderbuffersEXT(1, &shadow_fbo_id); shadow_fbo_id = 0; } + if (crepuscular_texture_id.num) + { + R_DestroyTexture(crepuscular_texture_id); + crepuscular_texture_id = r_nulltex; + } if (crepuscular_fbo_id) { qglDeleteRenderbuffersEXT(1, &crepuscular_fbo_id); @@ -2745,6 +2750,8 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, 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, batch_t **batches) { #ifdef GLQUAKE @@ -2789,45 +2796,41 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches) if (!gl_config.ext_framebuffer_objects) return; - if (!crepuscular_fbo_id) + if (!crepuscular_texture_id.num) { - qglGenFramebuffersEXT(1, &crepuscular_fbo_id); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, crepuscular_fbo_id); - qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - qglReadBuffer(GL_NONE); - - crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight); - /*FIXME: requires npot*/ crepuscular_shader = R_RegisterShader("crepuscular_screen", "{\n" "program crepuscular_rays\n" "{\n" - "map \"***crepusculartexture***\"\n" + "map $sourcecolour\n" "blend add\n" "}\n" "}\n" ); + + crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight); GL_MTBind(0, GL_TEXTURE_2D, crepuscular_texture_id); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, crepuscular_texture_id.num, 0); } - else - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, crepuscular_fbo_id); + + GLBE_RenderToTexture(r_nulltex, r_nulltex, crepuscular_texture_id, false); + BE_SelectMode(BEM_CREPUSCULAR); BE_SelectDLight(dl, colours); GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_BLEND); - //fixme: check regular post-proc - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + GLBE_RenderToTexture(crepuscular_texture_id, 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); #endif } diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 73dc0d2a4..5ccf5769b 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -3,6 +3,75 @@ WARNING: THIS FILE IS GENERATED BY 'generatebuiltinsl.c'. YOU SHOULD NOT EDIT THIS FILE BY HAND */ +#ifdef GLQUAKE +{QR_OPENGL, 110, "altwater", +//modifier: REFLECT +//modifier: FRESNEL (5=water) + +"varying vec2 tc;\n" +"varying vec4 tf;\n" +"varying vec3 norm;\n" +"varying vec3 eye;\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec3 v_normal;\n" +"uniform vec3 e_eyepos;\n" +"void main (void)\n" +"{\n" +"tc = v_texcoord.st;\n" +"tf = ftetransform();\n" +"norm = v_normal;\n" +"eye = e_eyepos - v_position.xyz;\n" +"gl_Position = tf;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0; //refract\n" +"uniform sampler2D s_t1; //normalmap\n" +"uniform sampler2D s_t2; //diffuse\n" +"#ifdef REFLECT\n" +"uniform sampler2D s_t3; //reflect\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" +"stc = (1.0 + (tf.xy / tf.w)) * 0.5;\n" + +//apply q1-style warp, just for kicks +"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" +"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" + +//generate the two wave patterns from the normalmap +"n = (texture2D(s_t1, 0.2*tc + vec2(e_time*0.1, 0)).xyz);\n" +"n += (texture2D(s_t1, 0.2*tc - vec2(0, e_time*0.097)).xyz);\n" +"n -= 1.0 - 4.0/256.0;\n" + +"n = normalize(n);\n" + +"#if 1//def REFRACT\n" +"refr = texture2D(s_t0, stc + n.st*0.2).rgb;\n" +"#else\n" +"refr = texture2D(s_t2, ntc).xyz;\n" +"#endif\n" +"#ifdef REFLECT\n" +"refl = texture2D(s_t3, stc - n.st*0.2).rgb;\n" +"#else\n" +"refl = texture2D(s_t2, ntc).xyz;\n" +"#endif\n" + +//the fresnel term decides how transparent the water should be +"f = pow(1.0-abs(dot(n, normalize(eye))), float(FRESNEL));\n" +"fres = refr * (1.0-f) + refl*f;\n" + +"gl_FragColor = vec4(fres, 1.0);\n" +"}\n" +"#endif\n" +}, +#endif #ifdef GLQUAKE {QR_OPENGL, 110, "bloom_blur", //apply gaussian filter @@ -33,9 +102,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef GLQUAKE {QR_OPENGL, 110, "bloom_filter", +"!!cvarv r_bloom_filter\n" //the bloom filter //filter out any texels which are not to bloom +"uniform vec3 cvar_r_bloom_filter;\n" "varying vec2 tc;\n" "#ifdef VERTEX_SHADER\n" @@ -50,13 +121,15 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform sampler2D s_t0;\n" "void main ()\n" "{\n" -"gl_FragColor = (texture2D(s_t0, tc) - vec4(0.5, 0.5, 0.5, 0.0)) * vec4(2.0,2.0,2.0,1.0);\n" +"gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter);\n" "}\n" "#endif\n" }, #endif #ifdef GLQUAKE {QR_OPENGL, 110, "bloom_final", +"!!cvarf r_bloom\n" +"uniform float cvar_r_bloom;\n" //add them together //optionally apply tonemapping @@ -79,9 +152,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "{\n" "gl_FragColor = \n" "texture2D(s_t0, tc) +\n" +"cvar_r_bloom*(\n" "texture2D(s_t1, tc) +\n" "texture2D(s_t2, tc) +\n" -"texture2D(s_t3, tc) ;\n" +"texture2D(s_t3, tc)\n" +") ;\n" "}\n" "#endif\n" }, diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 25eb8389b..fcca32bbb 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -419,8 +419,9 @@ struct shader_s SHADER_HASLIGHTMAP = 1 << 16, SHADER_HASTOPBOTTOM = 1 << 17, 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, - SHADER_HASREFRACT = 1 << 20 + 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 } flags; program_t *prog; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index e8d3b051f..f37b89def 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -4833,7 +4833,7 @@ void SV_Init (quakeparms_t *parms) Mod_Init (); } -#if !(defined(CSQC_DAT) || defined(MENU_DAT)) +#if defined(SERVERONLY) || !(defined(CSQC_DAT) || defined(MENU_DAT)) PF_Common_RegisterCvars(); #endif diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c index 2ad5d19f7..9e63c0d6d 100644 --- a/engine/shaders/generatebuiltinsl.c +++ b/engine/shaders/generatebuiltinsl.c @@ -3,6 +3,7 @@ char shaders[][64] = { + "altwater", "bloom_blur", "bloom_filter", "bloom_final", diff --git a/engine/shaders/glsl/altwater.glsl b/engine/shaders/glsl/altwater.glsl new file mode 100644 index 000000000..267f33c92 --- /dev/null +++ b/engine/shaders/glsl/altwater.glsl @@ -0,0 +1,65 @@ +//modifier: REFLECT +//modifier: FRESNEL (5=water) + +varying vec2 tc; +varying vec4 tf; +varying vec3 norm; +varying vec3 eye; +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec3 v_normal; +uniform vec3 e_eyepos; +void main (void) +{ + tc = v_texcoord.st; + tf = ftetransform(); + norm = v_normal; + eye = e_eyepos - v_position.xyz; + gl_Position = tf; +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; //refract +uniform sampler2D s_t1; //normalmap +uniform sampler2D s_t2; //diffuse +#ifdef REFLECT +uniform sampler2D s_t3; //reflect +#endif + +uniform float e_time; +void main (void) +{ + vec2 stc, ntc; + vec3 n, refr, refl, fres; + float f; + stc = (1.0 + (tf.xy / tf.w)) * 0.5; + + //apply q1-style warp, just for kicks + ntc.s = tc.s + sin(tc.t+e_time)*0.125; + ntc.t = tc.t + sin(tc.s+e_time)*0.125; + + //generate the two wave patterns from the normalmap + n = (texture2D(s_t1, 0.2*tc + vec2(e_time*0.1, 0)).xyz); + n += (texture2D(s_t1, 0.2*tc - vec2(0, e_time*0.097)).xyz); + n -= 1.0 - 4.0/256.0; + + n = normalize(n); + +#if 1//def REFRACT + refr = texture2D(s_t0, stc + n.st*0.2).rgb; +#else + refr = texture2D(s_t2, ntc).xyz; +#endif +#ifdef REFLECT + refl = texture2D(s_t3, stc - n.st*0.2).rgb; +#else + refl = texture2D(s_t2, ntc).xyz; +#endif + + //the fresnel term decides how transparent the water should be + f = pow(1.0-abs(dot(n, normalize(eye))), float(FRESNEL)); + fres = refr * (1.0-f) + refl*f; + + gl_FragColor = vec4(fres, 1.0); +} +#endif diff --git a/engine/shaders/glsl/bloom_filter.glsl b/engine/shaders/glsl/bloom_filter.glsl index 35f127828..d2e36e949 100644 --- a/engine/shaders/glsl/bloom_filter.glsl +++ b/engine/shaders/glsl/bloom_filter.glsl @@ -1,6 +1,8 @@ +!!cvarv r_bloom_filter //the bloom filter //filter out any texels which are not to bloom +uniform vec3 cvar_r_bloom_filter; varying vec2 tc; #ifdef VERTEX_SHADER @@ -15,6 +17,6 @@ void main () uniform sampler2D s_t0; void main () { - gl_FragColor = (texture2D(s_t0, tc) - vec4(0.5, 0.5, 0.5, 0.0)) * vec4(2.0,2.0,2.0,1.0); + gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter); } #endif \ No newline at end of file diff --git a/engine/shaders/glsl/bloom_final.glsl b/engine/shaders/glsl/bloom_final.glsl index 43fad1777..c5c21d155 100644 --- a/engine/shaders/glsl/bloom_final.glsl +++ b/engine/shaders/glsl/bloom_final.glsl @@ -1,3 +1,5 @@ +!!cvarf r_bloom +uniform float cvar_r_bloom; //add them together //optionally apply tonemapping @@ -20,8 +22,10 @@ void main () { gl_FragColor = texture2D(s_t0, tc) + - texture2D(s_t1, tc) + - texture2D(s_t2, tc) + - texture2D(s_t3, tc) ; + cvar_r_bloom*( + texture2D(s_t1, tc) + + texture2D(s_t2, tc) + + texture2D(s_t3, tc) + ) ; } #endif