summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2013-03-04 20:11:31 +0400
committerAndrey Nazarov <skuller@skuller.net>2013-03-14 20:53:32 +0400
commitbaff433b6a2347ba3b052c6d54027634ea90175e (patch)
tree7884bbe3f4bc36fabce24649204e0a321bcca0a7
parent9ca9cd9374fc98a3aeb466c1f5232bc07d6394b8 (diff)
Improve OpenGL renderer.
Support GL_UNSIGNED_INT and GL_UNSIGNED_SHORT indices for glDrawElements as compile time option. Explicitly generate texture object names for future compatibility with Core profile. Get rid of most GL matrix manipulation functions. Setup our own matrices. Further minimize number of GL state changes. Implement lightmap, flow and warp state bits. Implement client side array state bits. Lazily rebind textures on different TMUs. Lazily toggle multitexturing. Prevent ‘gl_nobind 1’ from interfering with texture uploads. Add support for vertex lighting, activated with ‘gl_vertexlight 1’. Remove dependency on GL_ARB_multitexture extension, renderer should now run on pure OpenGL 1.1 with vertex lighting. Preserve front-to-back ordering of world surfaces when hashing. Optimize drawing path with hashing disabled. Don't hash inline model surfaces. Add support for alpha test surfaces. Don't count meshes when displaying triangles per batch ratio.
-rw-r--r--inc/common/bsp.h6
-rw-r--r--inc/shared/shared.h2
-rw-r--r--src/common/bsp.c4
-rw-r--r--src/refresh/gl/draw.c13
-rw-r--r--src/refresh/gl/gl.h289
-rw-r--r--src/refresh/gl/images.c60
-rw-r--r--src/refresh/gl/main.c92
-rw-r--r--src/refresh/gl/mesh.c119
-rw-r--r--src/refresh/gl/models.c15
-rw-r--r--src/refresh/gl/sky.c11
-rw-r--r--src/refresh/gl/state.c427
-rw-r--r--src/refresh/gl/surf.c502
-rw-r--r--src/refresh/gl/tess.c398
-rw-r--r--src/refresh/gl/world.c179
14 files changed, 1145 insertions, 972 deletions
diff --git a/inc/common/bsp.h b/inc/common/bsp.h
index ca0dba2..47c7797 100644
--- a/inc/common/bsp.h
+++ b/inc/common/bsp.h
@@ -69,8 +69,9 @@ typedef struct {
int vert;
} msurfedge_t;
-#define SURF_NOLM_MASK \
- (SURF_SKY | SURF_WARP | SURF_FLOWING | SURF_TRANS33 | SURF_TRANS66)
+#define SURF_TRANS_MASK (SURF_TRANS33 | SURF_TRANS66)
+#define SURF_COLOR_MASK (SURF_TRANS_MASK | SURF_WARP)
+#define SURF_NOLM_MASK (SURF_COLOR_MASK | SURF_FLOWING | SURF_SKY)
#define DSURF_PLANEBACK 1
@@ -95,6 +96,7 @@ typedef struct mface_s {
#if USE_REF == REF_GL
int texnum[2];
+ int statebits;
int firstvert;
int light_s, light_t;
float stylecache[MAX_LIGHTMAPS];
diff --git a/inc/shared/shared.h b/inc/shared/shared.h
index ba3b87d..372c792 100644
--- a/inc/shared/shared.h
+++ b/inc/shared/shared.h
@@ -695,6 +695,8 @@ COLLISION DETECTION
#define SURF_FLOWING 0x40 // scroll towards angle
#define SURF_NODRAW 0x80 // don't bother referencing the texture
+#define SURF_ALPHATEST 0x02000000 // used by kmquake2
+
// content masks
diff --git a/src/common/bsp.c b/src/common/bsp.c
index aa3a045..804b98a 100644
--- a/src/common/bsp.c
+++ b/src/common/bsp.c
@@ -388,6 +388,10 @@ LOAD(Faces)
DEBUG("bad surfedges");
return Q_ERR_TOO_FEW;
}
+ if (numedges > 4096) {
+ DEBUG("bad surfedges");
+ return Q_ERR_TOO_MANY;
+ }
if (lastedge < firstedge || lastedge > bsp->numsurfedges) {
DEBUG("bad surfedges");
return Q_ERR_BAD_INDEX;
diff --git a/src/refresh/gl/draw.c b/src/refresh/gl/draw.c
index 344cf57..cd54d1a 100644
--- a/src/refresh/gl/draw.c
+++ b/src/refresh/gl/draw.c
@@ -27,7 +27,7 @@ static inline void _GL_StretchPic(
{
vec_t *dst_vert;
uint32_t *dst_color;
- int *dst_indices;
+ QGL_INDEX_TYPE *dst_indices;
if (tess.numverts + 4 > TESS_MAX_VERTICES ||
tess.numindices + 6 > TESS_MAX_INDICES ||
@@ -181,10 +181,7 @@ void R_SetScale(float *scale)
GL_Flush2D();
- qglMatrixMode(GL_PROJECTION);
- qglLoadIdentity();
-
- qglOrtho(0, Q_rint(r_config.width * f),
+ GL_Ortho(0, Q_rint(r_config.width * f),
Q_rint(r_config.height * f), 0, -1, 1);
draw.scale = f;
@@ -339,9 +336,9 @@ void Draw_Stats(void)
}
if (c.batchesDrawn) {
Draw_Stringf(x, y, "Batches drawn: %i", c.batchesDrawn); y += 10;
- Draw_Stringf(x, y, "Faces / batch: %i", c.facesDrawn / c.batchesDrawn);
+ Draw_Stringf(x, y, "Faces / batch: %.1f", (float)c.facesDrawn / c.batchesDrawn);
y += 10;
- Draw_Stringf(x, y, "Tris / batch : %i", c.trisDrawn / c.batchesDrawn);
+ Draw_Stringf(x, y, "Tris / batch : %.1f", (float)c.facesTris / c.batchesDrawn);
y += 10;
}
Draw_Stringf(x, y, "2D batches : %i", c.batchesDrawn2D); y += 10;
@@ -355,7 +352,7 @@ void Draw_Lightmaps(void)
x = i & 1;
y = i >> 1;
_GL_StretchPic(256 * x, 256 * y, 256, 256,
- 0, 0, 1, 1, U32_WHITE, TEXNUM_LIGHTMAP + i, 0);
+ 0, 0, 1, 1, U32_WHITE, lm.texnums[i], 0);
}
}
diff --git a/src/refresh/gl/gl.h b/src/refresh/gl/gl.h
index bd7fe77..e412ecd 100644
--- a/src/refresh/gl/gl.h
+++ b/src/refresh/gl/gl.h
@@ -36,47 +36,60 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*
*/
+#if 0
+#define QGL_INDEX_TYPE GLushort
+#define QGL_INDEX_ENUM GL_UNSIGNED_SHORT
+#else
+#define QGL_INDEX_TYPE GLuint
+#define QGL_INDEX_ENUM GL_UNSIGNED_INT
+#endif
+
#define MAX_TMUS 2
+#define TAB_SIN(x) gl_static.sintab[(x) & 255]
+#define TAB_COS(x) gl_static.sintab[((x) + 64) & 255]
+
+#define NUM_TEXNUMS 6
+
typedef struct {
- qboolean registering;
+ qboolean registering;
struct {
- bsp_t *cache;
- memhunk_t hunk;
- vec_t *vertices;
- GLuint bufnum;
- float add, modulate, scale;
- vec_t size;
+ bsp_t *cache;
+ memhunk_t hunk;
+ vec_t *vertices;
+ GLuint bufnum;
+ vec_t size;
} world;
- GLuint prognum_warp;
- GLbitfield stencil_buffer_bit;
- float entity_modulate;
- float inverse_intensity;
- float sintab[256];
-#define TAB_SIN(x) gl_static.sintab[(x) & 255]
-#define TAB_COS(x) gl_static.sintab[((x) + 64) & 255]
- byte latlngtab[NUMVERTEXNORMALS][2];
- byte lightstylemap[MAX_LIGHTSTYLES];
+ GLuint prognum_warp;
+ GLuint texnums[NUM_TEXNUMS];
+ GLbitfield stencil_buffer_bit;
+ float entity_modulate;
+ uint32_t inverse_intensity_33;
+ uint32_t inverse_intensity_66;
+ uint32_t inverse_intensity_100;
+ float sintab[256];
+ byte latlngtab[NUMVERTEXNORMALS][2];
+ byte lightstylemap[MAX_LIGHTSTYLES];
} glStatic_t;
typedef struct {
- refdef_t fd;
- vec3_t viewaxis[3];
- GLfloat viewmatrix[16];
- int visframe;
- int drawframe;
+ refdef_t fd;
+ vec3_t viewaxis[3];
+ GLfloat viewmatrix[16];
+ int visframe;
+ int drawframe;
#if USE_DLIGHTS
- int dlightframe;
+ int dlightframe;
#endif
- int viewcluster1;
- int viewcluster2;
- cplane_t frustumPlanes[4];
- entity_t *ent;
- qboolean entrotated;
- vec3_t entaxis[3];
- GLfloat entmatrix[16];
- lightpoint_t lightpoint;
- int num_beams;
+ int viewcluster1;
+ int viewcluster2;
+ cplane_t frustumPlanes[4];
+ entity_t *ent;
+ qboolean entrotated;
+ vec3_t entaxis[3];
+ GLfloat entmatrix[16];
+ lightpoint_t lightpoint;
+ int num_beams;
} glRefdef_t;
typedef struct {
@@ -107,6 +120,7 @@ typedef struct {
int leavesDrawn;
int facesMarked;
int facesDrawn;
+ int facesTris;
int texSwitches;
int texUploads;
int trisDrawn;
@@ -155,6 +169,7 @@ extern cvar_t *gl_novis;
extern cvar_t *gl_lockpvs;
extern cvar_t *gl_lightmap;
extern cvar_t *gl_fullbright;
+extern cvar_t *gl_vertexlight;
typedef enum {
CULL_OUT,
@@ -183,35 +198,35 @@ qboolean GL_ShowErrors(const char *func);
*/
typedef struct maliastc_s {
- float st[2];
+ float st[2];
} maliastc_t;
-typedef struct maliasvert_s {
- short pos[3];
- byte norm[2]; // lat, lng
+typedef struct masliasvert_s {
+ short pos[3];
+ byte norm[2]; // lat, lng
} maliasvert_t;
typedef struct maliasframe_s {
- vec3_t scale;
- vec3_t translate;
- vec3_t bounds[2];
- vec_t radius;
+ vec3_t scale;
+ vec3_t translate;
+ vec3_t bounds[2];
+ vec_t radius;
} maliasframe_t;
typedef struct maliasmesh_s {
- int numverts;
- int numtris;
- int numindices;
- uint32_t *indices;
- maliasvert_t *verts;
- maliastc_t *tcoords;
- image_t *skins[MAX_ALIAS_SKINS];
- int numskins;
+ int numverts;
+ int numtris;
+ int numindices;
+ QGL_INDEX_TYPE *indices;
+ maliasvert_t *verts;
+ maliastc_t *tcoords;
+ image_t *skins[MAX_ALIAS_SKINS];
+ int numskins;
} maliasmesh_t;
-// xyz[3] + st[2] + lmst[2]
-// xyz[3] + color[4]
-#define VERTEX_SIZE 7
+// xyz[3] | color[1] | st[2] | lmst[2]
+// xyz[3] | unused[1] | color[4]
+#define VERTEX_SIZE 8
/*
* gl_surf.c
@@ -227,72 +242,141 @@ typedef struct maliasmesh_s {
#define LM_BLOCK_HEIGHT 256
typedef struct {
- int inuse[LM_BLOCK_WIDTH];
- byte buffer[LM_BLOCK_WIDTH * LM_BLOCK_HEIGHT * 4];
- qboolean dirty;
- int comp;
- int nummaps;
- int highwater;
+ int inuse[LM_BLOCK_WIDTH];
+ byte buffer[LM_BLOCK_WIDTH * LM_BLOCK_HEIGHT * 4];
+ qboolean dirty;
+ int comp;
+ float add, modulate, scale;
+ int nummaps;
+ GLuint texnums[LM_MAX_LIGHTMAPS];
} lightmap_builder_t;
extern lightmap_builder_t lm;
void GL_AdjustColor(vec3_t color);
-void GL_BeginLights(void);
-void GL_EndLights(void);
void GL_PushLights(mface_t *surf);
-void LM_RebuildSurfaces(void);
-
-void GL_LoadWorld(const char *name);
+void GL_RebuildLighting(void);
void GL_FreeWorld(void);
+void GL_LoadWorld(const char *name);
/*
* gl_state.c
*
*/
typedef enum {
- GLS_CULL_DISABLE,
- GLS_CULL_FRONT,
- GLS_CULL_BACK
-} glCullFace_t;
-
-typedef enum {
GLS_DEFAULT = 0,
GLS_DEPTHMASK_FALSE = (1 << 0),
GLS_DEPTHTEST_DISABLE = (1 << 1),
GLS_BLEND_BLEND = (1 << 2),
GLS_BLEND_ADD = (1 << 3),
GLS_BLEND_MODULATE = (1 << 4),
- GLS_ALPHATEST_ENABLE = (1 << 5)
+ GLS_ALPHATEST_ENABLE = (1 << 5),
+ GLS_TEXTURE_REPLACE = (1 << 6),
+ GLS_FLOW_ENABLE = (1 << 7),
+ GLS_LIGHTMAP_ENABLE = (1 << 8),
+ GLS_WARP_ENABLE = (1 << 9),
+ GLS_CULL_DISABLE = (1 << 10),
+ GLS_SHADE_SMOOTH = (1 << 11)
} glStateBits_t;
#define GLS_BLEND_MASK (GLS_BLEND_BLEND | GLS_BLEND_ADD | GLS_BLEND_MODULATE)
+typedef enum {
+ GLA_NONE = 0,
+ GLA_VERTEX = (1 << 0),
+ GLA_TC = (1 << 1),
+ GLA_LMTC = (1 << 2),
+ GLA_COLOR = (1 << 3),
+} glArrayBits_t;
+
typedef struct {
- int tmu;
- int texnum[MAX_TMUS];
- GLenum texenv[MAX_TMUS];
- glStateBits_t bits;
- glCullFace_t cull;
- qboolean fp_enabled;
+ GLuint client_tmu;
+ GLuint server_tmu;
+ GLuint texnums[MAX_TMUS];
+ glStateBits_t state_bits;
+ glArrayBits_t array_bits;
+ const GLfloat *currentmatrix;
} glState_t;
extern glState_t gls;
-void GL_BindTexture(int texnum);
-void GL_SelectTMU(int tmu);
-void GL_TexEnv(GLenum texenv);
-void GL_CullFace(glCullFace_t cull);
-void GL_Bits(glStateBits_t bits);
+static inline void GL_ActiveTexture(GLuint tmu)
+{
+ if (gls.server_tmu != tmu) {
+ qglActiveTextureARB(GL_TEXTURE0_ARB + tmu);
+ gls.server_tmu = tmu;
+ }
+}
+
+static inline void GL_ClientActiveTexture(GLuint tmu)
+{
+ if (gls.client_tmu != tmu) {
+ qglClientActiveTextureARB(GL_TEXTURE0_ARB + tmu);
+ gls.client_tmu = tmu;
+ }
+}
+
+static inline void GL_VertexPointer(GLint size, GLsizei stride, const GLfloat *pointer)
+{
+ qglVertexPointer(size, GL_FLOAT, sizeof(GLfloat) * stride, pointer);
+}
+
+static inline void GL_TexCoordPointer(GLint size, GLsizei stride, const GLfloat *pointer)
+{
+ GL_ClientActiveTexture(0);
+ qglTexCoordPointer(size, GL_FLOAT, sizeof(GLfloat) * stride, pointer);
+}
+
+static inline void GL_LightCoordPointer(GLint size, GLsizei stride, const GLfloat *pointer)
+{
+ GL_ClientActiveTexture(1);
+ qglTexCoordPointer(size, GL_FLOAT, sizeof(GLfloat) * stride, pointer);
+}
+
+static inline void GL_ColorBytePointer(GLint size, GLsizei stride, const GLubyte *pointer)
+{
+ qglColorPointer(size, GL_UNSIGNED_BYTE, sizeof(GLfloat) * stride, pointer);
+}
+
+static inline void GL_ColorFloatPointer(GLint size, GLsizei stride, const GLfloat *pointer)
+{
+ qglColorPointer(size, GL_FLOAT, sizeof(GLfloat) * stride, pointer);
+}
+
+static inline void GL_LockArrays(GLsizei count)
+{
+ if (qglLockArraysEXT) {
+ qglLockArraysEXT(0, count);
+ }
+}
+
+static inline void GL_UnlockArrays(void)
+{
+ if (qglUnlockArraysEXT) {
+ qglUnlockArraysEXT();
+ }
+}
+
+static inline void GL_LoadMatrix(const GLfloat *matrix)
+{
+ if (gls.currentmatrix != matrix) {
+ qglLoadMatrixf(matrix);
+ gls.currentmatrix = matrix;
+ }
+}
+
+void GL_ForceTexture(GLuint tmu, GLuint texnum);
+void GL_BindTexture(GLuint tmu, GLuint texnum);
+void GL_StateBits(glStateBits_t bits);
+void GL_ArrayBits(glArrayBits_t bits);
+void GL_LoadMatrix(const GLfloat *matrix);
+void GL_Ortho(GLfloat xmin, GLfloat xmax, GLfloat ymin, GLfloat ymax, GLfloat znear, GLfloat zfar);
void GL_Setup2D(void);
void GL_Setup3D(void);
-
void GL_SetDefaultState(void);
void GL_InitPrograms(void);
void GL_ShutdownPrograms(void);
-void GL_EnableWarp(void);
-void GL_DisableWarp(void);
void GL_EnableOutlines(void);
void GL_DisableOutlines(void);
@@ -302,8 +386,8 @@ void GL_DisableOutlines(void);
*/
typedef struct {
color_t colors[2]; // 0 - actual color, 1 - transparency (for text drawing)
- int flags;
- float scale;
+ int flags;
+ float scale;
} drawStatic_t;
extern drawStatic_t draw;
@@ -324,17 +408,12 @@ void GL_Blend(void);
*/
// auto textures
-enum {
- TEXNUM_DEFAULT = MAX_RIMAGES,
- TEXNUM_SCRAP,
- TEXNUM_PARTICLE,
- TEXNUM_BEAM,
- TEXNUM_WHITE,
- TEXNUM_BLACK,
- TEXNUM_LIGHTMAP // must be the last one
-};
-
-#define NUM_TEXNUMS (TEXNUM_LIGHTMAP + LM_MAX_LIGHTMAPS - TEXNUM_DEFAULT)
+#define TEXNUM_DEFAULT gl_static.texnums[0]
+#define TEXNUM_SCRAP gl_static.texnums[1]
+#define TEXNUM_PARTICLE gl_static.texnums[2]
+#define TEXNUM_BEAM gl_static.texnums[3]
+#define TEXNUM_WHITE gl_static.texnums[4]
+#define TEXNUM_BLACK gl_static.texnums[5]
extern mtexinfo_t *upload_texinfo;
@@ -353,13 +432,13 @@ void GL_ShutdownImages(void);
#define TESS_MAX_INDICES (3 * TESS_MAX_VERTICES)
typedef struct {
- vec_t vertices[VERTEX_SIZE*TESS_MAX_VERTICES];
- int indices[TESS_MAX_INDICES];
- byte colors[4 * TESS_MAX_VERTICES];
- int texnum[MAX_TMUS];
- int numverts;
- int numindices;
- int flags;
+ GLfloat vertices[VERTEX_SIZE * TESS_MAX_VERTICES];
+ QGL_INDEX_TYPE indices[TESS_MAX_INDICES];
+ GLubyte colors[4 * TESS_MAX_VERTICES];
+ GLuint texnum[MAX_TMUS];
+ int numverts;
+ int numindices;
+ int flags;
} tesselator_t;
extern tesselator_t tess;
@@ -368,10 +447,15 @@ void GL_Flush2D(void);
void GL_DrawParticles(void);
void GL_DrawBeams(void);
+void GL_BindArrays(void);
+void GL_Flush3D(void);
+void GL_DrawFace(mface_t *surf);
+
void GL_AddAlphaFace(mface_t *face);
void GL_AddSolidFace(mface_t *face);
void GL_DrawAlphaFaces(void);
void GL_DrawSolidFaces(void);
+void GL_ClearSolidFaces(void);
/*
* gl_world.c
@@ -379,6 +463,7 @@ void GL_DrawSolidFaces(void);
*/
void GL_DrawBspModel(mmodel_t *model);
void GL_DrawWorld(void);
+void GL_SampleLightPoint(vec3_t color);
void GL_LightPoint(vec3_t origin, vec3_t color);
/*
diff --git a/src/refresh/gl/images.c b/src/refresh/gl/images.c
index a6baf8a..5124277 100644
--- a/src/refresh/gl/images.c
+++ b/src/refresh/gl/images.c
@@ -88,7 +88,7 @@ static void gl_texturemode_changed(cvar_t *self)
// change all the existing mipmap texture objects
for (i = 0, image = r_images; i < r_numImages; i++, image++) {
if (image->type == IT_WALL || image->type == IT_SKIN) {
- GL_BindTexture(image->texnum);
+ GL_ForceTexture(0, image->texnum);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
@@ -123,7 +123,7 @@ static void gl_anisotropy_changed(cvar_t *self)
// change all the existing mipmap texture objects
for (i = 0, image = r_images; i < r_numImages; i++, image++) {
if (image->type == IT_WALL || image->type == IT_SKIN) {
- GL_BindTexture(image->texnum);
+ GL_ForceTexture(0, image->texnum);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
gl_filter_anisotropy);
}
@@ -139,7 +139,7 @@ static void gl_bilerp_chars_changed(cvar_t *self)
// change all the existing charset texture objects
for (i = 0, image = r_images; i < r_numImages; i++, image++) {
if (image->type == IT_FONT) {
- GL_BindTexture(image->texnum);
+ GL_ForceTexture(0, image->texnum);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
@@ -155,7 +155,7 @@ static void gl_bilerp_pics_changed(cvar_t *self)
// change all the existing pic texture objects
for (i = 0, image = r_images; i < r_numImages; i++, image++) {
if (image->type == IT_PIC) {
- GL_BindTexture(image->texnum);
+ GL_ForceTexture(0, image->texnum);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
@@ -164,7 +164,7 @@ static void gl_bilerp_pics_changed(cvar_t *self)
// change scrap texture object
if (!gl_noscrap->integer) {
param = self->integer > 1 ? GL_LINEAR : GL_NEAREST;
- GL_BindTexture(TEXNUM_SCRAP);
+ GL_ForceTexture(0, TEXNUM_SCRAP);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
@@ -229,7 +229,8 @@ void Scrap_Upload(void)
if (!scrap_dirty) {
return;
}
- GL_BindTexture(TEXNUM_SCRAP);
+
+ GL_ForceTexture(0, TEXNUM_SCRAP);
GL_Upload8(scrap_data, SCRAP_BLOCK_WIDTH, SCRAP_BLOCK_HEIGHT, qfalse);
scrap_dirty = qfalse;
}
@@ -398,7 +399,7 @@ static void GL_ColorInvertTexture(byte *in, int inwidth, int inheight)
// (useful for small images in scarp, charsets, etc)
static inline qboolean is_nearest(void)
{
- if (gls.texnum[gls.tmu] == TEXNUM_SCRAP && gl_bilerp_pics->integer <= 1) {
+ if (gls.texnums[0] == TEXNUM_SCRAP && gl_bilerp_pics->integer <= 1) {
return qtrue; // hack for scrap texture
}
if (!upload_image) {
@@ -443,7 +444,7 @@ static inline qboolean is_downsample(void)
static inline qboolean is_clamp(void)
{
- if (gls.texnum[gls.tmu] == TEXNUM_SCRAP) {
+ if (gls.texnums[0] == TEXNUM_SCRAP) {
return qtrue; // hack for scrap texture
}
if (!upload_image) {
@@ -735,8 +736,8 @@ void IMG_Load(image_t *image, byte *pic, int width, int height)
R_FloodFillSkin(pic, width, height);
mipmap = (image->type == IT_WALL || image->type == IT_SKIN);
- image->texnum = (image - r_images);
- GL_BindTexture(image->texnum);
+ qglGenTextures(1, &image->texnum);
+ GL_ForceTexture(0, image->texnum);
if (image->flags & IF_PALETTED) {
transparent = GL_Upload8(pic, width, height, mipmap);
} else {
@@ -757,9 +758,9 @@ void IMG_Load(image_t *image, byte *pic, int width, int height)
void IMG_Unload(image_t *image)
{
- if (image->texnum > 0 && image->texnum < MAX_RIMAGES) {
- if (gls.texnum[gls.tmu] == image->texnum)
- gls.texnum[gls.tmu] = 0;
+ if (image->texnum && !(image->flags & IF_SCRAP)) {
+ if (gls.texnums[0] == image->texnum)
+ gls.texnums[0] = 0;
qglDeleteTextures(1, &image->texnum);
image->texnum = 0;
}
@@ -771,7 +772,6 @@ static void GL_BuildIntensityTable(void)
float f;
f = Cvar_ClampValue(gl_intensity, 1, 5);
- gl_static.inverse_intensity = 1 / f;
for (i = 0; i < 256; i++) {
j = i * f;
if (j > 255) {
@@ -779,6 +779,11 @@ static void GL_BuildIntensityTable(void)
}
intensitytable[i] = j;
}
+
+ j = 255.0f / f;
+ gl_static.inverse_intensity_33 = MakeColor(j, j, j, 85);
+ gl_static.inverse_intensity_66 = MakeColor(j, j, j, 170);
+ gl_static.inverse_intensity_100 = MakeColor(j, j, j, 255);
}
static void GL_BuildGammaTables(void)
@@ -838,7 +843,7 @@ static void GL_InitDefaultTexture(void)
}
}
- GL_BindTexture(TEXNUM_DEFAULT);
+ GL_ForceTexture(0, TEXNUM_DEFAULT);
GL_Upload32(pixels, 8, 8, qtrue);
// fill in notexture image
@@ -876,7 +881,7 @@ static void GL_InitParticleTexture(void)
}
}
- GL_BindTexture(TEXNUM_PARTICLE);
+ GL_ForceTexture(0, TEXNUM_PARTICLE);
GL_Upload32(pixels, 16, 16, qfalse);
if (gl_config.version_major == 1 && gl_config.version_minor == 1) {
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
@@ -892,13 +897,13 @@ static void GL_InitWhiteImage(void)
uint32_t pixel;
pixel = U32_WHITE;
- GL_BindTexture(TEXNUM_WHITE);
+ GL_ForceTexture(0, TEXNUM_WHITE);
GL_Upload32((byte *)&pixel, 1, 1, qfalse);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pixel = U32_BLACK;
- GL_BindTexture(TEXNUM_BLACK);
+ GL_ForceTexture(0, TEXNUM_BLACK);
GL_Upload32((byte *)&pixel, 1, 1, qfalse);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -924,7 +929,7 @@ static void GL_InitBeamTexture(void)
}
}
- GL_BindTexture(TEXNUM_BEAM);
+ GL_ForceTexture(0, TEXNUM_BEAM);
GL_Upload32(pixels, 16, 16, qfalse);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -989,12 +994,17 @@ void GL_InitImages(void)
upload_image = NULL;
upload_texinfo = NULL;
+ qglGenTextures(NUM_TEXNUMS, gl_static.texnums);
+ qglGenTextures(LM_MAX_LIGHTMAPS, lm.texnums);
+
Scrap_Init();
GL_InitDefaultTexture();
GL_InitParticleTexture();
GL_InitWhiteImage();
GL_InitBeamTexture();
+
+ GL_ShowErrors(__func__);
}
#ifdef _DEBUG
@@ -1008,9 +1018,6 @@ GL_ShutdownImages
*/
void GL_ShutdownImages(void)
{
- GLuint texnums[NUM_TEXNUMS];
- int i, j;
-
gl_bilerp_chars->changed = NULL;
gl_bilerp_pics->changed = NULL;
gl_texturemode->changed = NULL;
@@ -1019,13 +1026,8 @@ void GL_ShutdownImages(void)
gl_gamma->changed = NULL;
// delete auto textures
- j = TEXNUM_LIGHTMAP + lm.highwater - TEXNUM_DEFAULT;
- for (i = 0; i < j; i++) {
- texnums[i] = TEXNUM_DEFAULT + i;
- }
- qglDeleteTextures(j, texnums);
-
- lm.highwater = 0;
+ qglDeleteTextures(NUM_TEXNUMS, gl_static.texnums);
+ qglDeleteTextures(LM_MAX_LIGHTMAPS, lm.texnums);
#ifdef _DEBUG
r_charset = NULL;
diff --git a/src/refresh/gl/main.c b/src/refresh/gl/main.c
index 2d02de5..95cbb95 100644
--- a/src/refresh/gl/main.c
+++ b/src/refresh/gl/main.c
@@ -78,6 +78,7 @@ cvar_t *gl_novis;
cvar_t *gl_lockpvs;
cvar_t *gl_lightmap;
cvar_t *gl_fullbright;
+cvar_t *gl_vertexlight;
cvar_t *gl_polyblend;
cvar_t *gl_showerrors;
@@ -328,6 +329,9 @@ void GL_RotateForEntity(vec3_t origin)
GL_MultMatrix(glr.entmatrix, glr.viewmatrix, matrix);
qglLoadMatrixf(glr.entmatrix);
+
+ // forced matrix upload
+ gls.currentmatrix = glr.entmatrix;
}
static void GL_DrawSpriteModel(model_t *model)
@@ -353,9 +357,10 @@ static void GL_DrawSpriteModel(model_t *model)
bits |= GLS_BLEND_BLEND;
}
- GL_TexEnv(GL_MODULATE);
- GL_Bits(bits);
- GL_BindTexture(image->texnum);
+ GL_LoadMatrix(glr.viewmatrix);
+ GL_BindTexture(0, image->texnum);
+ GL_StateBits(bits);
+ GL_ArrayBits(GLA_VERTEX | GLA_TC);
qglColor4f(1, 1, 1, alpha);
VectorScale(glr.viewaxis[1], frame->origin_x, left);
@@ -368,8 +373,8 @@ static void GL_DrawSpriteModel(model_t *model)
VectorAdd3(e->origin, down, right, points[2]);
VectorAdd3(e->origin, up, right, points[3]);
- qglTexCoordPointer(2, GL_FLOAT, 0, tcoords);
- qglVertexPointer(3, GL_FLOAT, 0, points);
+ GL_TexCoordPointer(2, 0, tcoords);
+ GL_VertexPointer(3, 0, &points[0][0]);
qglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -391,19 +396,13 @@ static void GL_DrawNullModel(void)
VectorMA(e->origin, 16, glr.entaxis[1], points[3]);
VectorMA(e->origin, 16, glr.entaxis[2], points[5]);
- qglDisable(GL_TEXTURE_2D);
- //qglDisable(GL_DEPTH_TEST);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
- qglEnableClientState(GL_COLOR_ARRAY);
-
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
- qglVertexPointer(3, GL_FLOAT, 0, points);
+ GL_LoadMatrix(glr.viewmatrix);
+ GL_BindTexture(0, TEXNUM_WHITE);
+ GL_StateBits(GLS_DEFAULT);
+ GL_ArrayBits(GLA_VERTEX | GLA_COLOR);
+ GL_ColorBytePointer(4, 0, (GLubyte *)colors);
+ GL_VertexPointer(3, 0, &points[0][0]);
qglDrawArrays(GL_LINES, 0, 6);
-
- qglDisableClientState(GL_COLOR_ARRAY);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
- //qglEnable(GL_DEPTH_TEST);
- qglEnable(GL_TEXTURE_2D);
}
static void GL_DrawEntities(int mask)
@@ -485,39 +484,17 @@ static void GL_DrawEntities(int mask)
static void GL_DrawTearing(void)
{
- vec2_t points[4];
static int i;
// alternate colors to make tearing obvious
i++;
if (i & 1) {
qglClearColor(1, 1, 1, 1);
- qglColor4f(1, 1, 1, 1);
} else {
qglClearColor(1, 0, 0, 0);
- qglColor4f(1, 0, 0, 1);
}
- points[0][0] = 0;
- points[0][1] = r_config.height;
- points[1][0] = 0;
- points[1][1] = 0;
- points[2][0] = r_config.width;
- points[2][1] = r_config.height;
- points[3][0] = r_config.width;
- points[3][1] = 0;
-
qglClear(GL_COLOR_BUFFER_BIT);
-
- qglDisable(GL_TEXTURE_2D);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- qglVertexPointer(2, GL_FLOAT, 0, points);
- qglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglEnable(GL_TEXTURE_2D);
-
qglClearColor(0, 0, 0, 1);
}
@@ -580,13 +557,13 @@ void R_RenderFrame(refdef_t *fd)
glr.num_beams = 0;
#if USE_DLIGHTS
- if (gl_dynamic->integer != 1) {
+ if (gl_dynamic->integer != 1 || gl_vertexlight->integer) {
glr.fd.num_dlights = 0;
}
#endif
if (lm.dirty) {
- LM_RebuildSurfaces();
+ GL_RebuildLighting();
lm.dirty = qfalse;
}
@@ -710,14 +687,20 @@ static size_t GL_ViewCluster_m(char *buffer, size_t size)
return Q_scnprintf(buffer, size, "%d", glr.viewcluster1);
}
+static void gl_lightmap_changed(cvar_t *self)
+{
+ lm.scale = Cvar_ClampValue(gl_coloredlightmaps, 0, 1);
+ lm.comp = lm.scale ? GL_RGB : GL_LUMINANCE;
+ lm.add = 255 * Cvar_ClampValue(gl_brightness, -1, 1);
+ lm.modulate = gl_modulate->value * gl_modulate_world->value;
+ lm.dirty = qtrue; // rebuild all lightmaps next frame
+}
+
static void gl_modulate_entities_changed(cvar_t *self)
{
gl_static.entity_modulate = gl_modulate->value * gl_modulate_entities->value;
}
-// this one is defined in gl_surf.c
-extern void gl_lightmap_changed(cvar_t *self);
-
static void gl_modulate_changed(cvar_t *self)
{
gl_lightmap_changed(self);
@@ -791,10 +774,14 @@ static void GL_Register(void)
gl_lockpvs = Cvar_Get("gl_lockpvs", "0", CVAR_CHEAT);
gl_lightmap = Cvar_Get("gl_lightmap", "0", CVAR_CHEAT);
gl_fullbright = Cvar_Get("r_fullbright", "0", CVAR_CHEAT);
+ gl_fullbright->changed = gl_lightmap_changed;
+ gl_vertexlight = Cvar_Get("gl_vertexlight", "0", 0);
+ gl_vertexlight->changed = gl_lightmap_changed;
gl_polyblend = Cvar_Get("gl_polyblend", "1", 0);
gl_showerrors = Cvar_Get("gl_showerrors", "1", 0);
- gl_modulate_entities_changed(gl_modulate_entities);
+ gl_lightmap_changed(NULL);
+ gl_modulate_entities_changed(NULL);
Cmd_AddCommand("strings", GL_Strings_f);
Cmd_AddMacro("gl_viewcluster", GL_ViewCluster_m);
@@ -838,14 +825,8 @@ static qboolean GL_SetupConfig(void)
return qfalse;
}
- // get extensions string
+ // get and parse extension string
extensions = (const char *)qglGetString(GL_EXTENSIONS);
- if (!extensions || !*extensions) {
- Com_EPrintf("No OpenGL extensions found, check your drivers\n");
- return qfalse;
- }
-
- // parse extension string
gl_config.ext_supported = QGL_ParseExtensionString(extensions);
gl_config.ext_enabled = 0;
@@ -892,12 +873,6 @@ static qboolean GL_SetupConfig(void)
QGL_InitExtensions(gl_config.ext_enabled);
- // lack of multitexture support is a show stopper
- if (!qglActiveTextureARB) {
- Com_EPrintf("Required GL_ARB_multitexture extension is missing\n");
- return qfalse;
- }
-
qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &integer);
if (integer < 256) {
Com_EPrintf("OpenGL reports invalid maximum texture size\n");
@@ -928,6 +903,7 @@ static qboolean GL_SetupConfig(void)
qglGetIntegerv(GL_STENCIL_BITS, &integer);
gl_config.stencilbits = integer;
+ GL_ShowErrors(__func__);
return qtrue;
}
diff --git a/src/refresh/gl/mesh.c b/src/refresh/gl/mesh.c
index e1650c3..e469339 100644
--- a/src/refresh/gl/mesh.c
+++ b/src/refresh/gl/mesh.c
@@ -127,10 +127,10 @@ static void tess_static_shade(const maliasmesh_t *mesh)
dst_vert[0] = src_vert->pos[0] * newscale[0] + translate[0];
dst_vert[1] = src_vert->pos[1] * newscale[1] + translate[1];
dst_vert[2] = src_vert->pos[2] * newscale[2] + translate[2];
- dst_vert[3] = shadelight[0] * d;
- dst_vert[4] = shadelight[1] * d;
- dst_vert[5] = shadelight[2] * d;
- dst_vert[6] = shadelight[3];
+ dst_vert[4] = shadelight[0] * d;
+ dst_vert[5] = shadelight[1] * d;
+ dst_vert[6] = shadelight[2] * d;
+ dst_vert[7] = shadelight[3];
dst_vert += VERTEX_SIZE;
src_vert++;
@@ -220,10 +220,10 @@ static void tess_lerped_shade(const maliasmesh_t *mesh)
dst_vert[2] =
src_oldvert->pos[2] * oldscale[2] +
src_newvert->pos[2] * newscale[2] + translate[2];
- dst_vert[3] = shadelight[0] * d;
- dst_vert[4] = shadelight[1] * d;
- dst_vert[5] = shadelight[2] * d;
- dst_vert[6] = shadelight[3];
+ dst_vert[4] = shadelight[0] * d;
+ dst_vert[5] = shadelight[1] * d;
+ dst_vert[6] = shadelight[2] * d;
+ dst_vert[7] = shadelight[3];
dst_vert += VERTEX_SIZE;
src_oldvert++;
@@ -424,29 +424,19 @@ static void draw_celshading(maliasmesh_t *mesh)
if (celscale < 0.01f || celscale > 1)
return;
- GL_Bits(GLS_BLEND_BLEND);
- qglDisable(GL_TEXTURE_2D);
+ GL_BindTexture(0, TEXNUM_BLACK);
+ GL_StateBits(GLS_BLEND_BLEND);
+ GL_ArrayBits(GLA_VERTEX);
+
qglLineWidth(gl_celshading->value * celscale);
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
qglCullFace(GL_FRONT);
-
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
- if (shadelight)
- qglDisableClientState(GL_COLOR_ARRAY);
-
qglColor4f(0, 0, 0, color[3] * celscale);
- qglDrawElements(GL_TRIANGLES, mesh->numindices, GL_UNSIGNED_INT,
+ qglDrawElements(GL_TRIANGLES, mesh->numindices, QGL_INDEX_ENUM,
mesh->indices);
- qglColor4fv(color);
-
- if (shadelight)
- qglEnableClientState(GL_COLOR_ARRAY);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
qglCullFace(GL_BACK);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
qglLineWidth(1);
- qglEnable(GL_TEXTURE_2D);
}
static void setup_shadow(void)
@@ -530,7 +520,7 @@ static void draw_shadow(maliasmesh_t *mesh)
return;
// load shadow projection matrix
- qglLoadMatrixf(shadowmatrix);
+ GL_LoadMatrix(shadowmatrix);
// eliminate z-fighting by utilizing stencil buffer, if available
if (gl_config.stencilbits) {
@@ -539,26 +529,17 @@ static void draw_shadow(maliasmesh_t *mesh)
qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
}
- GL_Bits(GLS_BLEND_BLEND);
- GL_TexEnv(GL_MODULATE);
- GL_BindTexture(TEXNUM_WHITE);
-
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
- if (shadelight)
- qglDisableClientState(GL_COLOR_ARRAY);
+ GL_StateBits(GLS_BLEND_BLEND);
+ GL_BindTexture(0, TEXNUM_WHITE);
+ GL_ArrayBits(GLA_VERTEX);
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(-1.0f, -2.0f);
qglColor4f(0, 0, 0, color[3] * 0.5f);
- qglDrawElements(GL_TRIANGLES, mesh->numindices, GL_UNSIGNED_INT,
+ qglDrawElements(GL_TRIANGLES, mesh->numindices, QGL_INDEX_ENUM,
mesh->indices);
- qglColor4fv(color);
qglDisable(GL_POLYGON_OFFSET_FILL);
- if (shadelight)
- qglEnableClientState(GL_COLOR_ARRAY);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
// once we have drawn something to stencil buffer, continue to clear it for
// the lifetime of OpenGL context. leaving stencil buffer "dirty" and
// clearing just depth is slower (verified for Nvidia and ATI drivers).
@@ -566,9 +547,6 @@ static void draw_shadow(maliasmesh_t *mesh)
qglDisable(GL_STENCIL_TEST);
gl_static.stencil_buffer_bit |= GL_STENCIL_BUFFER_BIT;
}
-
- // fall back to entity matrix
- qglLoadMatrixf(glr.entmatrix);
}
static int texnum_for_mesh(maliasmesh_t *mesh)
@@ -597,30 +575,46 @@ static int texnum_for_mesh(maliasmesh_t *mesh)
static void draw_alias_mesh(maliasmesh_t *mesh)
{
+ glStateBits_t state = GLS_DEFAULT;
+
+ // fall back to entity matrix
+ GL_LoadMatrix(glr.entmatrix);
+
+ if (shadelight)
+ state |= GLS_SHADE_SMOOTH;
+
if (glr.ent->flags & RF_TRANSLUCENT)
- GL_Bits(GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE);
- else
- GL_Bits(GLS_DEFAULT);
+ state |= GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE;
+
+ GL_StateBits(state);
- GL_TexEnv(GL_MODULATE);
- GL_BindTexture(texnum_for_mesh(mesh));
+ GL_BindTexture(0, texnum_for_mesh(mesh));
(*tessfunc)(mesh);
c.trisDrawn += mesh->numverts;
- qglTexCoordPointer(2, GL_FLOAT, 0, mesh->tcoords);
+ if (shadelight) {
+ GL_ArrayBits(GLA_VERTEX | GLA_TC | GLA_COLOR);
+ GL_VertexPointer(3, VERTEX_SIZE, tess.vertices);
+ GL_ColorFloatPointer(4, VERTEX_SIZE, tess.vertices + 4);
+ } else {
+ GL_ArrayBits(GLA_VERTEX | GLA_TC);
+ GL_VertexPointer(3, 4, tess.vertices);
+ qglColor4fv(color);
+ }
- if (qglLockArraysEXT)
- qglLockArraysEXT(0, mesh->numverts);
+ GL_TexCoordPointer(2, 0, (GLfloat *)mesh->tcoords);
- qglDrawElements(GL_TRIANGLES, mesh->numindices, GL_UNSIGNED_INT,
+ GL_LockArrays(mesh->numverts);
+
+ qglDrawElements(GL_TRIANGLES, mesh->numindices, QGL_INDEX_ENUM,
mesh->indices);
draw_celshading(mesh);
if (gl_showtris->integer) {
GL_EnableOutlines();
- qglDrawElements(GL_TRIANGLES, mesh->numindices, GL_UNSIGNED_INT,
+ qglDrawElements(GL_TRIANGLES, mesh->numindices, QGL_INDEX_ENUM,
mesh->indices);
GL_DisableOutlines();
}
@@ -628,15 +622,14 @@ static void draw_alias_mesh(maliasmesh_t *mesh)
// FIXME: unlock arrays before changing matrix?
draw_shadow(mesh);
- if (qglUnlockArraysEXT)
- qglUnlockArraysEXT();
+ GL_UnlockArrays();
}
void GL_DrawAliasModel(model_t *model)
{
entity_t *ent = glr.ent;
glCullResult_t cull;
- maliasmesh_t *mesh, *last;
+ int i;
newframenum = ent->frame;
if (newframenum < 0 || newframenum >= model->numframes) {
@@ -692,7 +685,6 @@ void GL_DrawAliasModel(model_t *model)
tess_static_plain : tess_lerped_plain;
}
- qglPushMatrix();
GL_RotateForEntity(origin);
if ((ent->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) ==
@@ -706,22 +698,9 @@ void GL_DrawAliasModel(model_t *model)
if (ent->flags & RF_DEPTHHACK)
qglDepthRange(0, 0.25f);
- if (shadelight) {
- qglVertexPointer(3, GL_FLOAT, 4 * VERTEX_SIZE, tess.vertices);
- qglColorPointer(4, GL_FLOAT, 4 * VERTEX_SIZE, tess.vertices + 3);
- qglEnableClientState(GL_COLOR_ARRAY);
- } else {
- qglVertexPointer(3, GL_FLOAT, 4 * 4, tess.vertices);
- qglColor4fv(color);
- }
-
// draw all the meshes
- last = model->meshes + model->nummeshes;
- for (mesh = model->meshes; mesh != last; mesh++)
- draw_alias_mesh(mesh);
-
- if (shadelight)
- qglDisableClientState(GL_COLOR_ARRAY);
+ for (i = 0; i < model->nummeshes; i++)
+ draw_alias_mesh(&model->meshes[i]);
if (ent->flags & RF_DEPTHHACK)
qglDepthRange(0, 1);
@@ -733,7 +712,5 @@ void GL_DrawAliasModel(model_t *model)
qglMatrixMode(GL_MODELVIEW);
qglFrontFace(GL_CW);
}
-
- qglPopMatrix();
}
diff --git a/src/refresh/gl/models.c b/src/refresh/gl/models.c
index cb1aa46..64524c5 100644
--- a/src/refresh/gl/models.c
+++ b/src/refresh/gl/models.c
@@ -31,7 +31,7 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
maliasframe_t *dst_frame;
maliasvert_t *dst_vert;
maliasmesh_t *dst_mesh;
- uint32_t *finalIndices;
+ QGL_INDEX_TYPE *finalIndices;
maliastc_t *dst_tc;
int i, j, k;
uint16_t remap[MD2_MAX_TRIANGLES * 3];
@@ -229,7 +229,8 @@ qerror_t MOD_LoadMD3(model_t *model, const void *rawdata, size_t length)
maliasmesh_t *dst_mesh;
maliasvert_t *dst_vert;
maliastc_t *dst_tc;
- uint32_t *dst_idx;
+ QGL_INDEX_TYPE *dst_idx;
+ uint32_t index;
uint32_t numverts, numtris, numskins;
uint32_t totalVerts;
char skinname[MAX_QPATH];
@@ -387,15 +388,13 @@ qerror_t MOD_LoadMD3(model_t *model, const void *rawdata, size_t length)
goto fail;
}
dst_idx = dst_mesh->indices;
- for (j = 0; j < numtris; j++) {
- dst_idx[0] = LittleLong(src_idx[0]);
- dst_idx[1] = LittleLong(src_idx[1]);
- dst_idx[2] = LittleLong(src_idx[2]);
- if (dst_idx[0] >= numverts || dst_idx[1] >= numverts || dst_idx[2] >= numverts) {
+ for (j = 0; j < numtris * 3; j++) {
+ index = LittleLong(*src_idx++);
+ if (index >= numverts) {
ret = Q_ERR_BAD_INDEX;
goto fail;
}
- src_idx += 3; dst_idx += 3;
+ *dst_idx++ = index;
}
offset = LittleLong(src_mesh->meshsize);
diff --git a/src/refresh/gl/sky.c b/src/refresh/gl/sky.c
index d0e7807..beee1d4 100644
--- a/src/refresh/gl/sky.c
+++ b/src/refresh/gl/sky.c
@@ -369,18 +369,17 @@ void R_DrawSkyBox(void)
SkyRotate();
}
- GL_TexEnv(GL_REPLACE);
- GL_Bits(GLS_DEFAULT);
-
- qglVertexPointer(3, GL_FLOAT, 5 * 4, &verts[0][0]);
- qglTexCoordPointer(2, GL_FLOAT, 5 * 4, &verts[0][3]);
+ GL_StateBits(GLS_TEXTURE_REPLACE);
+ GL_ArrayBits(GLA_VERTEX | GLA_TC);
+ GL_VertexPointer(3, 5, &verts[0][0]);
+ GL_TexCoordPointer(2, 5, &verts[0][3]);
for (i = 0; i < 6; i++) {
if (!SKY_VISIBLE(i)) {
continue;
}
- GL_BindTexture(sky_images[skytexorder[i]]);
+ GL_BindTexture(0, sky_images[skytexorder[i]]);
MakeSkyVec(skymaxs[0][i], skymins[1][i], i, verts[0]);
MakeSkyVec(skymins[0][i], skymins[1][i], i, verts[1]);
diff --git a/src/refresh/gl/state.c b/src/refresh/gl/state.c
index 732c103..3d8c6b4 100644
--- a/src/refresh/gl/state.c
+++ b/src/refresh/gl/state.c
@@ -21,89 +21,45 @@ with this program; if not, write to the Free Software Foundation, Inc.,
glState_t gls;
-void GL_BindTexture(int texnum)
+// for uploading
+void GL_ForceTexture(GLuint tmu, GLuint texnum)
{
-#ifdef _DEBUG
- if (gl_nobind->integer && !gls.tmu) {
- texnum = TEXNUM_DEFAULT;
- }
-#endif
+ GL_ActiveTexture(tmu);
- if (gls.texnum[gls.tmu] == texnum) {
+ if (gls.texnums[tmu] == texnum) {
return;
}
qglBindTexture(GL_TEXTURE_2D, texnum);
- gls.texnum[gls.tmu] = texnum;
+ gls.texnums[tmu] = texnum;
c.texSwitches++;
}
-void GL_SelectTMU(int tmu)
+// for drawing
+void GL_BindTexture(GLuint tmu, GLuint texnum)
{
- if (gls.tmu == tmu) {
- return;
- }
-
- if (tmu < 0 || tmu >= gl_config.numTextureUnits) {
- Com_Error(ERR_FATAL, "GL_SelectTMU: bad tmu %d", tmu);
+#ifdef _DEBUG
+ if (gl_nobind->integer && !tmu) {
+ texnum = TEXNUM_DEFAULT;
}
+#endif
- qglActiveTextureARB(GL_TEXTURE0_ARB + tmu);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB + tmu);
-
- gls.tmu = tmu;
-}
-
-void GL_TexEnv(GLenum texenv)
-{
- if (gls.texenv[gls.tmu] == texenv) {
+ if (gls.texnums[tmu] == texnum) {
return;
}
- switch (texenv) {
- case GL_REPLACE:
- case GL_MODULATE:
- case GL_BLEND:
- case GL_ADD:
- qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texenv);
- break;
- default:
- Com_Error(ERR_FATAL, "GL_TexEnv: bad texenv");
- break;
- }
-
- gls.texenv[gls.tmu] = texenv;
-}
+ GL_ActiveTexture(tmu);
-void GL_CullFace(glCullFace_t cull)
-{
- if (gls.cull == cull) {
- return;
- }
- switch (cull) {
- case GLS_CULL_DISABLE:
- qglDisable(GL_CULL_FACE);
- break;
- case GLS_CULL_FRONT:
- qglEnable(GL_CULL_FACE);
- qglCullFace(GL_FRONT);
- break;
- case GLS_CULL_BACK:
- qglEnable(GL_CULL_FACE);
- qglCullFace(GL_BACK);
- break;
- default:
- Com_Error(ERR_FATAL, "GL_CullFace: bad cull");
- break;
- }
+ qglBindTexture(GL_TEXTURE_2D, texnum);
+ gls.texnums[tmu] = texnum;
- gls.cull = cull;
+ c.texSwitches++;
}
-void GL_Bits(glStateBits_t bits)
+void GL_StateBits(glStateBits_t bits)
{
- glStateBits_t diff = bits ^ gls.bits;
+ glStateBits_t diff = bits ^ gls.state_bits;
if (!diff) {
return;
@@ -148,17 +104,165 @@ void GL_Bits(glStateBits_t bits)
}
}
- gls.bits = bits;
+ if (diff & GLS_TEXTURE_REPLACE) {
+ GL_ActiveTexture(0);
+ if (bits & GLS_TEXTURE_REPLACE) {
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ } else {
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ }
+ }
+
+ if (diff & GLS_FLOW_ENABLE) {
+ GL_ActiveTexture(0);
+ qglMatrixMode(GL_TEXTURE);
+
+ if (bits & GLS_FLOW_ENABLE) {
+ float scaled, scroll;
+
+ if (bits & GLS_WARP_ENABLE) {
+ scaled = glr.fd.time * 0.5f;
+ scroll = -scaled;
+ } else {
+ scaled = glr.fd.time / 40;
+ scroll = -64 * (scaled - (int)scaled);
+ }
+
+ qglTranslatef(scroll, 0, 0);
+ } else {
+ qglLoadIdentity();
+ }
+
+ qglMatrixMode(GL_MODELVIEW);
+ }
+
+ if (diff & GLS_LIGHTMAP_ENABLE) {
+ GL_ActiveTexture(1);
+ if (bits & GLS_LIGHTMAP_ENABLE) {
+ qglEnable(GL_TEXTURE_2D);
+ } else {
+ qglDisable(GL_TEXTURE_2D);
+ }
+ }
+
+ if ((diff & GLS_WARP_ENABLE) && gl_static.prognum_warp) {
+ if (bits & GLS_WARP_ENABLE) {
+ vec4_t param;
+
+ qglEnable(GL_FRAGMENT_PROGRAM_ARB);
+ qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp);
+ param[0] = glr.fd.time;
+ param[1] = glr.fd.time;
+ param[2] = param[3] = 0;
+ qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param);
+ } else {
+ qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
+ qglDisable(GL_FRAGMENT_PROGRAM_ARB);
+ }
+ }
+
+ if (diff & GLS_CULL_DISABLE) {
+ if (bits & GLS_CULL_DISABLE) {
+ qglDisable(GL_CULL_FACE);
+ } else {
+ qglEnable(GL_CULL_FACE);
+ }
+ }
+
+ if (diff & GLS_SHADE_SMOOTH) {
+ if (bits & GLS_SHADE_SMOOTH) {
+ qglShadeModel(GL_SMOOTH);
+ } else {
+ qglShadeModel(GL_FLAT);
+ }
+ }
+
+ gls.state_bits = bits;
}
-void GL_Setup2D(void)
+void GL_ArrayBits(glArrayBits_t bits)
{
- qglViewport(0, 0, r_config.width, r_config.height);
+ glArrayBits_t diff = bits ^ gls.array_bits;
+
+ if (!diff) {
+ return;
+ }
+
+ if (diff & GLA_VERTEX) {
+ if (bits & GLA_VERTEX) {
+ qglEnableClientState(GL_VERTEX_ARRAY);
+ } else {
+ qglDisableClientState(GL_VERTEX_ARRAY);
+ }
+ }
+
+ if (diff & GLA_TC) {
+ GL_ClientActiveTexture(0);
+ if (bits & GLA_TC) {
+ qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+
+ if (diff & GLA_LMTC) {
+ GL_ClientActiveTexture(1);
+ if (bits & GLA_LMTC) {
+ qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+
+ if (diff & GLA_COLOR) {
+ if (bits & GLA_COLOR) {
+ qglEnableClientState(GL_COLOR_ARRAY);
+ } else {
+ qglDisableClientState(GL_COLOR_ARRAY);
+ }
+ }
+
+ gls.array_bits = bits;
+}
+
+void GL_Ortho(GLfloat xmin, GLfloat xmax, GLfloat ymin, GLfloat ymax, GLfloat znear, GLfloat zfar)
+{
+ GLfloat width, height, depth;
+ GLfloat matrix[16];
+
+ width = xmax - xmin;
+ height = ymax - ymin;
+ depth = zfar - znear;
+
+ matrix[0] = 2 / width;
+ matrix[4] = 0;
+ matrix[8] = 0;
+ matrix[12] = -(xmax + xmin) / width;
+
+ matrix[1] = 0;
+ matrix[5] = 2 / height;
+ matrix[9] = 0;
+ matrix[13] = -(ymax + ymin) / height;
+
+ matrix[2] = 0;
+ matrix[6] = 0;
+ matrix[10] = -2 / depth;
+ matrix[14] = -(zfar + znear) / depth;
+
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = 0;
+ matrix[15] = 1;
qglMatrixMode(GL_PROJECTION);
- qglLoadIdentity();
+ qglLoadMatrixf(matrix);
+}
- qglOrtho(0, r_config.width, r_config.height, 0, -1, 1);
+void GL_Setup2D(void)
+{
+ qglViewport(0, 0, r_config.width, r_config.height);
+
+ GL_Ortho(0, r_config.width, r_config.height, 0, -1, 1);
draw.scale = 1;
draw.colors[0].u32 = U32_WHITE;
@@ -172,63 +276,99 @@ void GL_Setup2D(void)
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity();
-
- GL_Bits(GLS_DEPTHTEST_DISABLE);
- GL_CullFace(GLS_CULL_DISABLE);
}
-void GL_Setup3D(void)
+static void GL_Frustum(void)
{
- GLdouble xmin, xmax, ymin, ymax, zfar;
- int yb = glr.fd.y + glr.fd.height;
+ GLfloat xmin, xmax, ymin, ymax, zfar, znear;
+ GLfloat width, height, depth;
+ GLfloat matrix[16];
- qglViewport(glr.fd.x, r_config.height - yb,
- glr.fd.width, glr.fd.height);
+ znear = gl_znear->value;
- qglMatrixMode(GL_PROJECTION);
- qglLoadIdentity();
+ if (glr.fd.rdflags & RDF_NOWORLDMODEL)
+ zfar = 2048;
+ else
+ zfar = gl_static.world.size * 2;
- ymax = gl_znear->value * tan(glr.fd.fov_y * M_PI / 360.0);
+ ymax = znear * tan(glr.fd.fov_y * M_PI / 360.0);
ymin = -ymax;
- xmax = gl_znear->value * tan(glr.fd.fov_x * M_PI / 360.0);
+ xmax = znear * tan(glr.fd.fov_x * M_PI / 360.0);
xmin = -xmax;
- if (glr.fd.rdflags & RDF_NOWORLDMODEL)
- zfar = 2048;
- else
- zfar = gl_static.world.size * 2;
+ width = xmax - xmin;
+ height = ymax - ymin;
+ depth = zfar - znear;
- qglFrustum(xmin, xmax, ymin, ymax, gl_znear->value, zfar);
+ matrix[0] = 2 * znear / width;
+ matrix[4] = 0;
+ matrix[8] = (xmax + xmin) / width;
+ matrix[12] = 0;
- qglMatrixMode(GL_MODELVIEW);
+ matrix[1] = 0;
+ matrix[5] = 2 * znear / height;
+ matrix[9] = (ymax + ymin) / height;
+ matrix[13] = 0;
+
+ matrix[2] = 0;
+ matrix[6] = 0;
+ matrix[10] = -(zfar + znear) / depth;
+ matrix[14] = -2 * zfar * znear / depth;
+
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = -1;
+ matrix[15] = 0;
+
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadMatrixf(matrix);
+}
+
+static void GL_RotateForViewer(void)
+{
+ GLfloat *matrix = glr.viewmatrix;
AnglesToAxis(glr.fd.viewangles, glr.viewaxis);
- glr.viewmatrix[0] = -glr.viewaxis[1][0];
- glr.viewmatrix[4] = -glr.viewaxis[1][1];
- glr.viewmatrix[8] = -glr.viewaxis[1][2];
- glr.viewmatrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg);
+ matrix[0] = -glr.viewaxis[1][0];
+ matrix[4] = -glr.viewaxis[1][1];
+ matrix[8] = -glr.viewaxis[1][2];
+ matrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg);
- glr.viewmatrix[1] = glr.viewaxis[2][0];
- glr.viewmatrix[5] = glr.viewaxis[2][1];
- glr.viewmatrix[9] = glr.viewaxis[2][2];
- glr.viewmatrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg);
+ matrix[1] = glr.viewaxis[2][0];
+ matrix[5] = glr.viewaxis[2][1];
+ matrix[9] = glr.viewaxis[2][2];
+ matrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg);
- glr.viewmatrix[2] = -glr.viewaxis[0][0];
- glr.viewmatrix[6] = -glr.viewaxis[0][1];
- glr.viewmatrix[10] = -glr.viewaxis[0][2];
- glr.viewmatrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg);
+ matrix[2] = -glr.viewaxis[0][0];
+ matrix[6] = -glr.viewaxis[0][1];
+ matrix[10] = -glr.viewaxis[0][2];
+ matrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg);
- glr.viewmatrix[3] = 0;
- glr.viewmatrix[7] = 0;
- glr.viewmatrix[11] = 0;
- glr.viewmatrix[15] = 1;
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = 0;
+ matrix[15] = 1;
- qglLoadMatrixf(glr.viewmatrix);
+ qglMatrixMode(GL_MODELVIEW);
+ qglLoadMatrixf(matrix);
- GL_Bits(GLS_DEFAULT);
- GL_CullFace(GLS_CULL_BACK);
+ // forced matrix upload
+ gls.currentmatrix = matrix;
+}
+
+void GL_Setup3D(void)
+{
+ qglViewport(glr.fd.x, r_config.height - (glr.fd.y + glr.fd.height),
+ glr.fd.width, glr.fd.height);
+
+ GL_Frustum();
+
+ GL_RotateForViewer();
+
+ // enable depth writes before clearing
+ GL_StateBits(GLS_DEFAULT);
qglClear(GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit);
}
@@ -246,22 +386,35 @@ void GL_SetDefaultState(void)
qglDisable(GL_BLEND);
qglDisable(GL_ALPHA_TEST);
qglAlphaFunc(GL_GREATER, 0.666f);
- qglFrontFace(GL_CW);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ qglFrontFace(GL_CW);
+ qglCullFace(GL_BACK);
+ qglEnable(GL_CULL_FACE);
+ qglShadeModel(GL_FLAT);
+
+ if (qglActiveTextureARB && qglClientActiveTextureARB) {
+ qglActiveTextureARB(GL_TEXTURE1_ARB);
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglDisable(GL_TEXTURE_2D);
+ qglClientActiveTextureARB(GL_TEXTURE1_ARB);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ qglActiveTextureARB(GL_TEXTURE0_ARB);
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglEnable(GL_TEXTURE_2D);
+ qglClientActiveTextureARB(GL_TEXTURE0_ARB);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ qglBindTexture(GL_TEXTURE_2D, 0);
+ qglEnable(GL_TEXTURE_2D);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
- qglActiveTextureARB(GL_TEXTURE1_ARB);
- qglClientActiveTextureARB(GL_TEXTURE1_ARB);
- qglBindTexture(GL_TEXTURE_2D, 0);
- qglDisable(GL_TEXTURE_2D);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- qglActiveTextureARB(GL_TEXTURE0_ARB);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB);
- qglBindTexture(GL_TEXTURE_2D, 0);
- qglEnable(GL_TEXTURE_2D);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ qglMatrixMode(GL_TEXTURE);
+ qglLoadIdentity();
+ qglMatrixMode(GL_MODELVIEW);
- qglEnableClientState(GL_VERTEX_ARRAY);
+ qglDisableClientState(GL_VERTEX_ARRAY);
qglDisableClientState(GL_COLOR_ARRAY);
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit);
@@ -287,45 +440,19 @@ byte *IMG_ReadPixels(qboolean reverse, int *width, int *height)
void GL_EnableOutlines(void)
{
- if (gls.fp_enabled) {
- qglDisable(GL_FRAGMENT_PROGRAM_ARB);
- }
- qglDisable(GL_TEXTURE_2D);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ GL_BindTexture(0, TEXNUM_WHITE);
+ GL_StateBits(GLS_DEFAULT);
+ GL_ArrayBits(GLA_VERTEX);
+ qglColor4f(1, 1, 1, 1);
+
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
qglDepthRange(0, 0);
- qglColor4f(1, 1, 1, 1);
}
void GL_DisableOutlines(void)
{
qglDepthRange(0, 1);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglEnable(GL_TEXTURE_2D);
- if (gls.fp_enabled) {
- qglEnable(GL_FRAGMENT_PROGRAM_ARB);
- }
-}
-
-void GL_EnableWarp(void)
-{
- vec4_t param;
-
- qglEnable(GL_FRAGMENT_PROGRAM_ARB);
- qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp);
- param[0] = glr.fd.time;
- param[1] = glr.fd.time;
- param[2] = param[3] = 0;
- qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param);
- gls.fp_enabled = qtrue;
-}
-
-void GL_DisableWarp(void)
-{
- qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
- qglDisable(GL_FRAGMENT_PROGRAM_ARB);
- gls.fp_enabled = qfalse;
}
void GL_InitPrograms(void)
@@ -345,7 +472,8 @@ void GL_InitPrograms(void)
Cvar_Set("gl_fragment_program", "0");
}
- if (!qglProgramStringARB) {
+ if (!qglGenProgramsARB || !qglBindProgramARB ||
+ !qglProgramStringARB || !qglDeleteProgramsARB) {
return;
}
@@ -379,4 +507,3 @@ void GL_ShutdownPrograms(void)
QGL_ShutdownExtensions(QGL_ARB_fragment_program);
gl_config.ext_enabled &= ~QGL_ARB_fragment_program;
}
-
diff --git a/src/refresh/gl/surf.c b/src/refresh/gl/surf.c
index 7fd44b8..cb86462 100644
--- a/src/refresh/gl/surf.c
+++ b/src/refresh/gl/surf.c
@@ -38,9 +38,9 @@ adjust_color_f(vec_t *out, const vec_t *in, float modulate)
float r, g, b, y, max;
// add & modulate
- r = (in[0] + gl_static.world.add) * modulate;
- g = (in[1] + gl_static.world.add) * modulate;
- b = (in[2] + gl_static.world.add) * modulate;
+ r = (in[0] + lm.add) * modulate;
+ g = (in[1] + lm.add) * modulate;
+ b = (in[2] + lm.add) * modulate;
// catch negative lights
if (r < 0) r = 0;
@@ -67,11 +67,11 @@ adjust_color_f(vec_t *out, const vec_t *in, float modulate)
// transform to grayscale by replacing color components with
// overall pixel luminance computed from weighted color sum
- if (gl_static.world.scale != 1) {
+ if (lm.scale != 1) {
y = LUMINANCE(r, g, b);
- r = y + (r - y) * gl_static.world.scale;
- g = y + (g - y) * gl_static.world.scale;
- b = y + (b - y) * gl_static.world.scale;
+ r = y + (r - y) * lm.scale;
+ g = y + (g - y) * lm.scale;
+ b = y + (b - y) * lm.scale;
}
out[0] = r;
@@ -84,7 +84,7 @@ adjust_color_ub(byte *out, const vec_t *in)
{
vec3_t tmp;
- adjust_color_f(tmp, in, gl_static.world.modulate);
+ adjust_color_f(tmp, in, lm.modulate);
out[0] = (byte)tmp[0];
out[1] = (byte)tmp[1];
out[2] = (byte)tmp[2];
@@ -263,7 +263,7 @@ static void update_dynamic_lightmap(mface_t *surf)
}
// upload lightmap subimage
- GL_BindTexture(surf->texnum[1]);
+ GL_ForceTexture(1, surf->texnum[1]);
qglTexSubImage2D(GL_TEXTURE_2D, 0,
surf->light_s, surf->light_t, smax, tmax,
GL_RGBA, GL_UNSIGNED_BYTE, temp);
@@ -271,23 +271,21 @@ static void update_dynamic_lightmap(mface_t *surf)
c.texUploads++;
}
-void GL_BeginLights(void)
-{
- qglActiveTextureARB(GL_TEXTURE1_ARB);
- gls.tmu = 1;
-}
-
-void GL_EndLights(void)
-{
- qglActiveTextureARB(GL_TEXTURE0_ARB);
- gls.tmu = 0;
-}
-
void GL_PushLights(mface_t *surf)
{
lightstyle_t *style;
int i;
+ if (!surf->lightmap) {
+ return;
+ }
+ if (surf->drawflags & SURF_NOLM_MASK) {
+ return;
+ }
+ if (!surf->texnum[1]) {
+ return;
+ }
+
#if USE_DLIGHTS
// dynamic this frame or dynamic previously
if (surf->dlightframe) {
@@ -334,16 +332,11 @@ static void LM_UploadBlock(void)
return;
}
- // bypassing our state tracker here, be careful to reset TMU1 afterwards!
- qglBindTexture(GL_TEXTURE_2D, TEXNUM_LIGHTMAP + lm.nummaps);
+ GL_ForceTexture(1, lm.texnums[lm.nummaps++]);
qglTexImage2D(GL_TEXTURE_2D, 0, lm.comp, LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (lm.highwater < ++lm.nummaps) {
- lm.highwater = lm.nummaps;
- }
}
static void build_style_map(int dynamic)
@@ -377,7 +370,10 @@ static void build_style_map(int dynamic)
static void LM_BeginBuilding(void)
{
- qglActiveTextureARB(GL_TEXTURE1_ARB);
+ // lightmap textures are not deleted from memory when changing maps,
+ // they are merely reused
+ lm.nummaps = 0;
+
LM_InitBlock();
// start up with fullbright styles
@@ -390,21 +386,14 @@ static void LM_EndBuilding(void)
LM_UploadBlock();
LM_InitBlock();
- qglActiveTextureARB(GL_TEXTURE0_ARB);
-
- // because LM_UploadBlock doesn't use our state tracker functions,
- // their idea of what is bound to TMU1 needs to be reset
- gls.texnum[1] = 0;
+ // vertex lighting implies fullbright styles
+ if (gl_fullbright->integer || gl_vertexlight->integer)
+ return;
// now build the real lightstyle map
build_style_map(gl_dynamic->integer);
-}
-static void LM_FreeLightmaps(void)
-{
- // lightmap textures are not deleted from memory when changing maps,
- // they are merely reused
- lm.nummaps = 0;
+ Com_DPrintf("%s: %d lightmaps built\n", __func__, lm.nummaps);
}
static void build_primary_lightmap(mface_t *surf)
@@ -438,48 +427,24 @@ static void build_primary_lightmap(mface_t *surf)
}
}
-static qboolean LM_BuildSurface(mface_t *surf, vec_t *vbo)
+static void LM_BuildSurface(mface_t *surf, vec_t *vbo)
{
- int smax, tmax, size, s, t, i;
- byte *src, *ptr;
- bsp_t *bsp;
+ int smax, tmax, s, t;
- // validate extents
- if (surf->extents[0] < 0 || surf->extents[0] > MAX_SURFACE_EXTENTS ||
- surf->extents[1] < 0 || surf->extents[1] > MAX_SURFACE_EXTENTS) {
- Com_EPrintf("%s: bad surface extents\n", __func__);
- return qfalse;
- }
-
- // validate blocklights size
smax = S_MAX(surf);
tmax = T_MAX(surf);
- size = smax * tmax;
- if (size > MAX_BLOCKLIGHTS) {
- Com_EPrintf("%s: MAX_BLOCKLIGHTS exceeded\n", __func__);
- return qfalse;
- }
-
- // validate lightmap bounds
- bsp = gl_static.world.cache;
- src = surf->lightmap + surf->numstyles * size * 3;
- ptr = bsp->lightmap + bsp->numlightmapbytes;
- if (src > ptr) {
- Com_EPrintf("%s: bad surface lightmap\n", __func__);
- return qfalse;
- }
if (!LM_AllocBlock(smax, tmax, &s, &t)) {
LM_UploadBlock();
if (lm.nummaps == LM_MAX_LIGHTMAPS) {
Com_EPrintf("%s: LM_MAX_LIGHTMAPS exceeded\n", __func__);
- return qfalse;
+ return;
}
LM_InitBlock();
if (!LM_AllocBlock(smax, tmax, &s, &t)) {
Com_EPrintf("%s: LM_AllocBlock(%d, %d) failed\n",
__func__, smax, tmax);
- return qfalse;
+ return;
}
}
@@ -488,49 +453,26 @@ static qboolean LM_BuildSurface(mface_t *surf, vec_t *vbo)
// store the surface lightmap parameters
surf->light_s = s;
surf->light_t = t;
- surf->texnum[1] = TEXNUM_LIGHTMAP + lm.nummaps;
+ surf->texnum[1] = lm.texnums[lm.nummaps];
// build the primary lightmap
build_primary_lightmap(surf);
-
- // normalize and store lmtc in vertices
- s = (s << 4) + 8;
- t = (t << 4) + 8;
-
- s -= surf->texturemins[0];
- t -= surf->texturemins[1];
-
- for (i = 0; i < surf->numsurfedges; i++) {
- vbo[5] += s;
- vbo[6] += t;
- vbo[5] /= LM_BLOCK_WIDTH * 16;
- vbo[6] /= LM_BLOCK_HEIGHT * 16;
- vbo += VERTEX_SIZE;
- }
-
- return qtrue;
}
-// called from the main loop whenever lightmap parameters change
-void LM_RebuildSurfaces(void)
+static void LM_RebuildSurfaces(void)
{
bsp_t *bsp = gl_static.world.cache;
mface_t *surf;
int i, texnum;
- if (!bsp) {
- return;
- }
-
build_style_map(gl_dynamic->integer);
if (!lm.nummaps) {
return;
}
- qglActiveTextureARB(GL_TEXTURE1_ARB);
- qglBindTexture(GL_TEXTURE_2D, TEXNUM_LIGHTMAP);
- texnum = TEXNUM_LIGHTMAP;
+ GL_ForceTexture(1, lm.texnums[0]);
+ texnum = lm.texnums[0];
for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
if (!surf->lightmap) {
@@ -548,7 +490,7 @@ void LM_RebuildSurfaces(void)
qglTexImage2D(GL_TEXTURE_2D, 0, lm.comp,
LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
- qglBindTexture(GL_TEXTURE_2D, surf->texnum[1]);
+ GL_ForceTexture(1, surf->texnum[1]);
texnum = surf->texnum[1];
c.texUploads++;
@@ -563,9 +505,6 @@ void LM_RebuildSurfaces(void)
GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
c.texUploads++;
-
- qglActiveTextureARB(GL_TEXTURE0_ARB);
- gls.texnum[1] = 0;
}
@@ -577,19 +516,55 @@ POLYGONS BUILDING
=============================================================================
*/
+static uint32_t color_for_surface(mface_t *surf)
+{
+ if (surf->drawflags & SURF_TRANS33)
+ return gl_static.inverse_intensity_33;
+
+ if (surf->drawflags & SURF_TRANS66)
+ return gl_static.inverse_intensity_66;
+
+ if (surf->drawflags & SURF_WARP)
+ return gl_static.inverse_intensity_100;
+
+ return U32_WHITE;
+}
+
static void build_surface_poly(mface_t *surf, vec_t *vbo)
{
msurfedge_t *src_surfedge;
mvertex_t *src_vert;
medge_t *src_edge;
mtexinfo_t *texinfo = surf->texinfo;
- int i;
vec2_t scale, tc, mins, maxs;
- int bmins[2], bmaxs[2];
+ int i, bmins[2], bmaxs[2];
+ uint32_t color;
surf->texnum[0] = texinfo->image->texnum;
surf->texnum[1] = 0;
+ color = color_for_surface(surf);
+
+ // convert surface flags to state bits
+ surf->statebits = GLS_DEFAULT;
+ if (!(surf->drawflags & SURF_COLOR_MASK)) {
+ surf->statebits |= GLS_TEXTURE_REPLACE;
+ }
+
+ if (surf->drawflags & SURF_WARP) {
+ surf->statebits |= GLS_WARP_ENABLE;
+ }
+
+ if (surf->drawflags & SURF_TRANS_MASK) {
+ surf->statebits |= GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE;
+ } else if (surf->drawflags & SURF_ALPHATEST) {
+ surf->statebits |= GLS_ALPHATEST_ENABLE;
+ }
+
+ if (surf->drawflags & SURF_FLOWING) {
+ surf->statebits |= GLS_FLOW_ENABLE;
+ }
+
// normalize texture coordinates
scale[0] = 1.0f / texinfo->image->width;
scale[1] = 1.0f / texinfo->image->height;
@@ -606,6 +581,9 @@ static void build_surface_poly(mface_t *surf, vec_t *vbo)
// vertex coordinates
VectorCopy(src_vert->point, vbo);
+ // vertex color
+ memcpy(vbo + 3, &color, sizeof(color));
+
// texture0 coordinates
tc[0] = DotProduct(vbo, texinfo->axis[0]) + texinfo->offset[0];
tc[1] = DotProduct(vbo, texinfo->axis[1]) + texinfo->offset[1];
@@ -616,12 +594,12 @@ static void build_surface_poly(mface_t *surf, vec_t *vbo)
if (mins[1] > tc[1]) mins[1] = tc[1];
if (maxs[1] < tc[1]) maxs[1] = tc[1];
- vbo[3] = tc[0] * scale[0];
- vbo[4] = tc[1] * scale[1];
+ vbo[4] = tc[0] * scale[0];
+ vbo[5] = tc[1] * scale[1];
// texture1 coordinates
- vbo[5] = tc[0];
- vbo[6] = tc[1];
+ vbo[6] = tc[0];
+ vbo[7] = tc[1];
vbo += VERTEX_SIZE;
}
@@ -639,37 +617,109 @@ static void build_surface_poly(mface_t *surf, vec_t *vbo)
surf->extents[1] = (bmaxs[1] - bmins[1]) << 4;
}
-// duplicates normalized texture0 coordinates for non-lit surfaces in texture1
-// to make them render properly when gl_lightmap hack is used
-static void duplicate_surface_lmtc(mface_t *surf, vec_t *vbo)
+// vertex lighting approximation
+static void sample_surface_verts(mface_t *surf, vec_t *vbo)
{
- int i;
+ int i;
+ vec3_t color;
+
+ glr.lightpoint.surf = surf;
for (i = 0; i < surf->numsurfedges; i++) {
- vbo[5] = vbo[3];
- vbo[6] = vbo[4];
+ glr.lightpoint.s = (int)vbo[6] - surf->texturemins[0];
+ glr.lightpoint.t = (int)vbo[7] - surf->texturemins[1];
+
+ GL_SampleLightPoint(color);
+ adjust_color_ub((byte *)(vbo + 3), color);
vbo += VERTEX_SIZE;
}
+
+ surf->statebits &= ~GLS_TEXTURE_REPLACE;
+ surf->statebits |= GLS_SHADE_SMOOTH;
}
-void GL_FreeWorld(void)
+// validates and processes surface lightmap
+static void build_surface_light(mface_t *surf, vec_t *vbo)
{
- if (!gl_static.world.cache) {
+ int smax, tmax, size;
+ byte *src, *ptr;
+ bsp_t *bsp;
+
+ if (gl_fullbright->integer)
+ return;
+
+ if (!surf->lightmap)
+ return;
+
+ if (surf->drawflags & SURF_NOLM_MASK)
+ return;
+
+ // validate extents
+ if (surf->extents[0] < 0 || surf->extents[0] > MAX_SURFACE_EXTENTS ||
+ surf->extents[1] < 0 || surf->extents[1] > MAX_SURFACE_EXTENTS) {
+ Com_EPrintf("%s: bad surface extents\n", __func__);
+ surf->lightmap = NULL; // don't use this lightmap
return;
}
- BSP_Free(gl_static.world.cache);
+ // validate blocklights size
+ smax = S_MAX(surf);
+ tmax = T_MAX(surf);
+ size = smax * tmax;
+ if (size > MAX_BLOCKLIGHTS) {
+ Com_EPrintf("%s: MAX_BLOCKLIGHTS exceeded\n", __func__);
+ surf->lightmap = NULL; // don't use this lightmap
+ return;
+ }
- if (gl_static.world.vertices) {
- Hunk_Free(&gl_static.world.hunk);
- } else if (qglDeleteBuffersARB) {
- qglDeleteBuffersARB(1, &gl_static.world.bufnum);
+ // validate lightmap bounds
+ bsp = gl_static.world.cache;
+ src = surf->lightmap + surf->numstyles * size * 3;
+ ptr = bsp->lightmap + bsp->numlightmapbytes;
+ if (src > ptr) {
+ Com_EPrintf("%s: bad surface lightmap\n", __func__);
+ surf->lightmap = NULL; // don't use this lightmap
+ return;
}
- LM_FreeLightmaps();
+ if (gl_vertexlight->integer)
+ sample_surface_verts(surf, vbo);
+ else
+ LM_BuildSurface(surf, vbo);
+}
- memset(&gl_static.world, 0, sizeof(gl_static.world));
+// normalizes and stores lightmap texture coordinates in vertices
+static void normalize_surface_lmtc(mface_t *surf, vec_t *vbo)
+{
+ float s, t;
+ int i;
+
+ s = ((surf->light_s << 4) + 8) - surf->texturemins[0];
+ t = ((surf->light_t << 4) + 8) - surf->texturemins[1];
+
+ for (i = 0; i < surf->numsurfedges; i++) {
+ vbo[6] += s;
+ vbo[7] += t;
+ vbo[6] *= 1.0f / (LM_BLOCK_WIDTH * 16);
+ vbo[7] *= 1.0f / (LM_BLOCK_HEIGHT * 16);
+
+ vbo += VERTEX_SIZE;
+ }
+}
+
+// duplicates normalized texture0 coordinates for non-lit surfaces in texture1
+// to make them render properly when gl_lightmap hack is used
+static void duplicate_surface_lmtc(mface_t *surf, vec_t *vbo)
+{
+ int i;
+
+ for (i = 0; i < surf->numsurfedges; i++) {
+ vbo[6] = vbo[4];
+ vbo[7] = vbo[5];
+
+ vbo += VERTEX_SIZE;
+ }
}
static qboolean create_surface_vbo(size_t size)
@@ -704,40 +754,137 @@ static void upload_surface_vbo(int lastvert)
GLintptrARB offset = lastvert * VERTEX_SIZE * sizeof(vec_t);
GLsizeiptrARB size = tess.numverts * VERTEX_SIZE * sizeof(vec_t);
- Com_DDPrintf("%s: %"PRIz" bytes\n", __func__, size);
+ Com_DDPrintf("%s: %"PRIz" bytes at %"PRIz"\n", __func__, size, offset);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, size, tess.vertices);
tess.numverts = 0;
}
-// silence GCC warning
-extern void gl_lightmap_changed(cvar_t *self);
+static void upload_world_surfaces(void)
+{
+ bsp_t *bsp = gl_static.world.cache;
+ vec_t *vbo;
+ mface_t *surf;
+ int i, currvert, lastvert;
+
+ // force vertex lighting if multitexture is not supported
+ if (!qglActiveTextureARB || !qglClientActiveTextureARB)
+ Cvar_Set("gl_vertexlight", "1");
+
+ if (!gl_static.world.vertices)
+ qglBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_static.world.bufnum);
+
+ currvert = 0;
+ lastvert = 0;
+ for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
+ if (surf->drawflags & SURF_SKY)
+ continue;
+
+ if (gl_static.world.vertices) {
+ vbo = gl_static.world.vertices + currvert * VERTEX_SIZE;
+ } else {
+ // upload VBO chunk if needed
+ if (tess.numverts + surf->numsurfedges > TESS_MAX_VERTICES) {
+ upload_surface_vbo(lastvert);
+ lastvert = currvert;
+ }
+
+ vbo = tess.vertices + tess.numverts * VERTEX_SIZE;
+ tess.numverts += surf->numsurfedges;
+ }
+
+ surf->firstvert = currvert;
+ build_surface_poly(surf, vbo);
+ build_surface_light(surf, vbo);
-void gl_lightmap_changed(cvar_t *self)
+ if (surf->texnum[1])
+ normalize_surface_lmtc(surf, vbo);
+ else
+ duplicate_surface_lmtc(surf, vbo);
+
+ currvert += surf->numsurfedges;
+ }
+
+ // upload the last VBO chunk
+ if (!gl_static.world.vertices) {
+ upload_surface_vbo(lastvert);
+ qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+ gl_fullbright->modified = qfalse;
+ gl_vertexlight->modified = qfalse;
+}
+
+static void set_world_size(void)
+{
+ mnode_t *node = gl_static.world.cache->nodes;
+ vec_t size, temp;
+ int i;
+
+ for (i = 0, size = 0; i < 3; i++) {
+ temp = node->maxs[i] - node->mins[i];
+ if (temp > size)
+ size = temp;
+ }
+
+ if (size > 4096)
+ gl_static.world.size = 8192;
+ else if (size > 2048)
+ gl_static.world.size = 4096;
+ else
+ gl_static.world.size = 2048;
+}
+
+// called from the main loop whenever lighting parameters change
+void GL_RebuildLighting(void)
{
- gl_static.world.scale = Cvar_ClampValue(gl_coloredlightmaps, 0, 1);
- lm.comp = gl_static.world.scale ? GL_RGB : GL_LUMINANCE;
+ if (!gl_static.world.cache)
+ return;
- // FIXME: the name 'brightness' is misleading in this context
- gl_static.world.add = 255 * Cvar_ClampValue(gl_brightness, -1, 1);
+ // if doing vertex lighting, rebuild all surfaces
+ if (gl_fullbright->integer || gl_vertexlight->integer) {
+ upload_world_surfaces();
+ return;
+ }
- gl_static.world.modulate = gl_modulate->value * gl_modulate_world->value;
+ // if did vertex lighting previously, rebuild all surfaces and lightmaps
+ if (gl_fullbright->modified || gl_vertexlight->modified) {
+ LM_BeginBuilding();
+ upload_world_surfaces();
+ LM_EndBuilding();
+ return;
+ }
- // rebuild all lightmaps next frame
- lm.dirty = qtrue;
+ // rebuild all lightmaps
+ LM_RebuildSurfaces();
+}
+
+void GL_FreeWorld(void)
+{
+ if (!gl_static.world.cache) {
+ return;
+ }
+
+ BSP_Free(gl_static.world.cache);
+
+ if (gl_static.world.vertices) {
+ Hunk_Free(&gl_static.world.hunk);
+ } else if (qglDeleteBuffersARB) {
+ qglDeleteBuffersARB(1, &gl_static.world.bufnum);
+ }
+
+ memset(&gl_static.world, 0, sizeof(gl_static.world));
}
void GL_LoadWorld(const char *name)
{
char buffer[MAX_QPATH];
- mface_t *surf;
- int i, count, lastvert;
size_t size;
- vec_t s, t;
- vec_t *vbo;
bsp_t *bsp;
mtexinfo_t *info;
+ mface_t *surf;
qerror_t ret;
+ int i;
ret = BSP_Load(name, &bsp);
if (!bsp) {
@@ -764,25 +911,10 @@ void GL_LoadWorld(const char *name)
// free previous model, if any
GL_FreeWorld();
- gl_lightmap_changed(NULL);
-
gl_static.world.cache = bsp;
// calculate world size for far clip plane and sky box
- for (i = 0, s = 0; i < 3; i++) {
- t = bsp->nodes[0].maxs[i] - bsp->nodes[0].mins[i];
- if (t > s)
- s = t;
- }
-
- if (s > 4096)
- gl_static.world.size = 8192;
- else if (s > 2048)
- gl_static.world.size = 4096;
- else
- gl_static.world.size = 2048;
-
- Com_DPrintf("%s: world size %.f (%.f)\n", __func__, gl_static.world.size, s);
+ set_world_size();
// register all texinfo
for (i = 0, info = bsp->texinfo; i < bsp->numtexinfo; i++, info++) {
@@ -794,82 +926,38 @@ void GL_LoadWorld(const char *name)
}
// calculate vertex buffer size in bytes
- count = 0;
+ size = 0;
for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
- if (!(surf->texinfo->c.flags & SURF_SKY)) {
- count += surf->numsurfedges;
- }
+ // hack surface flags into drawflags for faster access
+ surf->drawflags |= surf->texinfo->c.flags & ~DSURF_PLANEBACK;
+
+ // don't count sky surfaces
+ if (surf->drawflags & SURF_SKY)
+ continue;
+
+ size += surf->numsurfedges * VERTEX_SIZE * sizeof(vec_t);
}
- size = count * VERTEX_SIZE * sizeof(vec_t);
// try VBO first, then allocate on hunk
if (create_surface_vbo(size)) {
Com_DPrintf("%s: %"PRIz" bytes of vertex data as VBO\n", __func__, size);
} else {
Hunk_Begin(&gl_static.world.hunk, size);
- vbo = Hunk_Alloc(&gl_static.world.hunk, size);
+ gl_static.world.vertices = Hunk_Alloc(&gl_static.world.hunk, size);
Hunk_End(&gl_static.world.hunk);
Com_DPrintf("%s: %"PRIz" bytes of vertex data on hunk\n", __func__, size);
- gl_static.world.vertices = vbo;
}
// begin building lightmaps
LM_BeginBuilding();
// post process all surfaces
- count = 0;
- lastvert = 0;
- for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
- // hack surface flags into drawflags for faster access
- surf->drawflags |= surf->texinfo->c.flags & ~DSURF_PLANEBACK;
-
- if (surf->drawflags & SURF_SKY) {
- continue;
- }
-
- if (gl_static.world.vertices) {
- vbo = gl_static.world.vertices + count * VERTEX_SIZE;
- } else {
- if (surf->numsurfedges > TESS_MAX_VERTICES) {
- Com_EPrintf("%s: too many verts\n", __func__);
- continue;
- }
-
- // upload VBO chunk if needed
- if (tess.numverts + surf->numsurfedges > TESS_MAX_VERTICES) {
- upload_surface_vbo(lastvert);
- lastvert = count;
- }
-
- vbo = tess.vertices + tess.numverts * VERTEX_SIZE;
- tess.numverts += surf->numsurfedges;
- }
-
- surf->firstvert = count;
- build_surface_poly(surf, vbo);
-
- if (gl_fullbright->integer || (surf->drawflags & SURF_NOLM_MASK)) {
- surf->lightmap = NULL;
- } else if (surf->lightmap && !LM_BuildSurface(surf, vbo)) {
- surf->lightmap = NULL;
- }
-
- if (!surf->lightmap) {
- duplicate_surface_lmtc(surf, vbo);
- }
-
- count += surf->numsurfedges;
- }
-
- // upload the last VBO chunk
- if (!gl_static.world.vertices) {
- upload_surface_vbo(lastvert);
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
+ upload_world_surfaces();
// end building lightmaps
LM_EndBuilding();
- Com_DPrintf("%s: %d lightmaps built\n", __func__, lm.nummaps);
+
+ GL_ShowErrors(__func__);
}
diff --git a/src/refresh/gl/tess.c b/src/refresh/gl/tess.c
index 3a671a3..0571ef4 100644
--- a/src/refresh/gl/tess.c
+++ b/src/refresh/gl/tess.c
@@ -21,15 +21,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
tesselator_t tess;
#define FACE_HASH_BITS 5
-#define FACE_HASH_SIZE (1<<FACE_HASH_BITS)
-#define FACE_HASH_MASK (FACE_HASH_SIZE-1)
+#define FACE_HASH_SIZE (1 << FACE_HASH_BITS)
+#define FACE_HASH_MASK (FACE_HASH_SIZE - 1)
-// assumes a < 1024 (texture), b > 1024 (lightmap)
-#define FACE_HASH(a,b) \
- (((a)^((a)>>FACE_HASH_BITS)^((b)>>FACE_HASH_BITS*2))&FACE_HASH_MASK)
-
-static mface_t *faces_alpha, *faces_warp, *faces_alpha_warp;
-static mface_t *faces_hash[FACE_HASH_SIZE];
+static mface_t *faces_head[FACE_HASH_SIZE];
+static mface_t **faces_next[FACE_HASH_SIZE];
+static mface_t *faces_alpha;
void GL_Flush2D(void)
{
@@ -39,40 +36,32 @@ void GL_Flush2D(void)
return;
}
- bits = GLS_DEPTHTEST_DISABLE;
+ bits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_FALSE | GLS_CULL_DISABLE;
if (tess.flags & 2) {
bits |= GLS_BLEND_BLEND;
} else if (tess.flags & 1) {
bits |= GLS_ALPHATEST_ENABLE;
}
- GL_BindTexture(tess.texnum[0]);
- GL_TexEnv(GL_MODULATE);
- GL_Bits(bits);
-
- qglEnableClientState(GL_COLOR_ARRAY);
+ GL_BindTexture(0, tess.texnum[0]);
+ GL_StateBits(bits);
+ GL_ArrayBits(GLA_VERTEX | GLA_TC | GLA_COLOR);
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.colors);
- qglTexCoordPointer(2, GL_FLOAT, 16, tess.vertices + 2);
- qglVertexPointer(2, GL_FLOAT, 16, tess.vertices);
+ GL_VertexPointer(2, 4, tess.vertices);
+ GL_TexCoordPointer(2, 4, tess.vertices + 2);
+ GL_ColorBytePointer(4, 0, tess.colors);
- if (qglLockArraysEXT) {
- qglLockArraysEXT(0, tess.numverts);
- }
+ GL_LockArrays(tess.numverts);
- qglDrawElements(GL_TRIANGLES, tess.numindices, GL_UNSIGNED_INT, tess.indices);
+ qglDrawElements(GL_TRIANGLES, tess.numindices, QGL_INDEX_ENUM, tess.indices);
- if (gl_showtris->integer) {
+ if (gl_showtris->integer > 1) {
GL_EnableOutlines();
- qglDrawElements(GL_TRIANGLES, tess.numindices, GL_UNSIGNED_INT, tess.indices);
+ qglDrawElements(GL_TRIANGLES, tess.numindices, QGL_INDEX_ENUM, tess.indices);
GL_DisableOutlines();
}
- if (qglUnlockArraysEXT) {
- qglUnlockArraysEXT();
- }
-
- qglDisableClientState(GL_COLOR_ARRAY);
+ GL_UnlockArrays();
c.batchesDrawn2D++;
@@ -82,10 +71,13 @@ void GL_Flush2D(void)
tess.flags = 0;
}
+#define PARTICLE_SIZE (1 + M_SQRT1_2)
+#define PARTICLE_SCALE (1 / (2 * PARTICLE_SIZE))
+
void GL_DrawParticles(void)
{
particle_t *p;
- int i;
+ int total, count;
vec3_t transformed;
vec_t scale, dist;
color_t color;
@@ -94,82 +86,76 @@ void GL_DrawParticles(void)
uint32_t *dst_color;
int blend;
- if (!glr.fd.num_particles) {
+ if (!glr.fd.num_particles)
return;
- }
if (gl_partstyle->integer)
blend = GLS_BLEND_ADD;
else
blend = GLS_BLEND_BLEND;
- GL_BindTexture(TEXNUM_PARTICLE);
- GL_TexEnv(GL_MODULATE);
- GL_Bits(blend | GLS_DEPTHMASK_FALSE);
+ GL_LoadMatrix(glr.viewmatrix);
- qglEnableClientState(GL_COLOR_ARRAY);
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.colors);
- qglTexCoordPointer(2, GL_FLOAT, 20, tess.vertices + 3);
- qglVertexPointer(3, GL_FLOAT, 20, tess.vertices);
+ GL_VertexPointer(3, 5, tess.vertices);
+ GL_TexCoordPointer(2, 5, tess.vertices + 3);
+ GL_ColorBytePointer(4, 0, tess.colors);
-#define PARTICLE_SIZE (1+M_SQRT1_2)
-#define PARTICLE_SCALE (1/(2*PARTICLE_SIZE))
+ p = glr.fd.particles;
+ total = glr.fd.num_particles;
+ do {
+ GL_BindTexture(0, TEXNUM_PARTICLE);
+ GL_StateBits(blend | GLS_DEPTHMASK_FALSE);
+ GL_ArrayBits(GLA_VERTEX | GLA_TC | GLA_COLOR);
- numverts = 0;
- for (i = 0, p = glr.fd.particles; i < glr.fd.num_particles; i++, p++) {
- VectorSubtract(p->origin, glr.fd.vieworg, transformed);
- dist = DotProduct(transformed, glr.viewaxis[0]);
+ count = total;
+ if (count > TESS_MAX_VERTICES / 3)
+ count = TESS_MAX_VERTICES / 3;
- scale = gl_partscale->value;
- if (dist > 20) {
- scale += dist * 0.01f;
- }
+ total -= count;
- if (p->color == -1) {
- color.u32 = p->rgba.u32;
- } else {
- color.u32 = d_8to24table[p->color & 0xff];
- color.u8[3] = 255 * p->alpha;
- }
+ numverts = 0;
+ do {
+ VectorSubtract(p->origin, glr.fd.vieworg, transformed);
+ dist = DotProduct(transformed, glr.viewaxis[0]);
- if (numverts + 3 > TESS_MAX_VERTICES) {
- qglDrawArrays(GL_TRIANGLES, 0, numverts);
- if (gl_showtris->integer) {
- qglDisableClientState(GL_COLOR_ARRAY);
- GL_EnableOutlines();
- qglDrawArrays(GL_TRIANGLES, 0, numverts);
- GL_DisableOutlines();
- qglEnableClientState(GL_COLOR_ARRAY);
- }
- numverts = 0;
- }
+ scale = gl_partscale->value;
+ if (dist > 20)
+ scale += dist * 0.01f;
- dst_vert = tess.vertices + numverts * 5;
- VectorMA(p->origin, scale * PARTICLE_SCALE, glr.viewaxis[1], dst_vert);
- VectorMA(dst_vert, -scale * PARTICLE_SCALE, glr.viewaxis[2], dst_vert);
- VectorMA(dst_vert, scale, glr.viewaxis[2], dst_vert + 5);
- VectorMA(dst_vert, -scale, glr.viewaxis[1], dst_vert + 10);
+ if (p->color == -1) {
+ color.u32 = p->rgba.u32;
+ } else {
+ color.u32 = d_8to24table[p->color & 0xff];
+ color.u8[3] = 255 * p->alpha;
+ }
- dst_vert[ 3] = 0; dst_vert[ 4] = 0;
- dst_vert[ 8] = 0; dst_vert[ 9] = PARTICLE_SIZE;
- dst_vert[13] = PARTICLE_SIZE; dst_vert[14] = 0;
+ dst_vert = tess.vertices + numverts * 5;
+ VectorMA(p->origin, scale * PARTICLE_SCALE, glr.viewaxis[1], dst_vert);
+ VectorMA(dst_vert, -scale * PARTICLE_SCALE, glr.viewaxis[2], dst_vert);
+ VectorMA(dst_vert, scale, glr.viewaxis[2], dst_vert + 5);
+ VectorMA(dst_vert, -scale, glr.viewaxis[1], dst_vert + 10);
- dst_color = (uint32_t *)tess.colors + numverts;
- dst_color[0] = color.u32;
- dst_color[1] = color.u32;
- dst_color[2] = color.u32;
+ dst_vert[ 3] = 0; dst_vert[ 4] = 0;
+ dst_vert[ 8] = 0; dst_vert[ 9] = PARTICLE_SIZE;
+ dst_vert[13] = PARTICLE_SIZE; dst_vert[14] = 0;
- numverts += 3;
- }
+ dst_color = (uint32_t *)tess.colors + numverts;
+ dst_color[0] = color.u32;
+ dst_color[1] = color.u32;
+ dst_color[2] = color.u32;
- qglDrawArrays(GL_TRIANGLES, 0, numverts);
- qglDisableClientState(GL_COLOR_ARRAY);
+ p++;
+ numverts += 3;
+ } while (--count);
- if (gl_showtris->integer) {
- GL_EnableOutlines();
qglDrawArrays(GL_TRIANGLES, 0, numverts);
- GL_DisableOutlines();
- }
+
+ if (gl_showtris->integer) {
+ GL_EnableOutlines();
+ qglDrawArrays(GL_TRIANGLES, 0, numverts);
+ GL_DisableOutlines();
+ }
+ } while (total);
}
/* all things serve the Beam */
@@ -180,7 +166,7 @@ void GL_DrawBeams(void)
color_t color;
vec_t *dst_vert;
uint32_t *dst_color;
- int *dst_indices;
+ QGL_INDEX_TYPE *dst_indices;
vec_t length;
int numverts;
int numindices;
@@ -191,14 +177,14 @@ void GL_DrawBeams(void)
return;
}
- GL_BindTexture(TEXNUM_BEAM);
- GL_TexEnv(GL_MODULATE);
- GL_Bits(GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE);
+ GL_LoadMatrix(glr.viewmatrix);
+ GL_BindTexture(0, TEXNUM_BEAM);
+ GL_StateBits(GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE);
+ GL_ArrayBits(GLA_VERTEX | GLA_TC | GLA_COLOR);
- qglEnableClientState(GL_COLOR_ARRAY);
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.colors);
- qglTexCoordPointer(2, GL_FLOAT, 20, tess.vertices + 3);
- qglVertexPointer(3, GL_FLOAT, 20, tess.vertices);
+ GL_VertexPointer(3, 5, tess.vertices);
+ GL_TexCoordPointer(2, 5, tess.vertices + 3);
+ GL_ColorBytePointer(4, 0, tess.colors);
numverts = numindices = 0;
for (i = 0, ent = glr.fd.entities; i < glr.fd.num_entities; i++, ent++) {
@@ -227,7 +213,7 @@ void GL_DrawBeams(void)
if (numverts + 4 > TESS_MAX_VERTICES ||
numindices + 6 > TESS_MAX_INDICES) {
qglDrawElements(GL_TRIANGLES, numindices,
- GL_UNSIGNED_INT, tess.indices);
+ QGL_INDEX_ENUM, tess.indices);
numverts = numindices = 0;
}
@@ -261,11 +247,10 @@ void GL_DrawBeams(void)
}
qglDrawElements(GL_TRIANGLES, numindices,
- GL_UNSIGNED_INT, tess.indices);
- qglDisableClientState(GL_COLOR_ARRAY);
+ QGL_INDEX_ENUM, tess.indices);
}
-static void GL_BindArrays(void)
+void GL_BindArrays(void)
{
vec_t *ptr;
@@ -276,97 +261,64 @@ static void GL_BindArrays(void)
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_static.world.bufnum);
}
- qglVertexPointer(3, GL_FLOAT, 4 * VERTEX_SIZE, ptr + 0);
- qglTexCoordPointer(2, GL_FLOAT, 4 * VERTEX_SIZE,
- gl_lightmap->integer ? ptr + 5 : ptr + 3);
+ GL_VertexPointer(3, VERTEX_SIZE, ptr + 0);
- qglClientActiveTextureARB(GL_TEXTURE1_ARB);
- qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglTexCoordPointer(2, GL_FLOAT, 4 * VERTEX_SIZE, ptr + 5);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB);
-}
+ if (gl_lightmap->integer) {
+ GL_TexCoordPointer(2, VERTEX_SIZE, ptr + 6);
+ } else {
+ GL_TexCoordPointer(2, VERTEX_SIZE, ptr + 4);
+ if (lm.nummaps) {
+ GL_LightCoordPointer(2, VERTEX_SIZE, ptr + 6);
+ }
+ }
+
+ GL_ColorBytePointer(4, VERTEX_SIZE, (GLubyte *)(ptr + 3));
-static void GL_UnbindArrays(void)
-{
if (!gl_static.world.vertices) {
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
- qglClientActiveTextureARB(GL_TEXTURE1_ARB);
- qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
- qglClientActiveTextureARB(GL_TEXTURE0_ARB);
}
-static void GL_Flush3D(void)
+void GL_Flush3D(void)
{
+ glStateBits_t state = tess.flags;
+ glArrayBits_t array = GLA_VERTEX | GLA_TC;
+
if (!tess.numindices) {
return;
}
- if (tess.flags & (SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) {
- float f = gl_static.inverse_intensity;
-
- if (tess.flags & SURF_TRANS33) {
- qglColor4f(f, f, f, 0.33f);
- } else if (tess.flags & SURF_TRANS66) {
- qglColor4f(f, f, f, 0.66f);
- } else {
- qglColor4f(f, f, f, 1.0f);
- }
-
- GL_TexEnv(GL_MODULATE);
- } else {
- GL_TexEnv(GL_REPLACE);
+ if (q_likely(tess.texnum[1])) {
+ state |= GLS_LIGHTMAP_ENABLE;
+ array |= GLA_LMTC;
}
- GL_BindTexture(tess.texnum[0]);
-
- if (tess.flags & SURF_FLOWING) {
- float scaled, scroll;
-
- if (tess.flags & SURF_WARP) {
- scaled = glr.fd.time * 0.5f;
- scroll = -scaled;
- } else {
- scaled = glr.fd.time / 40;
- scroll = -64 * (scaled - (int)scaled);
- }
-
- qglMatrixMode(GL_TEXTURE);
- qglPushMatrix();
- qglTranslatef(scroll, 0, 0);
+ if (!(state & GLS_TEXTURE_REPLACE)) {
+ array |= GLA_COLOR;
}
- if (tess.texnum[1]) {
- GL_SelectTMU(1);
- qglEnable(GL_TEXTURE_2D);
- GL_TexEnv(GL_MODULATE);
- GL_BindTexture(tess.texnum[1]);
- }
+ GL_StateBits(state);
+ GL_ArrayBits(array);
- if (gl_static.world.vertices && qglLockArraysEXT) {
- qglLockArraysEXT(0, tess.numverts);
+ GL_BindTexture(0, tess.texnum[0]);
+ if (q_likely(tess.texnum[1])) {
+ GL_BindTexture(1, tess.texnum[1]);
}
- qglDrawElements(GL_TRIANGLES, tess.numindices, GL_UNSIGNED_INT, tess.indices);
-
- if (tess.texnum[1]) {
- qglDisable(GL_TEXTURE_2D);
- GL_SelectTMU(0);
+ if (gl_static.world.vertices) {
+ GL_LockArrays(tess.numverts);
}
+ qglDrawElements(GL_TRIANGLES, tess.numindices, QGL_INDEX_ENUM, tess.indices);
+
if (gl_showtris->integer) {
GL_EnableOutlines();
- qglDrawElements(GL_TRIANGLES, tess.numindices, GL_UNSIGNED_INT, tess.indices);
+ qglDrawElements(GL_TRIANGLES, tess.numindices, QGL_INDEX_ENUM, tess.indices);
GL_DisableOutlines();
}
- if (gl_static.world.vertices && qglUnlockArraysEXT) {
- qglUnlockArraysEXT();
- }
-
- if (tess.flags & SURF_FLOWING) {
- qglPopMatrix();
- qglMatrixMode(GL_MODELVIEW);
+ if (gl_static.world.vertices) {
+ GL_UnlockArrays();
}
c.batchesDrawn++;
@@ -399,31 +351,26 @@ static int GL_TextureAnimation(mtexinfo_t *tex)
{
int c;
- if (!tex->next)
- return tex->image->texnum;
-
- c = glr.ent->frame % tex->numframes;
- while (c) {
- tex = tex->next;
- c--;
+ if (q_unlikely(tex->next)) {
+ c = glr.ent->frame % tex->numframes;
+ while (c) {
+ tex = tex->next;
+ c--;
+ }
}
return tex->image->texnum;
}
-#define SURF_FLUSH_MASK \
- (SURF_TRANS33|SURF_TRANS66|SURF_WARP|SURF_FLOWING)
-
-static void GL_DrawFace(mface_t *surf)
+void GL_DrawFace(mface_t *surf)
{
int numtris = surf->numsurfedges - 2;
int numindices = numtris * 3;
- int diff = surf->drawflags ^ tess.flags;
- int texnum[2];
- int *dst_indices;
+ GLuint texnum[2];
+ QGL_INDEX_TYPE *dst_indices;
int i, j;
- if (gl_lightmap->integer) {
+ if (q_unlikely(gl_lightmap->integer)) {
texnum[0] = surf->texnum[1];
if (!texnum[0])
texnum[0] = GL_TextureAnimation(surf->texinfo);
@@ -435,16 +382,16 @@ static void GL_DrawFace(mface_t *surf)
if (tess.texnum[0] != texnum[0] ||
tess.texnum[1] != texnum[1] ||
- (diff & SURF_FLUSH_MASK) ||
+ tess.flags != surf->statebits ||
tess.numindices + numindices > TESS_MAX_INDICES) {
GL_Flush3D();
}
tess.texnum[0] = texnum[0];
tess.texnum[1] = texnum[1];
- tess.flags = surf->drawflags;
+ tess.flags = surf->statebits;
- if (gl_static.world.vertices) {
+ if (q_unlikely(gl_static.world.vertices)) {
j = GL_CopyVerts(surf);
} else {
j = surf->firstvert;
@@ -460,6 +407,8 @@ static void GL_DrawFace(mface_t *surf)
tess.numindices += numindices;
c.trisDrawn += numtris;
+ c.facesTris += numtris;
+ c.facesDrawn++;
}
static inline void GL_DrawChain(mface_t **head)
@@ -469,96 +418,63 @@ static inline void GL_DrawChain(mface_t **head)
for (face = *head; face; face = face->next) {
GL_DrawFace(face);
}
+
*head = NULL;
}
-void GL_DrawSolidFaces(void)
+void GL_ClearSolidFaces(void)
{
int i;
- GL_BindArrays();
-
- GL_Bits(GLS_DEFAULT);
-
- if (faces_warp) {
- GL_EnableWarp();
- GL_DrawChain(&faces_warp);
- GL_Flush3D();
- GL_DisableWarp();
+ for (i = 0; i < FACE_HASH_SIZE; i++) {
+ faces_next[i] = &faces_head[i];
}
+}
- if (gl_hash_faces->integer) {
- for (i = 0; i < FACE_HASH_SIZE; i++) {
- GL_DrawChain(&faces_hash[i]);
- }
- } else {
- GL_DrawChain(&faces_hash[0]);
- faces_hash[1] = NULL;
- }
+void GL_DrawSolidFaces(void)
+{
+ int i;
- GL_Flush3D();
- GL_UnbindArrays();
+ for (i = 0; i < FACE_HASH_SIZE; i++) {
+ GL_DrawChain(&faces_head[i]);
+ }
}
void GL_DrawAlphaFaces(void)
{
- glr.ent = &gl_world;
+ if (!faces_alpha) {
+ return;
+ }
- GL_BindArrays();
+ glr.ent = &gl_world;
- GL_Bits(GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE);
+ GL_LoadMatrix(glr.viewmatrix);
- if (faces_alpha_warp) {
- GL_EnableWarp();
- GL_DrawChain(&faces_alpha_warp);
- GL_Flush3D();
- GL_DisableWarp();
- }
+ GL_BindArrays();
GL_DrawChain(&faces_alpha);
GL_Flush3D();
- GL_UnbindArrays();
}
void GL_AddSolidFace(mface_t *face)
{
- if ((face->drawflags & SURF_WARP) && gl_static.prognum_warp) {
- face->next = faces_warp;
- faces_warp = face;
- } else {
- if (gl_hash_faces->integer && !gl_lightmap->integer) {
- unsigned i = FACE_HASH(face->texnum[0], face->texnum[1]);
- face->next = faces_hash[i];
- faces_hash[i] = face;
- } else {
- // preserve front-to-back ordering
- face->next = NULL;
- if (faces_hash[1])
- faces_hash[1]->next = face;
- else
- faces_hash[0] = face;
- faces_hash[1] = face;
- }
+ unsigned hash;
- if (face->lightmap && !(face->drawflags & SURF_NOLM_MASK) && gl_dynamic->integer) {
- GL_PushLights(face);
- }
- }
+ hash = face->texnum[0] ^ face->texnum[1] ^ face->statebits;
+ hash ^= hash >> FACE_HASH_BITS;
+ hash &= FACE_HASH_MASK;
- c.facesDrawn++;
+ // preserve front-to-back ordering
+ face->next = NULL;
+ *faces_next[hash] = face;
+ faces_next[hash] = &face->next;
}
void GL_AddAlphaFace(mface_t *face)
{
- if ((face->drawflags & SURF_WARP) && gl_static.prognum_warp) {
- face->next = faces_alpha_warp;
- faces_alpha_warp = face;
- } else {
- face->next = faces_alpha;
- faces_alpha = face;
- }
-
- c.facesDrawn++;
+ // draw back-to-front
+ face->next = faces_alpha;
+ faces_alpha = face;
}
diff --git a/src/refresh/gl/world.c b/src/refresh/gl/world.c
index 8c0a1b4..e7d3091 100644
--- a/src/refresh/gl/world.c
+++ b/src/refresh/gl/world.c
@@ -18,11 +18,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gl.h"
-static qboolean GL_SmoothLightPoint(vec3_t start, vec3_t color)
+void GL_SampleLightPoint(vec3_t color)
{
- bsp_t *bsp;
mface_t *surf;
- int s, t, i, index;
+ int s, t, i;
byte *lightmap;
byte *b1, *b2, *b3, *b4;
int fracu, fracv;
@@ -30,6 +29,53 @@ static qboolean GL_SmoothLightPoint(vec3_t start, vec3_t color)
byte temp[3];
int smax, tmax, size;
lightstyle_t *style;
+
+ fracu = glr.lightpoint.s & 15;
+ fracv = glr.lightpoint.t & 15;
+
+ // compute weights of lightmap blocks
+ w1 = (16 - fracu) * (16 - fracv);
+ w2 = fracu * (16 - fracv);
+ w3 = fracu * fracv;
+ w4 = (16 - fracu) * fracv;
+
+ s = glr.lightpoint.s >> 4;
+ t = glr.lightpoint.t >> 4;
+
+ surf = glr.lightpoint.surf;
+
+ smax = S_MAX(surf);
+ tmax = T_MAX(surf);
+ size = smax * tmax * 3;
+
+ VectorClear(color);
+
+ // add all the lightmaps with bilinear filtering
+ lightmap = surf->lightmap;
+ for (i = 0; i < surf->numstyles; i++) {
+ b1 = &lightmap[3 * ((t + 0) * smax + (s + 0))];
+ b2 = &lightmap[3 * ((t + 0) * smax + (s + 1))];
+ b3 = &lightmap[3 * ((t + 1) * smax + (s + 1))];
+ b4 = &lightmap[3 * ((t + 1) * smax + (s + 0))];
+
+ temp[0] = (w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0]) >> 8;
+ temp[1] = (w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1]) >> 8;
+ temp[2] = (w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2]) >> 8;
+
+ style = LIGHT_STYLE(surf, i);
+
+ color[0] += temp[0] * style->rgb[0];
+ color[1] += temp[1] * style->rgb[1];
+ color[2] += temp[2] * style->rgb[2];
+
+ lightmap += size;
+ }
+}
+
+static qboolean _GL_LightPoint(vec3_t start, vec3_t color)
+{
+ bsp_t *bsp;
+ int i, index;
lightpoint_t pt;
vec3_t end, mins, maxs;
entity_t *ent;
@@ -86,48 +132,10 @@ static qboolean GL_SmoothLightPoint(vec3_t start, vec3_t color)
glr.lightpoint = pt;
}
- surf = glr.lightpoint.surf;
- if (!surf)
+ if (!glr.lightpoint.surf)
return qfalse;
- fracu = glr.lightpoint.s & 15;
- fracv = glr.lightpoint.t & 15;
-
- // compute weights of lightmap blocks
- w1 = (16 - fracu) * (16 - fracv);
- w2 = fracu * (16 - fracv);
- w3 = fracu * fracv;
- w4 = (16 - fracu) * fracv;
-
- s = glr.lightpoint.s >> 4;
- t = glr.lightpoint.t >> 4;
-
- smax = S_MAX(surf);
- tmax = T_MAX(surf);
- size = smax * tmax * 3;
-
- VectorClear(color);
-
- // add all the lightmaps with bilinear filtering
- lightmap = surf->lightmap;
- for (i = 0; i < surf->numstyles; i++) {
- b1 = &lightmap[3 * ((t + 0) * smax + (s + 0))];
- b2 = &lightmap[3 * ((t + 0) * smax + (s + 1))];
- b3 = &lightmap[3 * ((t + 1) * smax + (s + 1))];
- b4 = &lightmap[3 * ((t + 1) * smax + (s + 0))];
-
- temp[0] = (w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0]) >> 8;
- temp[1] = (w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1]) >> 8;
- temp[2] = (w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2]) >> 8;
-
- style = LIGHT_STYLE(surf, i);
-
- color[0] += temp[0] * style->rgb[0];
- color[1] += temp[1] * style->rgb[1];
- color[2] += temp[2] * style->rgb[2];
-
- lightmap += size;
- }
+ GL_SampleLightPoint(color);
GL_AdjustColor(color);
@@ -168,7 +176,6 @@ static void GL_MarkLights_r(mnode_t *node, dlight_t *light, int lightbit)
}
GL_MarkLights_r(node->children[0], light, lightbit);
-
node = node->children[1];
}
}
@@ -178,6 +185,8 @@ static void GL_MarkLights(void)
int i;
dlight_t *light;
+ glr.dlightframe++;
+
for (i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++) {
VectorCopy(light->origin, light->transformed);
GL_MarkLights_r(gl_static.world.cache->nodes, light, 1 << i);
@@ -190,9 +199,7 @@ static void GL_TransformLights(mmodel_t *model)
dlight_t *light;
vec3_t temp;
- if (!model->headnode) {
- return;
- }
+ glr.dlightframe++;
for (i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++) {
VectorSubtract(light->origin, glr.ent->origin, temp);
@@ -219,6 +226,10 @@ static void GL_AddLights(vec3_t origin, vec3_t color)
}
}
}
+#else
+#define GL_MarkLights() (void)0
+#define GL_TransformLights() (void)0
+#define GL_AddLights(origin, color) (void)0
#endif
void GL_LightPoint(vec3_t origin, vec3_t color)
@@ -229,16 +240,12 @@ void GL_LightPoint(vec3_t origin, vec3_t color)
}
// get lighting from world
- if (!GL_SmoothLightPoint(origin, color)) {
+ if (!_GL_LightPoint(origin, color)) {
VectorSet(color, 1, 1, 1);
}
-#if USE_DLIGHTS
- if (gl_dynamic->integer == 1) {
- // add dynamic lights
- GL_AddLights(origin, color);
- }
-#endif
+ // add dynamic lights
+ GL_AddLights(origin, color);
if (gl_doublelight_entities->integer) {
// apply modulate twice to mimic original ref_gl behavior
@@ -344,7 +351,7 @@ finish:
}
-#define BACKFACE_EPSILON 0.001f
+#define BACKFACE_EPSILON 0.01f
#define BSP_CullFace(face, dot) \
(((dot) < -BACKFACE_EPSILON && !((face)->drawflags & DSURF_PLANEBACK)) || \
@@ -392,7 +399,7 @@ void GL_DrawBspModel(mmodel_t *model)
}
VectorSubtract(glr.fd.vieworg, ent->origin, transformed);
if (VectorEmpty(ent->origin) && model->drawframe != glr.drawframe) {
- mask = SURF_TRANS33 | SURF_TRANS66;
+ mask = SURF_TRANS_MASK;
}
}
@@ -400,20 +407,12 @@ void GL_DrawBspModel(mmodel_t *model)
// with alpha faces is referenced by multiple entities
model->drawframe = glr.drawframe;
-#if USE_DLIGHTS
- glr.dlightframe++;
- if (gl_dynamic->integer == 1) {
- GL_TransformLights(model);
- }
-#endif
-
- if (gl_dynamic->integer) {
- GL_BeginLights();
- }
+ GL_TransformLights(model);
- qglPushMatrix();
GL_RotateForEntity(ent->origin);
+ GL_BindArrays();
+
// draw visible faces
// FIXME: go by headnode instead?
face = model->firstface;
@@ -427,18 +426,15 @@ void GL_DrawBspModel(mmodel_t *model)
// on rotated or translated inline models
GL_AddAlphaFace(face);
} else {
- GL_AddSolidFace(face);
+ if (gl_dynamic->integer) {
+ GL_PushLights(face);
+ }
+ GL_DrawFace(face);
}
face++;
}
- if (gl_dynamic->integer) {
- GL_EndLights();
- }
-
- GL_DrawSolidFaces();
-
- qglPopMatrix();
+ GL_Flush3D();
}
#define NODE_CLIPPED 0
@@ -504,12 +500,20 @@ static inline void GL_DrawNode(mnode_t *node)
continue;
}
- if (face->drawflags & (SURF_TRANS33 | SURF_TRANS66)) {
+ if (face->drawflags & SURF_TRANS_MASK) {
GL_AddAlphaFace(face);
continue;
}
- GL_AddSolidFace(face);
+ if (gl_dynamic->integer) {
+ GL_PushLights(face);
+ }
+
+ if (gl_hash_faces->integer) {
+ GL_AddSolidFace(face);
+ } else {
+ GL_DrawFace(face);
+ }
}
c.nodesDrawn++;
@@ -551,28 +555,23 @@ void GL_DrawWorld(void)
GL_MarkLeaves();
-#if USE_DLIGHTS
- glr.dlightframe++;
- if (gl_dynamic->integer == 1) {
- GL_MarkLights();
- }
-#endif
+ GL_MarkLights();
R_ClearSkyBox();
- if (gl_dynamic->integer) {
- GL_BeginLights();
- }
+ GL_LoadMatrix(glr.viewmatrix);
+
+ GL_BindArrays();
+
+ GL_ClearSolidFaces();
GL_WorldNode_r(gl_static.world.cache->nodes,
gl_cull_nodes->integer ? NODE_CLIPPED : NODE_UNCLIPPED);
- if (gl_dynamic->integer) {
- GL_EndLights();
- }
-
GL_DrawSolidFaces();
+ GL_Flush3D();
+
R_DrawSkyBox();
}