mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-25 14:00:58 +00:00
GL1 unified draw calls, init
Implemented a batching procedure, to try to group meshes in a buffer and use a final GL call to draw them all in one step, instead of the many GL draw calls existing today. For now, only 2D textures are included, especifically console text ("conchars"), scrap and tiles. It's not worth doing this for individual 2D elements (e.g. crosshair).
This commit is contained in:
parent
4503333b3a
commit
50aebd2de4
6 changed files with 206 additions and 61 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 \
|
||||
|
|
171
src/client/refresh/gl1/gl1_buffer.c
Normal file
171
src/client/refresh/gl1/gl1_buffer.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
if (gl_buf.vtx_ptr == 0 || gl_buf.idx_ptr == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// defaults for drawing
|
||||
vtx_size = 3;
|
||||
texture = true;
|
||||
|
||||
// choosing features by type
|
||||
switch (gl_buf.type)
|
||||
{
|
||||
case buf_2d:
|
||||
vtx_size = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer (vtx_size, GL_FLOAT, 0, gl_buf.vtx);
|
||||
|
||||
if (texture)
|
||||
{
|
||||
R_Bind(gl_buf.texture[0]);
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, gl_buf.tex[0]);
|
||||
}
|
||||
|
||||
// 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 (texture)
|
||||
{
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -46,6 +46,7 @@ static qboolean vsyncActive = false;
|
|||
void
|
||||
RI_EndFrame(void)
|
||||
{
|
||||
R_ApplyGLBuffer(); // to draw buffered 2D text
|
||||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,19 +107,17 @@ typedef enum
|
|||
rserr_unknown
|
||||
} rserr_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
buf_2d
|
||||
} buffered_draw_t;
|
||||
|
||||
#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;
|
||||
|
||||
|
@ -287,6 +286,11 @@ 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);
|
||||
|
||||
#ifdef DEBUG
|
||||
void glCheckError_(const char *file, const char *function, int line);
|
||||
// Ideally, the following list should contain all OpenGL calls.
|
||||
|
@ -380,7 +384,7 @@ typedef struct
|
|||
|
||||
int lightmap_textures;
|
||||
|
||||
int currenttextures[2];
|
||||
int currenttextures[MAX_TEXTURE_UNITS];
|
||||
int currenttmu;
|
||||
GLenum currenttarget;
|
||||
|
||||
|
|
Loading…
Reference in a new issue