added args to the bloom shader for better tweekage.

Committing my lame water shader. r_water_refract/r_water_reflect 1 to use.
Bugfix for crepuscular arrays (r_sun_colour to easily enable).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4047 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-05-11 01:57:00 +00:00
parent 376324eacf
commit 1dcc435bca
21 changed files with 450 additions and 182 deletions

View file

@ -514,15 +514,18 @@ void M_Menu_Preset_f (void)
{ {
MB_REDTEXT("Please Choose Preset", false), 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_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("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("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("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("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("realtime (all on)", "fps_preset realtime;menupop\n", "For people who value pretty over fast/smooth. Not viable for deathmatch."),
MB_END() MB_END()
}; };
menu = M_Options_Title(&y, 0); menu = M_Options_Title(&y, 0);
MC_AddBulk(menu, bulk, 16, 216, y); 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) void FPS_Preset_f (void)

View file

@ -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_shadow_realtime_world, r_shadow_realtime_world_shadows;
extern cvar_t r_mirroralpha; extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha; 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_dynamic;
extern cvar_t r_novis; extern cvar_t r_novis;
extern cvar_t r_netgraph; extern cvar_t r_netgraph;

View file

@ -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_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_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_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"); 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_shadow_realtime_world_lightmaps, GRAPHICALNICETIES);
Cvar_Register (&r_sun_dir, GRAPHICALNICETIES); Cvar_Register (&r_sun_dir, GRAPHICALNICETIES);
Cvar_Register (&r_sun_colour, 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_viewsize, SCREENOPTIONS);
Cvar_Register(&scr_fov, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS);

View file

@ -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); Sys_Printf("GL_NORMAL_ARRAY: %s (%lx)\n", glIsEnabled(GL_NORMAL_ARRAY)?"en":"dis", (int) ptr);
// glGetPointerv(GL_SECONDARY_COLOR_ARRAY_POINTER, &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); // 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); for (i = 0; i < 4; i++)
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); 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); glGetIntegerv(GL_VERTEX_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr); glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_VERTEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_VERTEX_ARRAY)?"en":"dis", rval, ptr); Sys_Printf("GL_VERTEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_VERTEX_ARRAY)?"en":"dis", rval, ptr);

View file

@ -277,7 +277,7 @@ static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *file
#ifdef ANDROID #ifdef ANDROID
{ {
vfsfile_t *f = VFSSTDIO_Open(netpath, "rb"); vfsfile_t *f = VFSSTDIO_Open(netpath, "rb", NULL);
if (!f) if (!f)
return false; return false;
len = VFS_GETLEN(f); len = VFS_GETLEN(f);

View file

@ -347,7 +347,6 @@ Global
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|Win32.ActiveCfg = Debug|Win32 {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}.MDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.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}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLRelease|Win32.Build.0 = 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|Win32.Build.0 = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|x64.ActiveCfg = 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.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}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.ActiveCfg = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.Build.0 = Release|Win32 {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.Build.0 = Release|Win32

View file

@ -175,6 +175,7 @@ struct {
struct { struct {
backendmode_t mode; backendmode_t mode;
unsigned int flags; unsigned int flags;
int oldwidth, oldheight;
vbo_t *sourcevbo; vbo_t *sourcevbo;
const shader_t *curshader; const shader_t *curshader;
@ -3107,10 +3108,6 @@ static void BE_LegacyLighting(void)
mesh_t *mesh; mesh_t *mesh;
unsigned int attr = (1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR); unsigned int attr = (1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR);
if (!shaderstate.normalisationcubemap.num)
shaderstate.normalisationcubemap = GenerateNormalisationCubeMap();
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE); BE_SendPassBlendDepthMask(SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE);
//rotate this into modelspace //rotate this into modelspace
@ -3135,10 +3132,13 @@ static void BE_LegacyLighting(void)
} }
} }
if (shaderstate.curtexnums->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)); 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 //tmu0: normalmap+replace+regular tex coords
GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.curtexnums->bump); GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.curtexnums->bump);
BE_SetPassBlendMode(0, PBM_REPLACE); 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); shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth, vid.pixelheight);
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection); 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); 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_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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); GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, true);
GL_ForceDepthWritable(); GL_ForceDepthWritable();
qglClear(GL_DEPTH_BUFFER_BIT); 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_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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); GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, true);
GL_ForceDepthWritable(); GL_ForceDepthWritable();
qglClear(GL_DEPTH_BUFFER_BIT); 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); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, drb);
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth, vid.pixelheight); qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth, vid.pixelheight);
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb);
// qglDeleteRenderbuffersEXT(1, &drb);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
qglReadBuffer(GL_NONE); qglReadBuffer(GL_NONE);
@ -3935,6 +3938,39 @@ void GLBE_DrawWorld (qbyte *vis)
shaderstate.wbatch = 0; 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); BE_GenModelBatches(batches);
R_GenDlightBatches(batches); R_GenDlightBatches(batches);
shaderstate.curentity = &r_worldentity; shaderstate.curentity = &r_worldentity;

