Tomaz's awesome new GeForce3 water effect, thanks!
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 19 Sep 2003 20:18:30 +0000 (20:18 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 19 Sep 2003 20:18:30 +0000 (20:18 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3474 d7cf8633-e32d-0410-b094-e92efae38249

gl_rmain.c
gl_rsurf.c
gl_textures.c
glquake.h
menu.c
model_shared.c
model_shared.h
r_textures.h
render.h
vid_shared.c

index 5483275..4aa52d4 100644 (file)
@@ -77,7 +77,7 @@ cvar_t r_textureunits = {0, "r_textureunits", "32"};
 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
-
+cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
 
 
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
@@ -260,6 +260,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_lerpsprites);
        Cvar_RegisterVariable(&r_lerpmodels);
        Cvar_RegisterVariable(&r_waterscroll);
+       Cvar_RegisterVariable(&r_watershader);
        Cvar_RegisterVariable(&r_drawcollisionbrushes);
        if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
                Cvar_SetValue("r_fullbrights", 0);
index 2ea91dc..7bc9d73 100644 (file)
@@ -787,11 +787,17 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        float modelorg[3];
        texture_t *texture;
        matrix4x4_t tempmatrix;
+       float   args[4] = {0.05f,0,0,0.04f};
 
        if (r_waterscroll.value)
        {
                // scrolling in texture matrix
                Matrix4x4_CreateTranslate(&tempmatrix, sin(cl.time) * 0.025 * r_waterscroll.value, sin(cl.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+               if (gl_textureshader && r_watershader.integer)
+               {
+                       R_Mesh_TextureMatrix(1, &tempmatrix);
+                       Matrix4x4_CreateTranslate(&tempmatrix, -sin(cl.time) * 0.025 * r_waterscroll.value, -sin(cl.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+               }
                R_Mesh_TextureMatrix(0, &tempmatrix);
        }
 
@@ -816,7 +822,13 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                GL_BlendFunc(GL_ONE, GL_ZERO);
                GL_DepthMask(true);
        }
-       m.tex[0] = R_GetTexture(texture->skin.base);
+       if (gl_textureshader && r_watershader.integer)
+       {
+               m.tex[0] = R_GetTexture(mod_shared_distorttexture);
+               m.tex[1] = R_GetTexture(texture->skin.base);
+       }
+       else
+               m.tex[0] = R_GetTexture(texture->skin.base);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -829,6 +841,8 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        {
                GL_VertexPointer(mesh->vertex3f);
                m.pointer_texcoord[0] = mesh->texcoordtexture2f;
+               m.pointer_texcoord[1] = mesh->texcoordtexture2f;
+               m.texcombinergb[1] = GL_REPLACE;
                R_Mesh_State_Texture(&m);
                f = surf->flags & SURF_DRAWFULLBRIGHT ? 1.0f : ((surf->flags & SURF_LIGHTMAP) ? 0 : 0.5f);
                R_FillColors(varray_color4f, mesh->numverts, f, f, f, alpha);
@@ -840,7 +854,23 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                                RSurf_AddLightmapToVertexColors_Color4f(mesh->lightmapoffsets, varray_color4f, mesh->numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles);
                }
                RSurf_FogColors_Vertex3f_Color4f(mesh->vertex3f, varray_color4f, colorscale, mesh->numverts, modelorg);
-               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i);
+               if (gl_textureshader && r_watershader.integer)
+               {
+                       GL_ActiveTexture (0);
+                       qglTexEnvi (GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);       
+                       GL_ActiveTexture (1);
+                       qglTexEnvi (GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+                       qglTexEnvi (GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
+                       qglTexEnvi (GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
+                       qglTexEnvfv (GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
+                       qglEnable (GL_TEXTURE_SHADER_NV);
+               }
+               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i);
+               if (gl_textureshader && r_watershader.integer)
+               {
+                       qglDisable (GL_TEXTURE_SHADER_NV);
+                       GL_ActiveTexture (0);
+               }
        }
 
        if (fogenabled)
@@ -865,6 +895,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        {
                Matrix4x4_CreateIdentity(&tempmatrix);
                R_Mesh_TextureMatrix(0, &tempmatrix);
+               R_Mesh_TextureMatrix(1, &tempmatrix);
        }
 }
 
index bcfc554..4c9b11a 100644 (file)
@@ -39,11 +39,12 @@ typedef struct
 }
 textypeinfo_t;
 
-static textypeinfo_t textype_palette       = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 3};
-static textypeinfo_t textype_rgb           = {TEXTYPE_RGB    , 3, 3, GL_RGB , 3};
-static textypeinfo_t textype_rgba          = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 3};
-static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 4};
-static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 4};
+static textypeinfo_t textype_palette       = {TEXTYPE_PALETTE, 1, 4, GL_RGBA   , 3};
+static textypeinfo_t textype_rgb           = {TEXTYPE_RGB    , 3, 3, GL_RGB    , 3};
+static textypeinfo_t textype_rgba          = {TEXTYPE_RGBA   , 4, 4, GL_RGBA   , 3};
+static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA   , 4};
+static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA   , 4};
+static textypeinfo_t textype_dsdt          = {TEXTYPE_DSDT   , 2, 2, GL_DSDT_NV, GL_DSDT8_NV};
 
 // a tiling texture (most common type)
 #define GLIMAGETYPE_TILE 0
