summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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();
}