View file

@ -44,7 +44,9 @@ http://prideout.net/archive/bloom/ contains some sample code
#ifdef GLQUAKE #ifdef GLQUAKE
#include "shader.h" #include "shader.h"
#include "glquake.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 *bloomfilter;
static shader_t *bloomrescale; static shader_t *bloomrescale;
static shader_t *bloomblur; static shader_t *bloomblur;
@ -63,17 +65,21 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco
void R_BloomRegister(void) void R_BloomRegister(void)
{ {
Cvar_Register (&r_bloom, "bloom"); 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) static void R_SetupBloomTextures(int w, int h)
{ {
int i, j; int i, j;
char name[64]; char name[64];
if (w == scrwidth && h == scrheight) if (w == scrwidth && h == scrheight && !r_bloom_scale.modified)
return; return;
r_bloom_scale.modified = false;
scrwidth = w; scrwidth = w;
scrheight = h; scrheight = h;
w /= 2; //I'm depending on npot here
h /= 2; w *= r_bloom_scale.value;
h *= r_bloom_scale.value;
for (i = 0; i < MAXLEVELS; i++) for (i = 0; i < MAXLEVELS; i++)
{ {
w /= 2; w /= 2;
@ -94,8 +100,8 @@ static void R_SetupBloomTextures(int w, int h)
GL_MTBind(0, GL_TEXTURE_2D, scrtex); GL_MTBind(0, GL_TEXTURE_2D, scrtex);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
/*top level uses nearest sampling*/ /*top level uses nearest sampling*/
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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; return;
if (!gl_config.arb_shader_objects) if (!gl_config.arb_shader_objects)
return; return;
if (!gl_config.arb_texture_non_power_of_two)
return;
/*whu?*/ /*whu?*/
if (!r_refdef.pxrect.width || !r_refdef.pxrect.height) if (!r_refdef.pxrect.width || !r_refdef.pxrect.height)

View file

@ -209,6 +209,8 @@ void GL_DestroyTexture(texid_t tex)
if (!tex.ref) if (!tex.ref)
return; return;
//FIXME: unlink the old one
qglDeleteTextures(1, &tex.num); qglDeleteTextures(1, &tex.num);
} }

View file

@ -1051,6 +1051,134 @@ void Mod_FinishTexture(texture_t *tx, texnums_t tn)
R_BuildDefaultTexnums(&tn, tx->shader); 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 Mod_LoadTextures
@ -1058,16 +1186,14 @@ Mod_LoadTextures
*/ */
qboolean RMod_LoadTextures (lump_t *l) qboolean RMod_LoadTextures (lump_t *l)
{ {
int i, j, pixels, num, max, altmax; int i, j, num, max, altmax;
miptex_t *mt; miptex_t *mt;
texture_t *tx, *tx2; texture_t *tx, *tx2;
texture_t *anims[10]; texture_t *anims[10];
texture_t *altanims[10]; texture_t *altanims[10];
char altname[256];
dmiptexlump_t *m; dmiptexlump_t *m;
qboolean alphaed;
qbyte *base;
texnums_t tn; texnums_t tn;
int maps;
TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); 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); Con_Printf (CON_WARNING "Warning: Texture %s is not 16 aligned", mt->name);
if (mt->width < 1 || mt->height < 1) if (mt->width < 1 || mt->height < 1)
Con_Printf (CON_WARNING "Warning: Texture %s has no size", mt->name); 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), loadname );
tx = Hunk_AllocName (sizeof(texture_t)/* +pixels*/, loadname );
loadmodel->textures[i] = tx; loadmodel->textures[i] = tx;
memcpy (tx->name, mt->name, sizeof(tx->name)); memcpy (tx->name, mt->name, sizeof(tx->name));
@ -1140,115 +1265,18 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
memset(&tn, 0, sizeof(tn)); memset(&tn, 0, sizeof(tn));
if (!Q_strncmp(mt->name,"sky",3)) maps = LMT_DIFFUSE;
{ if (r_fb_bmodels.ival)
R_InitSky (&tn, tx, (char *)mt + mt->offsets[0]); maps |= LMT_FULLBRIGHT;
} if (r_loadbumpmapping)
else maps |= LMT_BUMP;
{
/*
RMod_LoadAdvancedTexture(tx->name, &tn.base, &tn.bump, &tn.fullbright, &tn.specular, NULL, NULL);
if (tn.base)
continue;
*/
base = (qbyte *)(mt+1); RMod_LoadMiptex(tx, mt, &tn, maps);
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);
}
}
}
Mod_FinishTexture(tx, tn); 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 // sequence the animations