@@ -167,6 +168,8 @@ static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags)
                        return &textype_rgb;
                case TEXTYPE_RGBA:
                        return &textype_rgba;
+               case TEXTYPE_DSDT:
+                       return &textype_dsdt;
                default:
                        Host_Error("R_GetTexTypeInfo: unknown texture format\n");
                        return NULL;
@@ -1032,6 +1035,8 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                        }
                }
                break;
+       case TEXTYPE_DSDT:
+               break;
        default:
                Host_Error("R_LoadTexture: unknown texture type\n");
        }
index d6be002..a74e600 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -295,6 +295,17 @@ extern int gl_combine_extension;
 
 extern cvar_t gl_combine;
 
+extern int gl_textureshader;
+#ifndef GL_TEXTURE_SHADER_NV
+#define GL_TEXTURE_SHADER_NV                   0x86DE
+#define GL_SHADER_OPERATION_NV                 0x86DF
+#define GL_OFFSET_TEXTURE_MATRIX_NV            0x86E1
+#define GL_PREVIOUS_TEXTURE_INPUT_NV   0x86E4
+#define GL_OFFSET_TEXTURE_2D_NV                        0x86E8
+#define GL_DSDT_NV                                             0x86F5
+#define GL_DSDT8_NV                                            0x8709
+#endif
+
 extern int gl_texture3d;
 #ifndef GL_TEXTURE_3D
 #define GL_PACK_SKIP_IMAGES                    0x806B
@@ -447,6 +458,7 @@ extern void (GLAPIENTRY *qglStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
 extern void (GLAPIENTRY *qglClearStencil)(GLint s);
 
 //extern void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
+extern void (GLAPIENTRY *qglTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params);
 extern void (GLAPIENTRY *qglTexEnvi)(GLenum target, GLenum pname, GLint param);
 extern void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
 //extern void (GLAPIENTRY *qglTexParameterfv)(GLenum target, GLenum pname, GLfloat *params);
diff --git a/menu.c b/menu.c
index 044dcf8..9e393c8 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -1359,7 +1359,7 @@ void M_Options_Key (int k)
        }
 }
 
-#define        OPTIONS_EFFECTS_ITEMS   20
+#define        OPTIONS_EFFECTS_ITEMS   21
 
 int options_effects_cursor;
 
@@ -1435,6 +1435,8 @@ void M_Menu_Options_Effects_AdjustSliders (int dir)
                Cvar_SetValueQuick (&r_lerpsprites, !r_lerpsprites.integer);
        else if (options_effects_cursor == optnum++)
                Cvar_SetValueQuick (&r_waterscroll, bound(0, r_waterscroll.value + dir * 0.5, 10));
+       else if (options_effects_cursor == optnum++)
+               Cvar_SetValueQuick (&r_watershader, !r_watershader.integer);
 }
 
 void M_Options_Effects_Draw (void)
@@ -1473,6 +1475,7 @@ void M_Options_Effects_Draw (void)
        M_Options_PrintCheckbox("   Model Interpolation", true, r_lerpmodels.integer);
        M_Options_PrintCheckbox("  Sprite Interpolation", true, r_lerpsprites.integer);
        M_Options_PrintSlider(  "        Water Movement", true, r_waterscroll.value, 0, 10);
+       M_Options_PrintCheckbox(" GeForce3 Water Shader", true, r_watershader.integer);
 }
 
 
index 2d519e2..5c578e3 100644 (file)
@@ -37,6 +37,7 @@ static model_t mod_known[MAX_MOD_KNOWN];
 rtexturepool_t *mod_shared_texturepool;
 rtexture_t *r_notexture;
 rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES];
