mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-21 20:21:09 +00:00
Merge pull request #1124 from protocultor/gl1_buffer
Grouped draw calls for improved performance with GL1
This commit is contained in:
commit
eef7db91d8
13 changed files with 739 additions and 612 deletions
|
@ -590,6 +590,7 @@ set(GL1-Source
|
|||
${REF_SRC_DIR}/gl1/gl1_surf.c
|
||||
${REF_SRC_DIR}/gl1/gl1_warp.c
|
||||
${REF_SRC_DIR}/gl1/gl1_sdl.c
|
||||
${REF_SRC_DIR}/gl1/gl1_buffer.c
|
||||
${REF_SRC_DIR}/files/models.c
|
||||
${REF_SRC_DIR}/files/pcx.c
|
||||
${REF_SRC_DIR}/files/stb.c
|
||||
|
|
1
Makefile
1
Makefile
|
@ -959,6 +959,7 @@ REFGL1_OBJS_ := \
|
|||
src/client/refresh/gl1/gl1_surf.o \
|
||||
src/client/refresh/gl1/gl1_warp.o \
|
||||
src/client/refresh/gl1/gl1_sdl.o \
|
||||
src/client/refresh/gl1/gl1_buffer.o \
|
||||
src/client/refresh/files/surf.o \
|
||||
src/client/refresh/files/models.o \
|
||||
src/client/refresh/files/pcx.o \
|
||||
|
|
|
@ -471,10 +471,6 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
|
|||
|
||||
## Graphics (OpenGL 1.4 only)
|
||||
|
||||
* **gl1_biglightmaps**: Enables lightmaps and scrap to use a bigger
|
||||
texture size, which means fewer texture switches, improving
|
||||
performance. Default is `1` (enabled). Requires a `vid_restart`.
|
||||
|
||||
* **gl1_intensity**: Sets the color intensity. Must be a floating point
|
||||
value, at least `1.0` - default is `2.0`. Applied when textures are
|
||||
loaded, so it needs a `vid_restart`.
|
||||
|
|
449
src/client/refresh/gl1/gl1_buffer.c
Normal file
449
src/client/refresh/gl1/gl1_buffer.c
Normal file
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Copyright (C) 2024 Jaime Moreira
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Drawing buffer: sort of a "Q3A shader" handler, allows to join multiple
|
||||
* draw calls into one, by grouping those which share the same
|
||||
* characteristics (mostly the same texture).
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "header/local.h"
|
||||
|
||||
#define MAX_VERTICES 16384
|
||||
#define MAX_INDICES (MAX_VERTICES * 4)
|
||||
|
||||
typedef struct // 832k aprox.
|
||||
{
|
||||
buffered_draw_t type;
|
||||
|
||||
GLfloat
|
||||
vtx[MAX_VERTICES * 3], // vertexes
|
||||
tex[MAX_TEXTURE_UNITS][MAX_VERTICES * 2], // texture coords
|
||||
clr[MAX_VERTICES * 4]; // color components
|
||||
|
||||
GLushort
|
||||
idx[MAX_INDICES], // indices
|
||||
vtx_ptr, idx_ptr; // pointers for array positions
|
||||
|
||||
int texture[MAX_TEXTURE_UNITS];
|
||||
int flags; // entity flags
|
||||
float alpha;
|
||||
} glbuffer_t;
|
||||
|
||||
glbuffer_t gl_buf;
|
||||
|
||||
GLuint vt, tx, cl; // indices for arrays in gl_buf
|
||||
|
||||
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
|
||||
|
||||
void
|
||||
R_ApplyGLBuffer(void)
|
||||
{
|
||||
// Properties of batched draws here
|
||||
GLint vtx_size;
|
||||
qboolean texture, mtex, alpha, color, alias, texenv_set;
|
||||
float fovy, dist;
|
||||
|
||||
if (gl_buf.vtx_ptr == 0 || gl_buf.idx_ptr == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// defaults for drawing (mostly buf_singletex features)
|
||||
vtx_size = 3;
|
||||
texture = true;
|
||||
mtex = alpha = color = alias = texenv_set = false;
|
||||
|
||||
// choosing features by type
|
||||
switch (gl_buf.type)
|
||||
{
|
||||
case buf_2d:
|
||||
vtx_size = 2;
|
||||
break;
|
||||
case buf_mtex:
|
||||
mtex = true;
|
||||
break;
|
||||
case buf_alpha:
|
||||
alpha = true;
|
||||
break;
|
||||
case buf_alias:
|
||||
alias = color = true;
|
||||
break;
|
||||
case buf_flash:
|
||||
color = true;
|
||||
case buf_shadow:
|
||||
texture = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
R_EnableMultitexture(mtex);
|
||||
|
||||
if (alias)
|
||||
{
|
||||
if (gl_buf.flags & RF_DEPTHHACK)
|
||||
{
|
||||
// hack the depth range to prevent view model from poking into walls
|
||||
glDepthRange(gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin));
|
||||
}
|
||||
|
||||
if (gl_buf.flags & RF_WEAPONMODEL)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
if (gl_lefthand->value == 1.0f)
|
||||
{
|
||||
glScalef(-1, 1, 1);
|
||||
}
|
||||
|
||||
fovy = (r_gunfov->value < 0) ? r_newrefdef.fov_y : r_gunfov->value;
|
||||
dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f;
|
||||
R_MYgluPerspective(fovy, (float)r_newrefdef.width / r_newrefdef.height, 4, dist);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
if (gl_lefthand->value == 1.0f)
|
||||
{
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
}
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
R_TexEnv(GL_MODULATE);
|
||||
|
||||
if (gl_buf.flags & RF_TRANSLUCENT)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (gl_buf.flags & (RF_SHELL_RED | RF_SHELL_GREEN |
|
||||
RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
|
||||
{
|
||||
texture = false;
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
// the textures are prescaled up for a better
|
||||
// lighting range, so scale it back down
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, gl_buf.alpha);
|
||||
|
||||
}
|
||||
else if (gl_buf.flags & SURF_DRAWTURB)
|
||||
{
|
||||
texenv_set = true;
|
||||
|
||||
// This is a hack ontop of a hack. Warping surfaces like those generated
|
||||
// by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefore
|
||||
// negated the global intensity on those surfaces, because otherwise they
|
||||
// would show up much too bright. When we implemented overbright bits this
|
||||
// hack modified the global GL state in an incompatible way. So implement
|
||||
// a new hack, based on overbright bits... Depending on the value set to
|
||||
// gl1_overbrightbits the result is different:
|
||||
|
||||
// 0: Old behaviour.
|
||||
// 1: No overbright bits on the global scene but correct lighting on
|
||||
// warping surfaces.
|
||||
// 2,4: Overbright bits on the global scene but not on warping surfaces.
|
||||
// They oversaturate otherwise.
|
||||
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_TexEnv(GL_MODULATE);
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer (vtx_size, GL_FLOAT, 0, gl_buf.vtx);
|
||||
|
||||
if (texture)
|
||||
{
|
||||
if (mtex)
|
||||
{
|
||||
// TMU 1: Lightmap texture
|
||||
R_MBind(GL_TEXTURE1, gl_state.lightmap_textures + gl_buf.texture[1]);
|
||||
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, gl1_overbrightbits->value);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, gl_buf.tex[1]);
|
||||
|
||||
// TMU 0: Color texture
|
||||
R_MBind(GL_TEXTURE0, gl_buf.texture[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_Bind(gl_buf.texture[0]);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, gl_buf.tex[0]);
|
||||
}
|
||||
|
||||
if (color)
|
||||
{
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(4, GL_FLOAT, 0, gl_buf.clr);
|
||||
}
|
||||
|
||||
// All set, we can finally draw
|
||||
glDrawElements(GL_TRIANGLES, gl_buf.idx_ptr, GL_UNSIGNED_SHORT, gl_buf.idx);
|
||||
// ... and now, turn back everything as it was
|
||||
|
||||
if (color)
|
||||
{
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (texture)
|
||||
{
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
if (texenv_set)
|
||||
{
|
||||
R_TexEnv(GL_REPLACE);
|
||||
}
|
||||
|
||||
if (alias)
|
||||
{
|
||||
if (gl_buf.flags & (RF_SHELL_RED | RF_SHELL_GREEN |
|
||||
RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if (gl_buf.flags & RF_TRANSLUCENT)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
if (gl_buf.flags & RF_WEAPONMODEL)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
if (gl_lefthand->value == 1.0F)
|
||||
{
|
||||
glCullFace(GL_FRONT);
|
||||
}
|
||||
}
|
||||
|
||||
if (gl_buf.flags & RF_DEPTHHACK)
|
||||
{
|
||||
glDepthRange(gldepthmin, gldepthmax);
|
||||
}
|
||||
}
|
||||
|
||||
gl_buf.vtx_ptr = gl_buf.idx_ptr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha)
|
||||
{
|
||||
if ( gl_buf.type != type || gl_buf.texture[0] != colortex ||
|
||||
(gl_config.multitexture && type == buf_mtex && gl_buf.texture[1] != lighttex) ||
|
||||
((type == buf_singletex || type == buf_alias) && gl_buf.flags != flags) ||
|
||||
(type == buf_alpha && gl_buf.alpha != alpha))
|
||||
{
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
gl_buf.type = type;
|
||||
gl_buf.texture[0] = colortex;
|
||||
gl_buf.texture[1] = lighttex;
|
||||
gl_buf.flags = flags;
|
||||
gl_buf.alpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
|
||||
GLfloat ul_tx, GLfloat ul_ty, GLfloat dr_tx, GLfloat dr_ty)
|
||||
{
|
||||
static const GLushort idx_max = MAX_INDICES - 7;
|
||||
static const GLushort vtx_max = MAX_VERTICES - 5;
|
||||
unsigned int i;
|
||||
|
||||
if (gl_buf.idx_ptr > idx_max || gl_buf.vtx_ptr > vtx_max)
|
||||
{
|
||||
R_ApplyGLBuffer();
|
||||
}
|
||||
|
||||
i = gl_buf.vtx_ptr * 2; // vertex index
|
||||
|
||||
// "Quad" = 2-triangle GL_TRIANGLE_FAN
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+1;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+2;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+2;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+3;
|
||||
|
||||
// up left corner coords
|
||||
gl_buf.vtx[i] = ul_vx;
|
||||
gl_buf.vtx[i+1] = ul_vy;
|
||||
// up right
|
||||
gl_buf.vtx[i+2] = dr_vx;
|
||||
gl_buf.vtx[i+3] = ul_vy;
|
||||
// down right
|
||||
gl_buf.vtx[i+4] = dr_vx;
|
||||
gl_buf.vtx[i+5] = dr_vy;
|
||||
// and finally, down left
|
||||
gl_buf.vtx[i+6] = ul_vx;
|
||||
gl_buf.vtx[i+7] = dr_vy;
|
||||
|
||||
gl_buf.tex[0][i] = ul_tx;
|
||||
gl_buf.tex[0][i+1] = ul_ty;
|
||||
gl_buf.tex[0][i+2] = dr_tx;
|
||||
gl_buf.tex[0][i+3] = ul_ty;
|
||||
gl_buf.tex[0][i+4] = dr_tx;
|
||||
gl_buf.tex[0][i+5] = dr_ty;
|
||||
gl_buf.tex[0][i+6] = ul_tx;
|
||||
gl_buf.tex[0][i+7] = dr_ty;
|
||||
|
||||
gl_buf.vtx_ptr += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up indices with the proper shape for the next buffered vertices
|
||||
*/
|
||||
void
|
||||
R_SetBufferIndices(GLenum type, GLuint vertices_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( gl_buf.vtx_ptr + vertices_num >= MAX_VERTICES ||
|
||||
gl_buf.idx_ptr + ( (vertices_num - 2) * 3 ) >= MAX_INDICES )
|
||||
{
|
||||
R_ApplyGLBuffer();
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
for (i = 0; i < vertices_num-2; i++)
|
||||
{
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2;
|
||||
}
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
for (i = 0; i < vertices_num-2; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2;
|
||||
}
|
||||
else // backwards order
|
||||
{
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
R_Printf(PRINT_DEVELOPER, "R_SetBufferIndices: no such type %d\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
// These affect the functions that follow in this file
|
||||
vt = gl_buf.vtx_ptr * 3; // vertex index
|
||||
tx = gl_buf.vtx_ptr * 2; // texcoord index
|
||||
cl = gl_buf.vtx_ptr * 4; // color index
|
||||
|
||||
// R_BufferVertex() must be called as many times as vertices_num
|
||||
gl_buf.vtx_ptr += vertices_num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a single vertex to buffer
|
||||
*/
|
||||
void
|
||||
R_BufferVertex(GLfloat x, GLfloat y, GLfloat z)
|
||||
{
|
||||
gl_buf.vtx[vt++] = x;
|
||||
gl_buf.vtx[vt++] = y;
|
||||
gl_buf.vtx[vt++] = z;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds texture coordinates for color texture (no lightmap coords)
|
||||
*/
|
||||
void
|
||||
R_BufferSingleTex(GLfloat s, GLfloat t)
|
||||
{
|
||||
// tx should be set before this is called, by R_SetBufferIndices
|
||||
gl_buf.tex[0][tx++] = s;
|
||||
gl_buf.tex[0][tx++] = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds texture coordinates for color and lightmap
|
||||
*/
|
||||
void
|
||||
R_BufferMultiTex(GLfloat cs, GLfloat ct, GLfloat ls, GLfloat lt)
|
||||
{
|
||||
gl_buf.tex[0][tx] = cs;
|
||||
gl_buf.tex[0][tx+1] = ct;
|
||||
gl_buf.tex[1][tx] = ls;
|
||||
gl_buf.tex[1][tx+1] = lt;
|
||||
tx += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds color components of vertex
|
||||
*/
|
||||
void
|
||||
R_BufferColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
|
||||
{
|
||||
gl_buf.clr[cl++] = r;
|
||||
gl_buf.clr[cl++] = g;
|
||||
gl_buf.clr[cl++] = b;
|
||||
gl_buf.clr[cl++] = a;
|
||||
}
|
|
@ -77,31 +77,10 @@ RDraw_CharScaled(int x, int y, int num, float scale)
|
|||
|
||||
scaledSize = 8*scale;
|
||||
|
||||
R_Bind(draw_chars->texnum);
|
||||
R_UpdateGLBuffer(buf_2d, draw_chars->texnum, 0, 0, 1);
|
||||
|
||||
GLfloat vtx[] = {
|
||||
x, y,
|
||||
x + scaledSize, y,
|
||||
x + scaledSize, y + scaledSize,
|
||||
x, y + scaledSize
|
||||
};
|
||||
|
||||
GLfloat tex[] = {
|
||||
fcol, frow,
|
||||
fcol + size, frow,
|
||||
fcol + size, frow + size,
|
||||
fcol, frow + size
|
||||
};
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 2, GL_FLOAT, 0, vtx );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
R_Buffer2DQuad(x, y, x + scaledSize, y + scaledSize,
|
||||
fcol, frow, fcol + size, frow + size);
|
||||
}
|
||||
|
||||
image_t *
|
||||
|
@ -190,6 +169,14 @@ RDraw_PicScaled(int x, int y, char *pic, float factor)
|
|||
Scrap_Upload();
|
||||
}
|
||||
|
||||
if (gl->texnum == TEXNUM_SCRAPS)
|
||||
{
|
||||
R_UpdateGLBuffer(buf_2d, TEXNUM_SCRAPS, 0, 0, 1);
|
||||
R_Buffer2DQuad(x, y, x + gl->width * factor, y + gl->height * factor,
|
||||
gl->sl, gl->tl, gl->sh, gl->th);
|
||||
return;
|
||||
}
|
||||
|
||||
R_Bind(gl->texnum);
|
||||
|
||||
GLfloat vtx[] = {
|
||||
|
@ -235,31 +222,10 @@ RDraw_TileClear(int x, int y, int w, int h, char *pic)
|
|||
return;
|
||||
}
|
||||
|
||||
R_Bind(image->texnum);
|
||||
R_UpdateGLBuffer(buf_2d, image->texnum, 0, 0, 1);
|
||||
|
||||
GLfloat vtx[] = {
|
||||
x, y,
|
||||
x + w, y,
|
||||
x + w, y + h,
|
||||
x, y + h
|
||||
};
|
||||
|
||||
GLfloat tex[] = {
|
||||
x / 64.0, y / 64.0,
|
||||
( x + w ) / 64.0, y / 64.0,
|
||||
( x + w ) / 64.0, ( y + h ) / 64.0,
|
||||
x / 64.0, ( y + h ) / 64.0
|
||||
};
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 2, GL_FLOAT, 0, vtx );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
R_Buffer2DQuad(x, y, x + w, y + h, x / 64.0, y / 64.0,
|
||||
( x + w ) / 64.0, ( y + h ) / 64.0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -306,6 +272,7 @@ RDraw_Fill(int x, int y, int w, int h, int c)
|
|||
void
|
||||
RDraw_FadeScreen(void)
|
||||
{
|
||||
R_ApplyGLBuffer(); // draw what needs to be hidden
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor4f(0, 0, 0, 0.8);
|
||||
|
|
|
@ -147,21 +147,12 @@ R_SetTexturePalette(unsigned palette[256])
|
|||
void
|
||||
R_SelectTexture(GLenum texture)
|
||||
{
|
||||
int tmu;
|
||||
|
||||
if (!gl_config.multitexture)
|
||||
if (!gl_config.multitexture || gl_state.currenttarget == texture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tmu = texture - GL_TEXTURE0;
|
||||
|
||||
if (tmu == gl_state.currenttmu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gl_state.currenttmu = tmu;
|
||||
gl_state.currenttmu = texture - GL_TEXTURE0;
|
||||
gl_state.currenttarget = texture;
|
||||
|
||||
qglActiveTexture(texture);
|
||||
|
@ -180,7 +171,7 @@ R_TexEnv(GLenum mode)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
qboolean
|
||||
R_Bind(int texnum)
|
||||
{
|
||||
extern image_t *draw_chars;
|
||||
|
@ -192,11 +183,12 @@ R_Bind(int texnum)
|
|||
|
||||
if (gl_state.currenttextures[gl_state.currenttmu] == texnum)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gl_state.currenttextures[gl_state.currenttmu] = texnum;
|
||||
glBindTexture(GL_TEXTURE_2D, texnum);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -308,7 +300,11 @@ R_TextureMode(char *string)
|
|||
nolerp = true;
|
||||
}
|
||||
|
||||
R_Bind(glt->texnum);
|
||||
if ( !R_Bind(glt->texnum) )
|
||||
{
|
||||
continue; // don't bother changing anything if texture was already set
|
||||
}
|
||||
|
||||
if ((glt->type != it_pic) && (glt->type != it_sky)) /* mipmapped texture */
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
|
|
|
@ -35,53 +35,34 @@ static float s_blocklights[34 * 34 * 3];
|
|||
void
|
||||
R_RenderDlight(dlight_t *light)
|
||||
{
|
||||
const float rad = light->intensity * 0.35;
|
||||
int i, j;
|
||||
float a;
|
||||
float rad;
|
||||
float vtx[3], a;
|
||||
|
||||
rad = light->intensity * 0.35;
|
||||
|
||||
GLfloat vtx[3*18];
|
||||
GLfloat clr[4*18];
|
||||
|
||||
unsigned int index_vtx = 3;
|
||||
unsigned int index_clr = 0;
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
clr[index_clr++] = light->color [ 0 ] * 0.2;
|
||||
clr[index_clr++] = light->color [ 1 ] * 0.2;
|
||||
clr[index_clr++] = light->color [ 2 ] * 0.2;
|
||||
clr[index_clr++] = 1;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, 18);
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
vtx [ i ] = light->origin [ i ] - vpn [ i ] * rad;
|
||||
}
|
||||
|
||||
R_BufferVertex( vtx[0], vtx[1], vtx[2] );
|
||||
R_BufferColor( light->color[0] * 0.2, light->color[1] * 0.2,
|
||||
light->color[2] * 0.2, 1 );
|
||||
|
||||
for ( i = 16; i >= 0; i-- )
|
||||
{
|
||||
clr[index_clr++] = 0;
|
||||
clr[index_clr++] = 0;
|
||||
clr[index_clr++] = 0;
|
||||
clr[index_clr++] = 1;
|
||||
|
||||
a = i / 16.0 * M_PI * 2;
|
||||
|
||||
for ( j = 0; j < 3; j++ )
|
||||
{
|
||||
vtx[index_vtx++] = light->origin [ j ] + vright [ j ] * cos( a ) * rad
|
||||
vtx[ j ] = light->origin [ j ] + vright [ j ] * cos( a ) * rad
|
||||
+ vup [ j ] * sin( a ) * rad;
|
||||
}
|
||||
|
||||
R_BufferVertex( vtx[0], vtx[1], vtx[2] );
|
||||
R_BufferColor( 0, 0, 0, 1 );
|
||||
}
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vtx );
|
||||
glColorPointer( 4, GL_FLOAT, 0, clr );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, 18 );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -94,6 +75,7 @@ R_RenderDlights(void)
|
|||
{
|
||||
return;
|
||||
}
|
||||
R_UpdateGLBuffer(buf_flash, 0, 0, 0, 1);
|
||||
|
||||
/* because the count hasn't advanced yet for this frame */
|
||||
r_dlightframecount = r_framecount + 1;
|
||||
|
@ -110,6 +92,7 @@ R_RenderDlights(void)
|
|||
{
|
||||
R_RenderDlight(l);
|
||||
}
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glDisable(GL_BLEND);
|
||||
|
|
|
@ -91,7 +91,6 @@ cvar_t *gl1_particle_square;
|
|||
cvar_t *gl1_palettedtexture;
|
||||
cvar_t *gl1_pointparameters;
|
||||
cvar_t *gl1_multitexture;
|
||||
cvar_t *gl1_biglightmaps;
|
||||
|
||||
cvar_t *gl_drawbuffer;
|
||||
cvar_t *gl_lightmap;
|
||||
|
@ -1221,7 +1220,6 @@ R_Register(void)
|
|||
gl1_palettedtexture = ri.Cvar_Get("r_palettedtextures", "0", CVAR_ARCHIVE);
|
||||
gl1_pointparameters = ri.Cvar_Get("gl1_pointparameters", "1", CVAR_ARCHIVE);
|
||||
gl1_multitexture = ri.Cvar_Get("gl1_multitexture", "1", CVAR_ARCHIVE);
|
||||
gl1_biglightmaps = ri.Cvar_Get("gl1_biglightmaps", "1", CVAR_ARCHIVE);
|
||||
|
||||
gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
|
||||
r_vsync = ri.Cvar_Get("r_vsync", "1", CVAR_ARCHIVE);
|
||||
|
@ -1402,7 +1400,7 @@ R_SetMode(void)
|
|||
qboolean
|
||||
RI_Init(void)
|
||||
{
|
||||
int j, max_tex_size;
|
||||
int j;
|
||||
byte *colormap;
|
||||
extern float r_turbsin[256];
|
||||
|
||||
|
@ -1621,35 +1619,17 @@ RI_Init(void)
|
|||
|
||||
// ----
|
||||
|
||||
/* Big lightmaps */
|
||||
R_Printf(PRINT_ALL, " - Big lightmaps: ");
|
||||
/* Big lightmaps: this used to be fast, but after the implementation of the "GL Buffer", it
|
||||
* became too evident that the bigger the texture, the slower the call to glTexSubImage2D() is.
|
||||
* Original logic remains, but it's preferable not to make it visible to the user.
|
||||
* Let's see if something changes in the future.
|
||||
*/
|
||||
|
||||
gl_state.block_width = BLOCK_WIDTH;
|
||||
gl_state.block_height = BLOCK_HEIGHT;
|
||||
gl_state.max_lightmaps = MAX_LIGHTMAPS;
|
||||
gl_state.scrap_width = BLOCK_WIDTH;
|
||||
gl_state.scrap_height = BLOCK_HEIGHT;
|
||||
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_size);
|
||||
if (max_tex_size > BLOCK_WIDTH)
|
||||
{
|
||||
if (gl1_biglightmaps->value)
|
||||
{
|
||||
gl_state.block_width = gl_state.block_height = Q_min(max_tex_size, 512);
|
||||
gl_state.max_lightmaps = (BLOCK_WIDTH * BLOCK_HEIGHT * MAX_LIGHTMAPS)
|
||||
/ (gl_state.block_width * gl_state.block_height);
|
||||
gl_state.scrap_width = gl_state.scrap_height =
|
||||
(gl_config.npottextures)? Q_min(max_tex_size, 384) : Q_min(max_tex_size, 256);
|
||||
R_Printf(PRINT_ALL, "Okay\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
R_Printf(PRINT_ALL, "Disabled\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_Printf(PRINT_ALL, "Failed, detected texture size = %d\n", max_tex_size);
|
||||
}
|
||||
gl_state.scrap_width = BLOCK_WIDTH * 2;
|
||||
gl_state.scrap_height = BLOCK_HEIGHT * 2;
|
||||
|
||||
// ----
|
||||
|
||||
|
|
|
@ -86,19 +86,13 @@ R_LerpVerts(entity_t *currententity, int nverts, dtrivertx_t *v, dtrivertx_t *ov
|
|||
static void
|
||||
R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
||||
{
|
||||
unsigned short total;
|
||||
GLenum type;
|
||||
float l;
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
int *order;
|
||||
int count;
|
||||
float frontlerp;
|
||||
float alpha;
|
||||
int count, i, index_xyz;
|
||||
float tex[2], frontlerp, l, alpha;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
int index_xyz;
|
||||
float *lerp;
|
||||
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
|
@ -120,13 +114,6 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
|||
alpha = 1.0;
|
||||
}
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
|
||||
RF_SHELL_HALF_DAM))
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
frontlerp = 1.0 - backlerp;
|
||||
|
||||
/* move should be the delta back to the previous frame * backlerp */
|
||||
|
@ -154,135 +141,72 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
|||
|
||||
R_LerpVerts(currententity, paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
|
||||
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
int maxCount = 0;
|
||||
const int* tmpOrder = order;
|
||||
while (1)
|
||||
{
|
||||
int c = *tmpOrder++;
|
||||
if (!c)
|
||||
break;
|
||||
if ( c < 0 )
|
||||
c = -c;
|
||||
if ( c > maxCount )
|
||||
maxCount = c;
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
tmpOrder += 3 * c;
|
||||
}
|
||||
|
||||
YQ2_VLA( GLfloat, vtx, 3 * maxCount );
|
||||
YQ2_VLA( GLfloat, tex, 2 * maxCount );
|
||||
YQ2_VLA( GLfloat, clr, 4 * maxCount );
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
if (!count)
|
||||
{
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
count = -count;
|
||||
|
||||
type = GL_TRIANGLE_FAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
}
|
||||
|
||||
total = count;
|
||||
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
YQ2_VLA(GLfloat, tex, 2*total);
|
||||
YQ2_VLA(GLfloat, clr, 4*total);
|
||||
#endif
|
||||
unsigned int index_vtx = 0;
|
||||
unsigned int index_tex = 0;
|
||||
unsigned int index_clr = 0;
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
|
||||
{
|
||||
do
|
||||
{
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
clr[index_clr++] = shadelight[0];
|
||||
clr[index_clr++] = shadelight[1];
|
||||
clr[index_clr++] = shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
/* texture coordinates come from the draw list */
|
||||
tex[index_tex++] = ((float *) order)[0];
|
||||
tex[index_tex++] = ((float *) order)[1];
|
||||
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
/* normals and vertexes come from the frame list */
|
||||
l = shadedots[verts[index_xyz].lightnormalindex];
|
||||
|
||||
clr[index_clr++] = l * shadelight[0];
|
||||
clr[index_clr++] = l * shadelight[1];
|
||||
clr[index_clr++] = l * shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, vtx);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tex);
|
||||
glColorPointer(4, GL_FLOAT, 0, clr);
|
||||
glDrawArrays(type, 0, total);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
break; /* done */
|
||||
}
|
||||
|
||||
YQ2_VLAFREE( vtx );
|
||||
YQ2_VLAFREE( tex );
|
||||
YQ2_VLAFREE( clr )
|
||||
if (count < 0)
|
||||
{
|
||||
count = -count;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_SetBufferIndices(GL_TRIANGLE_STRIP, count);
|
||||
}
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE |
|
||||
RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
|
||||
{
|
||||
do
|
||||
{
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
R_BufferVertex(s_lerped[index_xyz][0],
|
||||
s_lerped[index_xyz][1], s_lerped[index_xyz][2]);
|
||||
|
||||
R_BufferColor(shadelight[0], shadelight[1],
|
||||
shadelight[2], alpha);
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
/* texture coordinates come from the draw list */
|
||||
tex[0] = ((float *)order)[0];
|
||||
tex[1] = ((float *)order)[1];
|
||||
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
/* normals and vertexes come from the frame list */
|
||||
l = shadedots[verts[index_xyz].lightnormalindex];
|
||||
|
||||
R_BufferVertex(s_lerped[index_xyz][0],
|
||||
s_lerped[index_xyz][1], s_lerped[index_xyz][2]);
|
||||
|
||||
R_BufferSingleTex(tex[0], tex[1]);
|
||||
|
||||
R_BufferColor(l * shadelight[0], l * shadelight[1],
|
||||
l * shadelight[2], alpha);
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
||||
{
|
||||
unsigned short total;
|
||||
GLenum type;
|
||||
int *order;
|
||||
vec3_t point;
|
||||
float height = 0, lheight;
|
||||
|
@ -292,6 +216,8 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
height = -lheight + 0.1f;
|
||||
|
||||
R_UpdateGLBuffer(buf_shadow, 0, 0, 0, 1);
|
||||
|
||||
/* stencilbuffer shadows */
|
||||
if (gl_state.stencil && gl1_stencilshadow->value)
|
||||
{
|
||||
|
@ -300,25 +226,6 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
int maxCount = 0;
|
||||
const int* tmpOrder = order;
|
||||
while (1)
|
||||
{
|
||||
int c = *tmpOrder++;
|
||||
if (!c)
|
||||
break;
|
||||
if (c < 0)
|
||||
c = -c;
|
||||
if (c > maxCount)
|
||||
maxCount = c;
|
||||
|
||||
tmpOrder += 3 * c;
|
||||
}
|
||||
|
||||
YQ2_VLA(GLfloat, vtx, 3 * maxCount);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* get the vertex count and primitive type */
|
||||
|
@ -332,21 +239,13 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
if (count < 0)
|
||||
{
|
||||
count = -count;
|
||||
|
||||
type = GL_TRIANGLE_FAN;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
R_SetBufferIndices(GL_TRIANGLE_STRIP, count);
|
||||
}
|
||||
|
||||
total = count;
|
||||
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
#endif
|
||||
unsigned int index_vtx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
/* normals and vertexes come from the frame list */
|
||||
|
@ -356,22 +255,14 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
point[1] -= shadevector[1] * (point[2] + lheight);
|
||||
point[2] = height;
|
||||
|
||||
vtx[index_vtx++] = point [ 0 ];
|
||||
vtx[index_vtx++] = point [ 1 ];
|
||||
vtx[index_vtx++] = point [ 2 ];
|
||||
R_BufferVertex( point[0], point[1], point[2] );
|
||||
|
||||
order += 3;
|
||||
}
|
||||
while (--count);
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vtx );
|
||||
glDrawArrays( type, 0, total );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
}
|
||||
YQ2_VLAFREE(vtx);
|
||||
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
/* stencilbuffer shadows */
|
||||
if (gl_state.stencil && gl1_stencilshadow->value)
|
||||
|
@ -557,7 +448,6 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
}
|
||||
}
|
||||
|
||||
R_EnableMultitexture(false);
|
||||
paliashdr = (dmdl_t *)currentmodel->extradata;
|
||||
|
||||
/* get lighting information */
|
||||
|
@ -685,7 +575,6 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ir goggles color override */
|
||||
if (r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags &
|
||||
RF_IR_VISIBLE)
|
||||
|
@ -707,45 +596,6 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
/* locate the proper data */
|
||||
c_alias_polys += paliashdr->num_tris;
|
||||
|
||||
/* draw all the triangles */
|
||||
if (currententity->flags & RF_DEPTHHACK)
|
||||
{
|
||||
/* hack the depth range to prevent view model from poking into walls */
|
||||
glDepthRange(gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin));
|
||||
}
|
||||
|
||||
if (currententity->flags & RF_WEAPONMODEL)
|
||||
{
|
||||
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
if (gl_lefthand->value == 1.0F)
|
||||
{
|
||||
glScalef(-1, 1, 1);
|
||||
}
|
||||
|
||||
float dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f;
|
||||
|
||||
if (r_gunfov->value < 0)
|
||||
{
|
||||
R_MYgluPerspective(r_newrefdef.fov_y, (float)r_newrefdef.width / r_newrefdef.height, 4, dist);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_MYgluPerspective(r_gunfov->value, (float)r_newrefdef.width / r_newrefdef.height, 4, dist);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
if (gl_lefthand->value == 1.0F)
|
||||
{
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
currententity->angles[PITCH] = -currententity->angles[PITCH];
|
||||
R_RotateForEntity(currententity);
|
||||
|
@ -778,18 +628,6 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
skin = r_notexture; /* fallback... */
|
||||
}
|
||||
|
||||
R_Bind(skin->texnum);
|
||||
|
||||
/* draw it */
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
R_TexEnv(GL_MODULATE);
|
||||
|
||||
if (currententity->flags & RF_TRANSLUCENT)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
if ((currententity->frame >= paliashdr->num_frames) ||
|
||||
(currententity->frame < 0))
|
||||
{
|
||||
|
@ -813,7 +651,9 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
currententity->backlerp = 0;
|
||||
}
|
||||
|
||||
R_UpdateGLBuffer(buf_alias, skin->texnum, 0, currententity->flags, 1);
|
||||
R_DrawAliasFrameLerp(currententity, paliashdr, currententity->backlerp);
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
@ -836,25 +676,6 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
|
|||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
if (currententity->flags & RF_WEAPONMODEL)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
if (gl_lefthand->value == 1.0F)
|
||||
glCullFace(GL_FRONT);
|
||||
}
|
||||
|
||||
if (currententity->flags & RF_TRANSLUCENT)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (currententity->flags & RF_DEPTHHACK)
|
||||
{
|
||||
glDepthRange(gldepthmin, gldepthmax);
|
||||
}
|
||||
|
||||
if (gl_shadows->value &&
|
||||
!(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW)))
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@ static qboolean vsyncActive = false;
|
|||
void
|
||||
RI_EndFrame(void)
|
||||
{
|
||||
R_ApplyGLBuffer(); // to draw buffered 2D text
|
||||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,63 +43,35 @@ void R_SetCacheState(msurface_t *surf);
|
|||
void R_BuildLightMap(msurface_t *surf, byte *dest, int stride);
|
||||
|
||||
static void
|
||||
R_DrawGLPoly(glpoly_t *p)
|
||||
R_DrawGLPoly(msurface_t *fa)
|
||||
{
|
||||
float *v;
|
||||
int i, nv;
|
||||
float *v, scroll;
|
||||
|
||||
v = p->verts[0];
|
||||
v = fa->polys->verts[0];
|
||||
nv = fa->polys->numverts;
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v+3 );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
static void
|
||||
R_DrawGLFlowingPoly(msurface_t *fa)
|
||||
{
|
||||
int i;
|
||||
float *v;
|
||||
glpoly_t *p;
|
||||
float scroll;
|
||||
|
||||
p = fa->polys;
|
||||
|
||||
scroll = -64 * ((r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0));
|
||||
|
||||
if (scroll == 0.0)
|
||||
if (fa->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
scroll = -64.0;
|
||||
scroll = -64 * ((r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0));
|
||||
|
||||
if (scroll == 0.0)
|
||||
{
|
||||
scroll = -64.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scroll = 0.0;
|
||||
}
|
||||
|
||||
YQ2_VLA(GLfloat, tex, 2*p->numverts);
|
||||
unsigned int index_tex = 0;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, nv);
|
||||
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
for ( i = 0; i < p->numverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
tex[index_tex++] = v [ 3 ] + scroll;
|
||||
tex[index_tex++] = v [ 4 ];
|
||||
}
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
YQ2_VLAFREE(tex);
|
||||
for ( i = 0; i < nv; i++, v += VERTEXSIZE )
|
||||
{
|
||||
R_BufferVertex(v[0], v[1], v[2]);
|
||||
R_BufferSingleTex(v[3] + scroll, v[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -419,47 +391,11 @@ R_RenderBrushPoly(entity_t *currententity, msurface_t *fa)
|
|||
|
||||
if (fa->flags & SURF_DRAWTURB)
|
||||
{
|
||||
/* This is a hack ontop of a hack. Warping surfaces like those generated
|
||||
by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefore
|
||||
negated the global intensity on those surfaces, because otherwise they
|
||||
would show up much too bright. When we implemented overbright bits this
|
||||
hack modified the global GL state in an incompatible way. So implement
|
||||
a new hack, based on overbright bits... Depending on the value set to
|
||||
gl1_overbrightbits the result is different:
|
||||
|
||||
0: Old behaviour.
|
||||
1: No overbright bits on the global scene but correct lighting on
|
||||
warping surfaces.
|
||||
2: Overbright bits on the global scene but not on warping surfaces.
|
||||
They oversaturate otherwise. */
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_TexEnv(GL_MODULATE);
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, 1.0f);
|
||||
}
|
||||
|
||||
R_EmitWaterPolys(fa);
|
||||
R_TexEnv(GL_REPLACE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
|
||||
if (fa->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
R_DrawGLFlowingPoly(fa);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawGLPoly(fa->polys);
|
||||
}
|
||||
R_DrawGLPoly(fa);
|
||||
|
||||
if (gl_config.multitexture)
|
||||
{
|
||||
|
@ -538,7 +474,7 @@ void
|
|||
R_DrawAlphaSurfaces(void)
|
||||
{
|
||||
msurface_t *s;
|
||||
float intens;
|
||||
float alpha;
|
||||
|
||||
/* go back to the world matrix */
|
||||
glLoadMatrixf(r_world_matrix);
|
||||
|
@ -546,41 +482,35 @@ R_DrawAlphaSurfaces(void)
|
|||
glEnable(GL_BLEND);
|
||||
R_TexEnv(GL_MODULATE);
|
||||
|
||||
/* the textures are prescaled up for a better
|
||||
lighting range, so scale it back down */
|
||||
intens = gl_state.inverse_intensity;
|
||||
|
||||
for (s = r_alpha_surfaces; s; s = s->texturechain)
|
||||
{
|
||||
R_Bind(s->texinfo->image->texnum);
|
||||
c_brush_polys++;
|
||||
|
||||
if (s->texinfo->flags & SURF_TRANS33)
|
||||
{
|
||||
glColor4f(intens, intens, intens, 0.33);
|
||||
alpha = 0.33f;
|
||||
}
|
||||
else if (s->texinfo->flags & SURF_TRANS66)
|
||||
{
|
||||
glColor4f(intens, intens, intens, 0.66);
|
||||
alpha = 0.66f;
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(intens, intens, intens, 1);
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
R_UpdateGLBuffer(buf_alpha, s->texinfo->image->texnum, 0, 0, alpha);
|
||||
|
||||
if (s->flags & SURF_DRAWTURB)
|
||||
{
|
||||
R_EmitWaterPolys(s);
|
||||
}
|
||||
else if (s->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
R_DrawGLFlowingPoly(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawGLPoly(s->polys);
|
||||
R_DrawGLPoly(s);
|
||||
}
|
||||
}
|
||||
R_ApplyGLBuffer(); // Flush the last batched array
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
@ -643,15 +573,6 @@ R_RenderLightmappedPoly(entity_t *currententity, msurface_t *surf)
|
|||
float scroll;
|
||||
float *v;
|
||||
|
||||
R_MBind(GL_TEXTURE1, gl_state.lightmap_textures + surf->lightmaptexturenum);
|
||||
|
||||
// Apply overbrightbits to TMU 1 (lightmap)
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, gl1_overbrightbits->value);
|
||||
}
|
||||
|
||||
c_brush_polys++;
|
||||
v = surf->polys->verts[0];
|
||||
|
||||
|
@ -663,82 +584,19 @@ R_RenderLightmappedPoly(entity_t *currententity, msurface_t *surf)
|
|||
{
|
||||
scroll = -64.0;
|
||||
}
|
||||
|
||||
YQ2_VLA(GLfloat, tex, 4 * nv);
|
||||
unsigned int index_tex = 0;
|
||||
|
||||
for (i = 0; i < nv; i++, v += VERTEXSIZE)
|
||||
{
|
||||
tex[index_tex++] = v[3] + scroll;
|
||||
tex[index_tex++] = v[4];
|
||||
tex[index_tex++] = v[5];
|
||||
tex[index_tex++] = v[6];
|
||||
}
|
||||
v = surf->polys->verts[0];
|
||||
|
||||
// Polygon
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v);
|
||||
|
||||
// Texture
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
qglClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(GLfloat), tex);
|
||||
|
||||
// Lightmap
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
qglClientActiveTexture(GL_TEXTURE1);
|
||||
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(GLfloat), tex + 2);
|
||||
|
||||
// Draw the thing
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, nv);
|
||||
|
||||
YQ2_VLAFREE(tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Polygon
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v);
|
||||
|
||||
// Texture
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
qglClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v + 3);
|
||||
|
||||
// Lightmap
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
qglClientActiveTexture(GL_TEXTURE1);
|
||||
glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v + 5);
|
||||
|
||||
// Draw it
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, nv);
|
||||
scroll = 0.0;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, nv);
|
||||
|
||||
static void
|
||||
R_UploadDynamicLights(msurface_t *surf)
|
||||
{
|
||||
int map, smax, tmax;
|
||||
|
||||
if ( !gl_config.multitexture || !R_HasDynamicLights(surf, &map) )
|
||||
for (i = 0; i < nv; i++, v += VERTEXSIZE)
|
||||
{
|
||||
return;
|
||||
R_BufferVertex( v[0], v[1], v[2] );
|
||||
R_BufferMultiTex( v[3] + scroll, v[4], v[5], v[6] );
|
||||
}
|
||||
YQ2_VLA(byte, temp, gl_state.block_width * gl_state.block_height);
|
||||
|
||||
smax = (surf->extents[0] >> 4) + 1;
|
||||
tmax = (surf->extents[1] >> 4) + 1;
|
||||
R_BuildLightMap(surf, (void *) temp, smax * LIGHTMAP_BYTES);
|
||||
R_UpdateSurfCache(surf, map);
|
||||
|
||||
R_Bind(gl_state.lightmap_textures + surf->lightmaptexturenum);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax,
|
||||
tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
|
||||
YQ2_VLAFREE(temp);
|
||||
}
|
||||
|
||||
/* Upload dynamic lights to each lightmap texture (multitexture path only) */
|
||||
|
@ -864,17 +722,16 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
|
||||
for ( ; s; s = s->texturechain)
|
||||
{
|
||||
R_Bind(image->texnum); // may reset because of dynamic lighting in R_RenderBrushPoly
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, s->flags, 1);
|
||||
R_RenderBrushPoly(currententity, s);
|
||||
}
|
||||
|
||||
image->texturechain = NULL;
|
||||
}
|
||||
R_ApplyGLBuffer(); // Flush the last batched array
|
||||
}
|
||||
else // multitexture
|
||||
{
|
||||
R_EnableMultitexture(true);
|
||||
|
||||
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
||||
{
|
||||
if (!image->registration_sequence || !image->texturechain)
|
||||
|
@ -882,19 +739,20 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
continue;
|
||||
}
|
||||
|
||||
R_MBind(GL_TEXTURE0, image->texnum); // setting it only once
|
||||
c_visible_textures++;
|
||||
|
||||
for (s = image->texturechain; s; s = s->texturechain)
|
||||
{
|
||||
if (!(s->flags & SURF_DRAWTURB))
|
||||
{
|
||||
R_UpdateGLBuffer(buf_mtex, image->texnum, s->lightmaptexturenum, 0, 1);
|
||||
R_RenderLightmappedPoly(currententity, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
R_EnableMultitexture(false);
|
||||
R_EnableMultitexture(false); // force disabling, SURF_DRAWTURB surfaces may not exist
|
||||
|
||||
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
||||
{
|
||||
|
@ -907,13 +765,14 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
{
|
||||
if (s->flags & SURF_DRAWTURB)
|
||||
{
|
||||
R_Bind(image->texnum);
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, s->flags, 1);
|
||||
R_RenderBrushPoly(currententity, s);
|
||||
}
|
||||
}
|
||||
|
||||
image->texturechain = NULL;
|
||||
}
|
||||
R_ApplyGLBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -928,7 +787,7 @@ R_DrawInlineBModel(entity_t *currententity, const model_t *currentmodel)
|
|||
image_t *image;
|
||||
|
||||
/* calculate dynamic lighting for bmodel */
|
||||
if (!gl1_flashblend->value)
|
||||
if (!gl_config.multitexture && !gl1_flashblend->value)
|
||||
{
|
||||
lt = r_newrefdef.dlights;
|
||||
|
||||
|
@ -973,20 +832,19 @@ R_DrawInlineBModel(entity_t *currententity, const model_t *currentmodel)
|
|||
|
||||
if (gl_config.multitexture && !(psurf->flags & SURF_DRAWTURB))
|
||||
{
|
||||
R_UploadDynamicLights(psurf);
|
||||
R_EnableMultitexture(true);
|
||||
R_MBind(GL_TEXTURE0, image->texnum);
|
||||
// Dynamic lighting already generated in R_GetBrushesLighting()
|
||||
R_UpdateGLBuffer(buf_mtex, image->texnum, psurf->lightmaptexturenum, 0, 1);
|
||||
R_RenderLightmappedPoly(currententity, psurf);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_EnableMultitexture(false);
|
||||
R_Bind(image->texnum);
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, psurf->flags, 1);
|
||||
R_RenderBrushPoly(currententity, psurf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
if (!(currententity->flags & RF_TRANSLUCENT))
|
||||
{
|
||||
|
@ -1214,6 +1072,96 @@ R_RecursiveWorldNode(entity_t *currententity, mnode_t *node)
|
|||
R_RecursiveWorldNode(currententity, node->children[!side]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for the RegenAllLightmaps() function to be able to regenerate
|
||||
* lighting not only for the world, but also for the brushes in the entity list.
|
||||
* Logic extracted from R_DrawBrushModel() & R_DrawInlineBModel().
|
||||
*/
|
||||
static void
|
||||
R_GetBrushesLighting(void)
|
||||
{
|
||||
int i, k;
|
||||
vec3_t mins, maxs;
|
||||
msurface_t *surf;
|
||||
cplane_t *pplane;
|
||||
dlight_t *lt;
|
||||
float dot;
|
||||
|
||||
if (!gl_config.multitexture || !r_drawentities->value || gl1_flashblend->value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < r_newrefdef.num_entities; i++)
|
||||
{
|
||||
entity_t *currententity = &r_newrefdef.entities[i];
|
||||
|
||||
if (currententity->flags & RF_BEAM)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const model_t *currentmodel = currententity->model;
|
||||
|
||||
if (!currentmodel || currentmodel->type != mod_brush || currentmodel->nummodelsurfaces == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// from R_DrawBrushModel()
|
||||
if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2])
|
||||
{
|
||||
for (k = 0; k < 3; k++)
|
||||
{
|
||||
mins[k] = currententity->origin[k] - currentmodel->radius;
|
||||
maxs[k] = currententity->origin[k] + currentmodel->radius;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd(currententity->origin, currentmodel->mins, mins);
|
||||
VectorAdd(currententity->origin, currentmodel->maxs, maxs);
|
||||
}
|
||||
|
||||
if (r_cull->value && R_CullBox(mins, maxs, frustum))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// from R_DrawInlineBModel()
|
||||
lt = r_newrefdef.dlights;
|
||||
|
||||
for (k = 0; k < r_newrefdef.num_dlights; k++, lt++)
|
||||
{
|
||||
R_MarkLights(lt, 1 << k,
|
||||
currentmodel->nodes + currentmodel->firstnode,
|
||||
r_dlightframecount, R_MarkSurfaceLights);
|
||||
}
|
||||
|
||||
surf = ¤tmodel->surfaces[currentmodel->firstmodelsurface];
|
||||
|
||||
for (k = 0; k < currentmodel->nummodelsurfaces; k++, surf++)
|
||||
{
|
||||
if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)
|
||||
|| surf->flags & SURF_DRAWTURB)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// find which side of the node we are on
|
||||
pplane = surf->plane;
|
||||
dot = DotProduct(modelorg, pplane->normal) - pplane->dist;
|
||||
|
||||
if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
||||
(!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
|
||||
{
|
||||
surf->lightmapchain = gl_lms.lightmap_surfaces[surf->lightmaptexturenum];
|
||||
gl_lms.lightmap_surfaces[surf->lightmaptexturenum] = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
R_DrawWorld(void)
|
||||
{
|
||||
|
@ -1242,6 +1190,7 @@ R_DrawWorld(void)
|
|||
|
||||
R_ClearSkyBox();
|
||||
R_RecursiveWorldNode(&ent, r_worldmodel->nodes);
|
||||
R_GetBrushesLighting();
|
||||
R_RegenAllLightmaps();
|
||||
R_DrawTextureChains(&ent);
|
||||
R_BlendLightmaps(r_worldmodel);
|
||||
|
|
|
@ -282,7 +282,7 @@ R_EmitWaterPolys(msurface_t *fa)
|
|||
{
|
||||
glpoly_t *p, *bp;
|
||||
float *v;
|
||||
int i;
|
||||
int i, nv;
|
||||
float s, t, os, ot;
|
||||
float scroll;
|
||||
float rdt = r_newrefdef.time;
|
||||
|
@ -296,53 +296,24 @@ R_EmitWaterPolys(msurface_t *fa)
|
|||
scroll = 0;
|
||||
}
|
||||
|
||||
// workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
#ifdef _MSC_VER
|
||||
int maxNumVerts = 0;
|
||||
for ( glpoly_t* tmp = fa->polys; tmp; tmp = tmp->next )
|
||||
{
|
||||
if (tmp->numverts > maxNumVerts)
|
||||
maxNumVerts = tmp->numverts;
|
||||
}
|
||||
|
||||
YQ2_VLA( GLfloat, tex, 2 * maxNumVerts );
|
||||
#endif
|
||||
|
||||
for (bp = fa->polys; bp; bp = bp->next)
|
||||
{
|
||||
p = bp;
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, tex, 2*p->numverts);
|
||||
#endif
|
||||
unsigned int index_tex = 0;
|
||||
nv = p->numverts;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, nv);
|
||||
|
||||
for ( i = 0, v = p->verts [ 0 ]; i < p->numverts; i++, v += VERTEXSIZE )
|
||||
for ( i = 0, v = p->verts [ 0 ]; i < nv; i++, v += VERTEXSIZE )
|
||||
{
|
||||
os = v [ 3 ];
|
||||
ot = v [ 4 ];
|
||||
|
||||
s = os + r_turbsin [ (int) ( ( ot * 0.125 + r_newrefdef.time ) * TURBSCALE ) & 255 ];
|
||||
s += scroll;
|
||||
tex[index_tex++] = s * ( 1.0 / 64 );
|
||||
|
||||
s = os + r_turbsin [ (int) ( ( ot * 0.125 + rdt ) * TURBSCALE ) & 255 ] + scroll;
|
||||
t = ot + r_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ];
|
||||
tex[index_tex++] = t * ( 1.0 / 64 );
|
||||
|
||||
R_BufferVertex( v[0], v[1], v[2] );
|
||||
R_BufferSingleTex( s * ( 1.0 / 64 ), t * ( 1.0 / 64 ) );
|
||||
}
|
||||
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
YQ2_VLAFREE( tex );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -39,17 +39,18 @@
|
|||
#define GL_COLOR_INDEX8_EXT GL_COLOR_INDEX
|
||||
#endif
|
||||
|
||||
#define TEXNUM_LIGHTMAPS 1024
|
||||
#define TEXNUM_SCRAPS 1152
|
||||
#define TEXNUM_IMAGES 1153
|
||||
#define MAX_GLTEXTURES 1024
|
||||
#define MAX_LIGHTMAPS 128
|
||||
#define MAX_SCRAPS 1
|
||||
#define TEXNUM_LIGHTMAPS 1024
|
||||
#define TEXNUM_SCRAPS (TEXNUM_LIGHTMAPS + MAX_LIGHTMAPS)
|
||||
#define TEXNUM_IMAGES (TEXNUM_SCRAPS + MAX_SCRAPS)
|
||||
#define MAX_GLTEXTURES 1024
|
||||
#define BLOCK_WIDTH 128 // default values; now defined in glstate_t
|
||||
#define BLOCK_HEIGHT 128
|
||||
#define REF_VERSION "Yamagi Quake II OpenGL Refresher"
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
#define LIGHTMAP_BYTES 4
|
||||
#define MAX_LIGHTMAPS 128
|
||||
#define MAX_TEXTURE_UNITS 2
|
||||
#define GL_LIGHTMAP_FORMAT GL_RGBA
|
||||
|
||||
/* up / down */
|
||||
|
@ -106,22 +107,23 @@ typedef enum
|
|||
rserr_unknown
|
||||
} rserr_t;
|
||||
|
||||
#include "model.h"
|
||||
typedef enum
|
||||
{
|
||||
buf_2d,
|
||||
buf_singletex,
|
||||
buf_mtex,
|
||||
buf_alpha,
|
||||
buf_alias,
|
||||
buf_flash,
|
||||
buf_shadow
|
||||
} buffered_draw_t;
|
||||
|
||||
void GL_BeginRendering(int *x, int *y, int *width, int *height);
|
||||
void GL_EndRendering(void);
|
||||
#include "model.h"
|
||||
|
||||
void R_SetDefaultState(void);
|
||||
|
||||
extern float gldepthmin, gldepthmax;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z;
|
||||
float s, t;
|
||||
float r, g, b;
|
||||
} glvert_t;
|
||||
|
||||
extern image_t gltextures[MAX_GLTEXTURES];
|
||||
extern int numgltextures;
|
||||
|
||||
|
@ -163,7 +165,6 @@ extern cvar_t *gl1_overbrightbits;
|
|||
extern cvar_t *gl1_palettedtexture;
|
||||
extern cvar_t *gl1_pointparameters;
|
||||
extern cvar_t *gl1_multitexture;
|
||||
extern cvar_t *gl1_biglightmaps;
|
||||
|
||||
extern cvar_t *gl1_particle_min_size;
|
||||
extern cvar_t *gl1_particle_max_size;
|
||||
|
@ -229,7 +230,7 @@ extern int c_visible_textures;
|
|||
extern float r_world_matrix[16];
|
||||
|
||||
void R_TranslatePlayerSkin(int playernum);
|
||||
void R_Bind(int texnum);
|
||||
qboolean R_Bind(int texnum);
|
||||
|
||||
void R_TexEnv(GLenum value);
|
||||
void R_SelectTexture(GLenum);
|
||||
|
@ -290,12 +291,23 @@ void R_TextureAlphaMode(char *string);
|
|||
void R_TextureSolidMode(char *string);
|
||||
int Scrap_AllocBlock(int w, int h, int *x, int *y);
|
||||
|
||||
void R_ApplyGLBuffer(void);
|
||||
void R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha);
|
||||
void R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
|
||||
GLfloat ul_tx, GLfloat ul_ty, GLfloat dr_tx, GLfloat dr_ty);
|
||||
void R_SetBufferIndices(GLenum type, GLuint vertices_num);
|
||||
void R_BufferVertex(GLfloat x, GLfloat y, GLfloat z);
|
||||
void R_BufferSingleTex(GLfloat s, GLfloat t);
|
||||
void R_BufferMultiTex(GLfloat cs, GLfloat ct, GLfloat ls, GLfloat lt);
|
||||
void R_BufferColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
#ifdef DEBUG
|
||||
void glCheckError_(const char *file, const char *function, int line);
|
||||
// Ideally, the following list should contain all OpenGL calls.
|
||||
// Either way, errors are caught, since error flags are persisted until the next glGetError() call.
|
||||
// So they show, even if the location of the error is inaccurate.
|
||||
#define glDrawArrays(...) glDrawArrays(__VA_ARGS__); glCheckError_(__FILE__, __func__, __LINE__)
|
||||
#define glDrawElements(...) glDrawElements(__VA_ARGS__); glCheckError_(__FILE__, __func__, __LINE__)
|
||||
#define glTexImage2D(...) glTexImage2D(__VA_ARGS__); glCheckError_(__FILE__, __func__, __LINE__)
|
||||
#define glTexSubImage2D(...) glTexSubImage2D(__VA_ARGS__); glCheckError_(__FILE__, __func__, __LINE__)
|
||||
#define glTexEnvf(...) glTexEnvf(__VA_ARGS__); glCheckError_(__FILE__, __func__, __LINE__)
|
||||
|
@ -382,7 +394,7 @@ typedef struct
|
|||
|
||||
int lightmap_textures;
|
||||
|
||||
int currenttextures[2];
|
||||
int currenttextures[MAX_TEXTURE_UNITS];
|
||||
int currenttmu;
|
||||
GLenum currenttarget;
|
||||
|
||||
|
|
Loading…
Reference in a new issue