View file

@ -1180,7 +1180,7 @@ void GLR_RenderView (void)
if (r_refdef.flags & Q2RDF_NOWORLDMODEL) if (r_refdef.flags & Q2RDF_NOWORLDMODEL)
return; return;
if (r_bloom.ival) if (r_bloom.value)
R_BloomBlend(); R_BloomBlend();
// SCENE POST PROCESSING // SCENE POST PROCESSING

View file

@ -105,7 +105,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 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 //negative x
bytePtr=data; bytePtr=data;
@ -128,7 +128,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 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 //positive y
bytePtr=data; bytePtr=data;
@ -151,7 +151,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 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 //negative y
bytePtr=data; bytePtr=data;
@ -174,7 +174,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 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 //positive z
bytePtr=data; bytePtr=data;
@ -197,7 +197,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 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 //negative z
bytePtr=data; bytePtr=data;
@ -220,7 +220,7 @@ texid_t GenerateNormalisationCubeMap(void)
} }
} }
qglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 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); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

View file

@ -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, start, end - start);
memcpy(permutationdefines[nummodifiers]+8+(end-start), "\n", 2); memcpy(permutationdefines[nummodifiers]+8+(end-start), "\n", 2);
start = strchr(permutationdefines[nummodifiers]+8, '=');
if (start)
*start = ' ';
for (start = permutationdefines[nummodifiers]+8; *start; start++) for (start = permutationdefines[nummodifiers]+8; *start; start++)
*start = toupper(*start); *start = toupper(*start);
nummodifiers++; nummodifiers++;
@ -1446,6 +1450,8 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype)
{ {
unsigned int i; unsigned int i;
void *file; void *file;
char basicname[MAX_QPATH];
char *h;
sgeneric_t *g; sgeneric_t *g;
@ -1469,24 +1475,30 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype)
g->prog.refs = 1; g->prog.refs = 1;
if (strchr(name, '/') || strchr(name, '.')) basicname[1] = 0;
FS_LoadFile(name, &file); 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) 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) else if (qrenderer == QR_OPENGL)
{ {
#ifdef GLQUAKE #ifdef GLQUAKE
if (gl_config.gles) if (gl_config.gles)
FS_LoadFile(va("gles/%s.glsl", name), &file); FS_LoadFile(va("gles/%s.glsl", basicname), &file);
else else
#endif #endif
FS_LoadFile(va("glsl/%s.glsl", name), &file); FS_LoadFile(va("glsl/%s.glsl", basicname), &file);
} }
else else
file = NULL; file = NULL;
if (file) 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); g->failed = !Shader_LoadPermutations(name, &g->prog, file, qrtype, 0);
FS_FreeFile(file); FS_FreeFile(file);
@ -1495,16 +1507,10 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype)
} }
else else
{ {
int matchlen;
int ver; int ver;
char *h = strchr(name, '#');
if (h)
matchlen = h - name;
else
matchlen = strlen(name) + 1;
for (i = 0; *sbuiltins[i].name; i++) 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; ver = sbuiltins[i].apiver;
#ifdef GLQUAKE #ifdef GLQUAKE
@ -2133,6 +2139,7 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
{ {
pass->texgen = T_GEN_NORMALMAP; pass->texgen = T_GEN_NORMALMAP;
pass->tcgen = TC_GEN_BASE; pass->tcgen = TC_GEN_BASE;
shader->flags |= SHADER_HASNORMALMAP;
} }
else if (!Q_stricmp (tname, "$specular")) 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 (!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 //q1 water
if (r_wateralpha.value == 0) else if (r_wateralpha.value == 0)
{ {
builtin = ( builtin = (
"{\n" "{\n"

View file

@ -52,6 +52,11 @@ void Sh_Shutdown(void)
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id); qglDeleteRenderbuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0; shadow_fbo_id = 0;
} }
if (crepuscular_texture_id.num)
{
R_DestroyTexture(crepuscular_texture_id);
crepuscular_texture_id = r_nulltex;
}
if (crepuscular_fbo_id) if (crepuscular_fbo_id)
{ {
qglDeleteRenderbuffersEXT(1, &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_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) void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches)
{ {
#ifdef GLQUAKE #ifdef GLQUAKE
@ -2789,45 +2796,41 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches)
if (!gl_config.ext_framebuffer_objects) if (!gl_config.ext_framebuffer_objects)
return; 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*/ /*FIXME: requires npot*/
crepuscular_shader = R_RegisterShader("crepuscular_screen", crepuscular_shader = R_RegisterShader("crepuscular_screen",
"{\n" "{\n"
"program crepuscular_rays\n" "program crepuscular_rays\n"
"{\n" "{\n"
"map \"***crepusculartexture***\"\n" "map $sourcecolour\n"
"blend add\n" "blend add\n"
"}\n" "}\n"
"}\n" "}\n"
); );
crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight);
GL_MTBind(0, GL_TEXTURE_2D, crepuscular_texture_id); 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); 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_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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_S, GL_CLAMP);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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_SelectMode(BEM_CREPUSCULAR);
BE_SelectDLight(dl, colours); BE_SelectDLight(dl, colours);
GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_BLEND); 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); BE_SelectMode(BEM_STANDARD);
GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0); GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0);
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false);
#endif #endif
} }