+rtexture_t *mod_shared_distorttexture;
 
 void Mod_BuildDetailTextures (void)
 {
@@ -78,6 +79,24 @@ void Mod_BuildDetailTextures (void)
        }
 }
 
+void Mod_BuildDistortTexture (void)
+{
+       int x, y;
+#define DISTORTRESOLUTION 32
+       qbyte data[DISTORTRESOLUTION][DISTORTRESOLUTION][2];
+       for (y=0; y<DISTORTRESOLUTION; y++)
+       {
+               for (x=0; x<DISTORTRESOLUTION; x++)
+               {
+                       data[y][x][0] = rand () & 255;
+                       data[y][x][1] = rand () & 255;
+               }
+       }
+
+       mod_shared_distorttexture = R_LoadTexture2D(mod_shared_texturepool, "distorttexture", DISTORTRESOLUTION, DISTORTRESOLUTION, &data[0][0][0], TEXTYPE_DSDT, TEXF_PRECACHE, NULL);
+       return;
+}
+
 texture_t r_surf_notexture;
 
 void Mod_SetupNoTexture(void)
@@ -121,6 +140,7 @@ static void mod_start(void)
        mod_shared_texturepool = R_AllocTexturePool();
        Mod_SetupNoTexture();
        Mod_BuildDetailTextures();
+       Mod_BuildDistortTexture();
 }
 
 static void mod_shutdown(void)
index 8a296f3..7c1f5ec 100644 (file)
@@ -543,6 +543,8 @@ extern rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES];
 // every texture must be in a pool...
 extern rtexturepool_t *mod_shared_texturepool;
 
+extern rtexture_t *mod_shared_distorttexture;
+
 // model loading
 extern model_t *loadmodel;
 extern qbyte *mod_base;
index a6e323a..330825a 100644 (file)
@@ -28,6 +28,8 @@
 #define TEXTYPE_RGB 2
 // 32bit RGBA
 #define TEXTYPE_RGBA 3
+// 16bit DSDT
+#define TEXTYPE_DSDT 4
 
 // contents of this structure are mostly private to gl_textures.c
 typedef struct
index 342f92b..b8c6b84 100644 (file)
--- a/render.h
+++ b/render.h
@@ -71,6 +71,7 @@ extern cvar_t r_detailtextures;
 extern cvar_t r_lerpsprites;
 extern cvar_t r_lerpmodels;
 extern cvar_t r_waterscroll;
+extern cvar_t r_watershader;
 
 // useful functions for rendering
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b);
index dfce1bb..1a456d9 100644 (file)
@@ -32,6 +32,8 @@ int gl_support_var = false;
 int gl_support_var2 = false;
 // GL_EXT_texture_filter_anisotropic
 int gl_support_anisotropy = false;
+// GL_NV_texture_shader
+int gl_textureshader = false;
 
 // LordHavoc: if window is hidden, don't update screen
 int vid_hidden = true;
@@ -189,6 +191,7 @@ void (GLAPIENTRY *qglStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
 void (GLAPIENTRY *qglClearStencil)(GLint s);
 
 //void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
+void (GLAPIENTRY *qglTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params);
 void (GLAPIENTRY *qglTexEnvi)(GLenum target, GLenum pname, GLint param);
 void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
 //void (GLAPIENTRY *qglTexParameterfv)(GLenum target, GLenum pname, GLfloat *params);
@@ -329,6 +332,7 @@ static dllfunction_t opengl110funcs[] =
        {"glStencilOp", (void **) &qglStencilOp},
        {"glClearStencil", (void **) &qglClearStencil},
 //     {"glTexEnvf", (void **) &qglTexEnvf},
+       {"glTexEnvfv", (void **) &qglTexEnvfv},
        {"glTexEnvi", (void **) &qglTexEnvi},
        {"glTexParameterf", (void **) &qglTexParameterf},
 //     {"glTexParameterfv", (void **) &qglTexParameterfv},
@@ -456,6 +460,8 @@ void VID_CheckExtensions(void)
 
        gl_support_anisotropy = GL_CheckExtension("GL_EXT_texture_filter_anisotropic", NULL, "-noanisotropy", false);
 
+       gl_textureshader = GL_CheckExtension("GL_NV_texture_shader", NULL, "-notextureshader", false);
+
        // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code
        if (qglDrawRangeElements == NULL)
                qglDrawRangeElements = qglDrawRangeElementsEXT;