View file

@ -3,6 +3,75 @@ WARNING: THIS FILE IS GENERATED BY 'generatebuiltinsl.c'.
YOU SHOULD NOT EDIT THIS FILE BY HAND 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 #ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_blur", {QR_OPENGL, 110, "bloom_blur",
//apply gaussian filter //apply gaussian filter
@ -33,9 +102,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif #endif
#ifdef GLQUAKE #ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_filter", {QR_OPENGL, 110, "bloom_filter",
"!!cvarv r_bloom_filter\n"
//the bloom filter //the bloom filter
//filter out any texels which are not to bloom //filter out any texels which are not to bloom
"uniform vec3 cvar_r_bloom_filter;\n"
"varying vec2 tc;\n" "varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
@ -50,13 +121,15 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform sampler2D s_t0;\n" "uniform sampler2D s_t0;\n"
"void main ()\n" "void main ()\n"
"{\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" "}\n"
"#endif\n" "#endif\n"
}, },
#endif #endif
#ifdef GLQUAKE #ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_final", {QR_OPENGL, 110, "bloom_final",
"!!cvarf r_bloom\n"
"uniform float cvar_r_bloom;\n"
//add them together //add them together
//optionally apply tonemapping //optionally apply tonemapping
@ -79,9 +152,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"{\n" "{\n"
"gl_FragColor = \n" "gl_FragColor = \n"
"texture2D(s_t0, tc) +\n" "texture2D(s_t0, tc) +\n"
"cvar_r_bloom*(\n"
"texture2D(s_t1, tc) +\n" "texture2D(s_t1, tc) +\n"
"texture2D(s_t2, tc) +\n" "texture2D(s_t2, tc) +\n"
"texture2D(s_t3, tc) ;\n" "texture2D(s_t3, tc)\n"
") ;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
}, },

View file

@ -419,8 +419,9 @@ struct shader_s
SHADER_HASLIGHTMAP = 1 << 16, SHADER_HASLIGHTMAP = 1 << 16,
SHADER_HASTOPBOTTOM = 1 << 17, 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_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_HASREFLECT = 1 << 19, //says that we need to generate a reflection image first
SHADER_HASREFRACT = 1 << 20 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; } flags;
program_t *prog; program_t *prog;

View file

@ -4833,7 +4833,7 @@ void SV_Init (quakeparms_t *parms)
Mod_Init (); Mod_Init ();
} }
#if !(defined(CSQC_DAT) || defined(MENU_DAT)) #if defined(SERVERONLY) || !(defined(CSQC_DAT) || defined(MENU_DAT))
PF_Common_RegisterCvars(); PF_Common_RegisterCvars();
#endif #endif

View file

@ -3,6 +3,7 @@
char shaders[][64] = char shaders[][64] =
{ {
"altwater",
"bloom_blur", "bloom_blur",
"bloom_filter", "bloom_filter",
"bloom_final", "bloom_final",

View file

@ -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

View file

@ -1,6 +1,8 @@
!!cvarv r_bloom_filter
//the bloom filter //the bloom filter
//filter out any texels which are not to bloom //filter out any texels which are not to bloom
uniform vec3 cvar_r_bloom_filter;
varying vec2 tc; varying vec2 tc;
#ifdef VERTEX_SHADER #ifdef VERTEX_SHADER
@ -15,6 +17,6 @@ void main ()
uniform sampler2D s_t0; uniform sampler2D s_t0;
void main () 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 #endif

View file

@ -1,3 +1,5 @@
!!cvarf r_bloom
uniform float cvar_r_bloom;
//add them together //add them together
//optionally apply tonemapping //optionally apply tonemapping
@ -20,8 +22,10 @@ void main ()
{ {
gl_FragColor = gl_FragColor =
texture2D(s_t0, tc) + texture2D(s_t0, tc) +
texture2D(s_t1, tc) + cvar_r_bloom*(
texture2D(s_t2, tc) + texture2D(s_t1, tc) +
texture2D(s_t3, tc) ; texture2D(s_t2, tc) +
texture2D(s_t3, tc)
) ;
} }
#endif #endif