Adding the new renderer

This commit is contained in:
Richard Allen 2011-03-09 00:56:46 +00:00
parent 2b5d779adf
commit 615d28dd92
29 changed files with 8977 additions and 835 deletions

View file

@ -1431,8 +1431,10 @@ Q3OBJ = \
$(B)/client/tr_bsp.o \
$(B)/client/tr_cmds.o \
$(B)/client/tr_curve.o \
$(B)/client/tr_extramath.o \
$(B)/client/tr_flares.o \
$(B)/client/tr_font.o \
$(B)/client/tr_glsl.o \
$(B)/client/tr_image.o \
$(B)/client/tr_image_png.o \
$(B)/client/tr_image_jpg.o \
@ -1454,6 +1456,7 @@ Q3OBJ = \
$(B)/client/tr_sky.o \
$(B)/client/tr_surface.o \
$(B)/client/tr_world.o \
$(B)/client/tr_vbo.o \
\
$(B)/client/sdl_gamma.o \
$(B)/client/sdl_input.o \

View file

@ -652,7 +652,7 @@ Returns 1, 2, or 1 + 2
int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p)
{
float dist[2];
int sides, b, i;
int sides; //, b, i;
// fast axial cases
if (p->type < 3)
@ -665,6 +665,7 @@ int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p)
}
// general case
#if 0
dist[0] = dist[1] = 0;
if (p->signbits < 8) // >= 8: default case is original code (dist[0]=dist[1]=0)
{
@ -675,6 +676,47 @@ int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p)
dist[!b] += p->normal[i]*emins[i];
}
}
#else
// general case
switch (p->signbits)
{
case 0:
dist[0] = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist[1] = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 1:
dist[0] = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist[1] = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 2:
dist[0] = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist[1] = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 3:
dist[0] = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist[1] = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 4:
dist[0] = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist[1] = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 5:
dist[0] = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist[1] = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 6:
dist[0] = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist[1] = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
case 7:
dist[0] = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist[1] = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
default:
dist[0] = dist[1] = 0; // shut up compiler
break;
}
#endif
sides = 0;
if (dist[0] >= p->dist)

View file

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// surface geometry should not exceed these limits
#define SHADER_MAX_VERTEXES 1000
#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
#define SHADER_MAX_TRIANGLES (SHADER_MAX_INDEXES / 3)
// the maximum size of game relative pathnames

View file

@ -39,6 +39,108 @@ extern void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat
extern void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
extern void (APIENTRYP qglUnlockArraysEXT) (void);
// GL_EXT_multi_draw_arrays
extern void (APIENTRY * qglMultiDrawArraysEXT) (GLenum, GLint *, GLsizei *, GLsizei);
extern void (APIENTRY * qglMultiDrawElementsEXT) (GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei);
// GL_ARB_vertex_program
extern void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
extern void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
extern void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid * pointer);
extern void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
extern void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
// GL_ARB_vertex_buffer_object
extern void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
extern void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
extern void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
extern GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
extern void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
extern void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
extern void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
extern void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
extern void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
// GL_ARB_shader_objects
extern void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
extern GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
extern void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
extern GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
extern void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
const GLint * length);
extern void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
extern GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
extern void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
extern void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
extern void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
extern void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
extern void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
extern void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
extern void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
extern void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
extern void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
extern void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
extern void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
extern void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
extern void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
extern void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
extern void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
extern void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
extern void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
extern void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
extern void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
extern void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
extern void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
extern void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
GLhandleARB * obj);
extern GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
extern void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
GLint * size, GLenum * type, GLcharARB * name);
extern void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
extern void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
extern void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
// GL_ARB_vertex_shader
extern void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
extern void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
GLint * size, GLenum * type, GLcharARB * name);
extern GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
#if defined(WIN32)
// WGL_ARB_create_context
#ifndef WGL_ARB_create_context
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096
#endif
extern HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList);
#endif
#if 0 //defined(__linux__)
// GLX_ARB_create_context
#ifndef GLX_ARB_create_context
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GLX_CONTEXT_FLAGS_ARB 0x2094
#endif
extern GLXContext (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
#endif
//===========================================================================

View file

@ -73,15 +73,21 @@ void GL_SelectTexture( int unit )
{
qglActiveTextureARB( GL_TEXTURE0_ARB );
GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE0_ARB )\n" );
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglClientActiveTextureARB( GL_TEXTURE0_ARB );
GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE0_ARB )\n" );
}
}
else if ( unit == 1 )
{
qglActiveTextureARB( GL_TEXTURE1_ARB );
GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE1_ARB )\n" );
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglClientActiveTextureARB( GL_TEXTURE1_ARB );
GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE1_ARB )\n" );
}
} else {
ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
}
@ -117,6 +123,25 @@ void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint
}
}
/*
** GL_BindToTMU
*/
void GL_BindToTMU( image_t *image, int tmu )
{
int texnum;
int oldtmu = glState.currenttmu;
texnum = image->texnum;
if ( glState.currenttextures[tmu] != texnum ) {
GL_SelectTexture( tmu );
image->frameUsed = tr.frameCount;
glState.currenttextures[tmu] = texnum;
qglBindTexture( GL_TEXTURE_2D, texnum );
GL_SelectTexture( oldtmu );
}
}
/*
** GL_Cull
@ -386,6 +411,33 @@ void GL_State( unsigned long stateBits )
}
void GL_SetProjectionMatrix(matrix_t matrix)
{
Matrix16Copy(matrix, glState.projection);
Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(matrix);
qglMatrixMode(GL_MODELVIEW);
}
}
void GL_SetModelviewMatrix(matrix_t matrix)
{
Matrix16Copy(matrix, glState.modelview);
Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglLoadMatrixf(matrix);
}
}
/*
================
@ -410,9 +462,7 @@ static void RB_Hyperspace( void ) {
static void SetViewportAndScissor( void ) {
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf( backEnd.viewParms.projectionMatrix );
qglMatrixMode(GL_MODELVIEW);
GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
// set the window clipping
qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
@ -500,17 +550,27 @@ void RB_BeginDrawingView (void) {
plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane);
plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
qglLoadMatrixf( s_flipMatrix );
GL_SetModelviewMatrix( s_flipMatrix );
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglClipPlane (GL_CLIP_PLANE0, plane2);
qglEnable (GL_CLIP_PLANE0);
}
} else {
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglDisable (GL_CLIP_PLANE0);
}
}
}
#define MAC_EVENT_PUMP_MSEC 5
/*
==================
RB_RenderDrawSurfList
@ -565,6 +625,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
RB_EndSurface();
}
RB_BeginSurface( shader, fogNum );
backEnd.pc.c_surfBatches++;
oldShader = shader;
oldFogNum = fogNum;
oldDlighted = dlighted;
@ -609,7 +670,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
}
qglLoadMatrixf( backEnd.or.modelMatrix );
GL_SetModelviewMatrix( backEnd.or.modelMatrix );
//
// change depthrange. Also change projection matrix so first person weapon does not look like coming
@ -626,9 +687,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
if(oldDepthRange)
{
// was not a crosshair but now is, change back proj matrix
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
qglMatrixMode(GL_MODELVIEW);
GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
}
}
else
@ -637,9 +696,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
R_SetupProjection(&temp, r_znear->value, qfalse);
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(temp.projectionMatrix);
qglMatrixMode(GL_MODELVIEW);
GL_SetProjectionMatrix( temp.projectionMatrix );
}
}
@ -650,9 +707,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
{
if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
qglMatrixMode(GL_MODELVIEW);
GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
}
qglDepthRange (0, 1);
@ -677,7 +732,8 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
// go back to the world modelview matrix
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix );
if ( depthRange ) {
qglDepthRange (0, 1);
}
@ -708,16 +764,18 @@ RB_SetGL2D
================
*/
void RB_SetGL2D (void) {
matrix_t matrix;
backEnd.projection2D = qtrue;
// set 2D virtual screen size
qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity ();
qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity ();
Matrix16Ortho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, matrix);
GL_SetProjectionMatrix(matrix);
Matrix16Identity(matrix);
GL_SetModelviewMatrix(matrix);
GL_State( GLS_DEPTHTEST_DISABLE |
GLS_SRCBLEND_SRC_ALPHA |
@ -744,6 +802,7 @@ Used for cinematics.
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
int i, j;
int start, end;
matrix_t matrix;
if ( !tr.registered ) {
return;
@ -793,9 +852,103 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
RB_SetGL2D();
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
tess.xyz[tess.numVertexes][0] = x;
tess.xyz[tess.numVertexes][1] = y;
tess.xyz[tess.numVertexes][2] = 0;
tess.xyz[tess.numVertexes][3] = 1;
tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols;
tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
tess.xyz[tess.numVertexes][0] = x + w;
tess.xyz[tess.numVertexes][1] = y;
tess.xyz[tess.numVertexes][2] = 0;
tess.xyz[tess.numVertexes][3] = 1;
tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols;
tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
tess.xyz[tess.numVertexes][0] = x + w;
tess.xyz[tess.numVertexes][1] = y + h;
tess.xyz[tess.numVertexes][2] = 0;
tess.xyz[tess.numVertexes][3] = 1;
tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols;
tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
tess.xyz[tess.numVertexes][0] = x;
tess.xyz[tess.numVertexes][1] = y + h;
tess.xyz[tess.numVertexes][2] = 0;
tess.xyz[tess.numVertexes][3] = 1;
tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols;
tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 1;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 3;
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = &tr.genericShader[0];
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniform_ModelViewProjectionMatrix(sp, glState.modelviewProjection);
GLSL_SetUniform_FogAdjustColors(sp, 0);
GLSL_SetUniform_DeformGen(sp, DGEN_NONE);
GLSL_SetUniform_TCGen0(sp, TCGEN_TEXTURE);
Matrix16Identity(matrix);
GLSL_SetUniform_Texture0Matrix(sp, matrix);
GLSL_SetUniform_Texture1Env(sp, 0);
GLSL_SetUniform_ColorGen(sp, CGEN_IDENTITY);
GLSL_SetUniform_AlphaGen(sp, AGEN_IDENTITY);
}
else
{
qglEnableClientState( GL_VERTEX_ARRAY );
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
qglVertexPointer(3, GL_FLOAT, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz));
qglTexCoordPointer( 2, GL_FLOAT, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st) );
}
qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(0));
//R_BindNullVBO();
//R_BindNullIBO();
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
}
else
{
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
qglBegin (GL_QUADS);
qglBegin (GL_QUADS); // Alternate made
qglTexCoord2f ( 0.5f / cols, 0.5f / rows );
qglVertex2f (x, y);
qglTexCoord2f ( ( cols - 0.5f ) / cols , 0.5f / rows );
@ -805,6 +958,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
qglVertex2f (x, y+h);
qglEnd ();
}
}
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
@ -986,6 +1140,7 @@ void RB_ShowImages( void ) {
int i;
image_t *image;
float x, y, w, h;
vec4_t quadVerts[4];
int start, end;
if ( !backEnd.projection2D ) {
@ -1012,7 +1167,20 @@ void RB_ShowImages( void ) {
h *= image->uploadHeight / 512.0f;
}
GL_Bind( image );
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
GL_Bind(image);
VectorSet4(quadVerts[0], x, y, 0, 1);
VectorSet4(quadVerts[1], x + w, y, 0, 1);
VectorSet4(quadVerts[2], x + w, y + h, 0, 1);
VectorSet4(quadVerts[3], x, y + h, 0, 1);
RB_InstantQuad(quadVerts);
}
else
{
GL_Bind( image ); // Alternate made
qglBegin (GL_QUADS);
qglTexCoord2f( 0, 0 );
qglVertex2f( x, y );
@ -1024,6 +1192,7 @@ void RB_ShowImages( void ) {
qglVertex2f( x, y + h );
qglEnd();
}
}
qglFinish();
@ -1207,3 +1376,4 @@ void RB_RenderThread( void ) {
}
}

File diff suppressed because it is too large Load diff

View file

@ -40,8 +40,8 @@ void R_PerformanceCounters( void ) {
}
if (r_speeds->integer == 1) {
ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
ri.Printf (PRINT_ALL, "%i/%i/%i shaders/batches/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
backEnd.pc.c_shaders, backEnd.pc.c_surfBatches, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
} else if (r_speeds->integer == 2) {
@ -69,6 +69,11 @@ void R_PerformanceCounters( void ) {
ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
}
else if (r_speeds->integer == 7 )
{
ri.Printf( PRINT_ALL, "VBO draws: static %i dynamic %i\nMultidraws: %i merged %i\n",
backEnd.pc.c_staticVboDraws, backEnd.pc.c_dynamicVboDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged );
}
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );

View file

@ -33,7 +33,7 @@ distance from the true curve.
Only a single entry point:
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
*/
@ -43,7 +43,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
LerpDrawVert
============
*/
static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
static void LerpDrawVert( srfVert_t *a, srfVert_t *b, srfVert_t *out ) {
out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]);
out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]);
out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]);
@ -54,10 +54,10 @@ static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
out->color[0] = (a->color[0] + b->color[0]) >> 1;
out->color[1] = (a->color[1] + b->color[1]) >> 1;
out->color[2] = (a->color[2] + b->color[2]) >> 1;
out->color[3] = (a->color[3] + b->color[3]) >> 1;
out->vertexColors[0] = (a->vertexColors[0] + b->vertexColors[0]) >> 1;
out->vertexColors[1] = (a->vertexColors[1] + b->vertexColors[1]) >> 1;
out->vertexColors[2] = (a->vertexColors[2] + b->vertexColors[2]) >> 1;
out->vertexColors[3] = (a->vertexColors[3] + b->vertexColors[3]) >> 1;
}
/*
@ -65,9 +65,9 @@ static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
Transpose
============
*/
static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
static void Transpose( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j;
drawVert_t temp;
srfVert_t temp;
if ( width > height ) {
for ( i = 0 ; i < height ; i++ ) {
@ -109,7 +109,7 @@ MakeMeshNormals
Handles all the complicated wrapping and degenerate cases
=================
*/
static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
static void MakeMeshNormals( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j, k, dist;
vec3_t normal;
vec3_t sum;
@ -117,7 +117,7 @@ static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZ
vec3_t base;
vec3_t delta;
int x, y;
drawVert_t *dv;
srfVert_t *dv;
vec3_t around[8], temp;
qboolean good[8];
qboolean wrapWidth, wrapHeight;
@ -214,14 +214,68 @@ static int neighbors[8][2] = {
}
static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
{
int i, j;
int numTriangles;
int w, h;
srfVert_t *dv;
static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
h = height - 1;
w = width - 1;
numTriangles = 0;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
int v1, v2, v3, v4;
// vertex order to be reckognized as tristrips
v1 = i * width + j + 1;
v2 = v1 - 1;
v3 = v2 + width;
v4 = v3 + 1;
triangles[numTriangles].indexes[0] = v2;
triangles[numTriangles].indexes[1] = v3;
triangles[numTriangles].indexes[2] = v1;
numTriangles++;
triangles[numTriangles].indexes[0] = v1;
triangles[numTriangles].indexes[1] = v3;
triangles[numTriangles].indexes[2] = v4;
numTriangles++;
}
}
R_CalcSurfaceTriangleNeighbors(numTriangles, triangles);
// FIXME: use more elegant way
for(i = 0; i < width; i++)
{
for(j = 0; j < height; j++)
{
dv = &ctrl2[j * width + i];
*dv = ctrl[j][i];
}
}
R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2);
return numTriangles;
}
/*
============
InvertCtrl
============
*/
static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
static void InvertCtrl( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j;
drawVert_t temp;
srfVert_t temp;
for ( i = 0 ; i < height ; i++ ) {
for ( j = 0 ; j < width/2 ; j++ ) {
@ -259,10 +313,10 @@ static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int
PutPointsOnCurve
==================
*/
static void PutPointsOnCurve( drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
int width, int height ) {
int i, j;
drawVert_t prev, next;
srfVert_t prev, next;
for ( i = 0 ; i < width ; i++ ) {
for ( j = 1 ; j < height ; j += 2 ) {
@ -288,14 +342,15 @@ R_CreateSurfaceGridMesh
=================
*/
srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE] ) {
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
int numTriangles, srfTriangle_t triangles[SHADER_MAX_TRIANGLES]) {
int i, j, size;
drawVert_t *vert;
srfVert_t *vert;
vec3_t tmpVec;
srfGridMesh_t *grid;
// copy the results out to a grid
size = (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid );
#ifdef PATCH_STITCHING
grid = /*ri.Hunk_Alloc*/ ri.Malloc( size );
@ -306,6 +361,13 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 );
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
grid->numTriangles = numTriangles;
grid->triangles = ri.Malloc(grid->numTriangles * sizeof(srfTriangle_t));
Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
grid->numVerts = (width * height);
grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t));
#else
grid = ri.Hunk_Alloc( size );
Com_Memset(grid, 0, size);
@ -315,6 +377,13 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->heightLodError = ri.Hunk_Alloc( height * 4 );
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
grid->numTriangles = numTriangles;
grid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
grid->numVerts = (width * height);
grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
#endif
grid->width = width;
@ -349,6 +418,8 @@ R_FreeSurfaceGridMesh
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
ri.Free(grid->widthLodError);
ri.Free(grid->heightLodError);
ri.Free(grid->triangles);
ri.Free(grid->verts);
ri.Free(grid);
}
@ -358,16 +429,18 @@ R_SubdividePatchToGrid
=================
*/
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
int i, j, k, l;
drawVert_t_cleared( prev );
drawVert_t_cleared( next );
drawVert_t_cleared( mid );
srfVert_t_cleared( prev );
srfVert_t_cleared( next );
srfVert_t_cleared( mid );
float len, maxLen;
int dir;
int t;
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
int numTriangles;
static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) {
@ -511,10 +584,13 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
}
#endif
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate normals
MakeMeshNormals( width, height, ctrl );
return R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
}
/*
@ -525,10 +601,12 @@ R_GridInsertColumn
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
int i, j;
int width, height, oldwidth;
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
int numTriangles;
static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
oldwidth = 0;
width = grid->width + 1;
@ -557,6 +635,10 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
}
// put all the aproximating points on the curve
//PutPointsOnCurve( ctrl, width, height );
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate normals
MakeMeshNormals( width, height, ctrl );
@ -565,7 +647,7 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
// free the old grid
R_FreeSurfaceGridMesh(grid);
// create a new grid
grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
grid->lodRadius = lodRadius;
VectorCopy(lodOrigin, grid->lodOrigin);
return grid;
@ -579,10 +661,12 @@ R_GridInsertRow
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
int i, j;
int width, height, oldheight;
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
int numTriangles;
static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
oldheight = 0;
width = grid->width;
@ -611,6 +695,10 @@ srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t
}
// put all the aproximating points on the curve
//PutPointsOnCurve( ctrl, width, height );
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate normals
MakeMeshNormals( width, height, ctrl );
@ -619,7 +707,7 @@ srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t
// free the old grid
R_FreeSurfaceGridMesh(grid);
// create a new grid
grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
grid->lodRadius = lodRadius;
VectorCopy(lodOrigin, grid->lodOrigin);
return grid;

View file

@ -0,0 +1,125 @@
/*
===========================================================================
Copyright (C) 2010 James Canete (use.less01@gmail.com)
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_extramath.c - extra math needed by the renderer not in qmath.c
#include "tr_local.h"
// Some matrix helper functions
// FIXME: do these already exist in ioq3 and I don't know about them?
void Matrix16Zero( matrix_t out )
{
out[ 0] = 0.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
out[ 1] = 0.0f; out[ 5] = 0.0f; out[ 9] = 0.0f; out[13] = 0.0f;
out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 0.0f; out[14] = 0.0f;
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 0.0f;
}
void Matrix16Identity( matrix_t out )
{
out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = 0.0f;
out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = 0.0f;
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void Matrix16Copy( const matrix_t in, matrix_t out )
{
out[ 0] = in[ 0]; out[ 4] = in[ 4]; out[ 8] = in[ 8]; out[12] = in[12];
out[ 1] = in[ 1]; out[ 5] = in[ 5]; out[ 9] = in[ 9]; out[13] = in[13];
out[ 2] = in[ 2]; out[ 6] = in[ 6]; out[10] = in[10]; out[14] = in[14];
out[ 3] = in[ 3]; out[ 7] = in[ 7]; out[11] = in[11]; out[15] = in[15];
}
void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out )
{
out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3];
out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3];
out[ 4] = in1[ 0] * in2[ 4] + in1[ 4] * in2[ 5] + in1[ 8] * in2[ 6] + in1[12] * in2[ 7];
out[ 5] = in1[ 1] * in2[ 4] + in1[ 5] * in2[ 5] + in1[ 9] * in2[ 6] + in1[13] * in2[ 7];
out[ 6] = in1[ 2] * in2[ 4] + in1[ 6] * in2[ 5] + in1[10] * in2[ 6] + in1[14] * in2[ 7];
out[ 7] = in1[ 3] * in2[ 4] + in1[ 7] * in2[ 5] + in1[11] * in2[ 6] + in1[15] * in2[ 7];
out[ 8] = in1[ 0] * in2[ 8] + in1[ 4] * in2[ 9] + in1[ 8] * in2[10] + in1[12] * in2[11];
out[ 9] = in1[ 1] * in2[ 8] + in1[ 5] * in2[ 9] + in1[ 9] * in2[10] + in1[13] * in2[11];
out[10] = in1[ 2] * in2[ 8] + in1[ 6] * in2[ 9] + in1[10] * in2[10] + in1[14] * in2[11];
out[11] = in1[ 3] * in2[ 8] + in1[ 7] * in2[ 9] + in1[11] * in2[10] + in1[15] * in2[11];
out[12] = in1[ 0] * in2[12] + in1[ 4] * in2[13] + in1[ 8] * in2[14] + in1[12] * in2[15];
out[13] = in1[ 1] * in2[12] + in1[ 5] * in2[13] + in1[ 9] * in2[14] + in1[13] * in2[15];
out[14] = in1[ 2] * in2[12] + in1[ 6] * in2[13] + in1[10] * in2[14] + in1[14] * in2[15];
out[15] = in1[ 3] * in2[12] + in1[ 7] * in2[13] + in1[11] * in2[14] + in1[15] * in2[15];
}
void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out )
{
out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3];
out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3];
}
qboolean Matrix16Compare( const matrix_t a, const matrix_t b )
{
return (a[ 0] == b[ 0] && a[ 4] == b[ 4] && a[ 8] == b[ 8] && a[12] == b[12] &&
a[ 1] == b[ 1] && a[ 5] == b[ 5] && a[ 9] == b[ 9] && a[13] == b[13] &&
a[ 2] == b[ 2] && a[ 6] == b[ 6] && a[10] == b[10] && a[14] == b[14] &&
a[ 3] == b[ 3] && a[ 7] == b[ 7] && a[11] == b[11] && a[15] == b[15]);
}
void Matrix16Dump( const matrix_t in )
{
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 0], in[ 4], in[ 8], in[12]);
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 1], in[ 5], in[ 9], in[13]);
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 2], in[ 6], in[10], in[14]);
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 3], in[ 7], in[11], in[15]);
}
void Matrix16Translation( vec3_t vec, matrix_t out )
{
out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = vec[0];
out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = vec[1];
out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = vec[2];
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out )
{
Matrix16Zero(out);
out[ 0] = 2.0f / (right - left);
out[ 5] = 2.0f / (top - bottom);
out[10] = 2.0f / (zfar - znear);
out[12] = -(right + left) / (right - left);
out[13] = -(top + bottom) / (top - bottom);
out[14] = -(zfar + znear) / (zfar - znear);
out[15] = 1.0f;
}
void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c)
{
c[0] = a[0] * (1.0f - lerp) + b[0] * lerp;
c[1] = a[1] * (1.0f - lerp) + b[1] * lerp;
c[2] = a[2] * (1.0f - lerp) + b[2] * lerp;
}

View file

@ -0,0 +1,57 @@
/*
===========================================================================
Copyright (C) 2010 James Canete (use.less01@gmail.com)
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_extramath.h
#ifndef __TR_EXTRAMATH_H__
#define __TR_EXTRAMATH_H__
typedef vec_t matrix_t[16];
void Matrix16Zero( matrix_t out );
void Matrix16Identity( matrix_t out );
void Matrix16Copy( const matrix_t in, matrix_t out );
void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out );
void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out );
qboolean Matrix16Compare(const matrix_t a, const matrix_t b);
void Matrix16Dump( const matrix_t in );
void Matrix16Translation( vec3_t vec, matrix_t out );
void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out );
#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define VectorSet4(v,x,y,z,w) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))
#define DotProduct4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b))
static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
{
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3])
{
return 0;
}
return 1;
}
void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c);
#define SGN(x) (((x) >= 0) ? !!(x) : -1)
#endif

View file

@ -444,6 +444,7 @@ void RB_RenderFlares (void) {
flare_t *f;
flare_t **prev;
qboolean draw;
matrix_t oldmodelview, oldprojection, matrix;
if ( !r_flares->integer ) {
return;
@ -505,14 +506,14 @@ void RB_RenderFlares (void) {
qglDisable (GL_CLIP_PLANE0);
}
qglPushMatrix();
qglLoadIdentity();
qglMatrixMode( GL_PROJECTION );
qglPushMatrix();
qglLoadIdentity();
qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
Matrix16Copy(glState.projection, oldprojection);
Matrix16Copy(glState.modelview, oldmodelview);
Matrix16Identity(matrix);
GL_SetModelviewMatrix(matrix);
Matrix16Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
-99999, 99999 );
-99999, 99999, matrix );
GL_SetProjectionMatrix(matrix);
for ( f = r_activeFlares ; f ; f = f->next ) {
if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
@ -522,8 +523,7 @@ void RB_RenderFlares (void) {
}
}
qglPopMatrix();
qglMatrixMode( GL_MODELVIEW );
qglPopMatrix();
GL_SetProjectionMatrix(oldprojection);
GL_SetModelviewMatrix(oldmodelview);
}

File diff suppressed because it is too large Load diff

View file

@ -741,16 +741,16 @@ done:
if (mipmap)
{
if ( textureFilterAnisotropic )
if ( glRefConfig.textureFilterAnisotropic )
qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
(GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) );
(GLint)Com_Clamp( 1, glRefConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
if ( textureFilterAnisotropic )
if ( glRefConfig.textureFilterAnisotropic )
qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

View file

@ -24,8 +24,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
glconfig_t glConfig;
qboolean textureFilterAnisotropic = qfalse;
int maxAnisotropy = 0;
glRefConfig_t glRefConfig;
float displayAspect = 0.0f;
glstate_t glState;
@ -92,6 +93,13 @@ cvar_t *r_ext_texture_env_add;
cvar_t *r_ext_texture_filter_anisotropic;
cvar_t *r_ext_max_anisotropy;
cvar_t *r_arb_vertex_buffer_object;
cvar_t *r_arb_shader_objects;
cvar_t *r_ext_multi_draw_arrays;
cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces;
cvar_t *r_ignoreGLErrors;
cvar_t *r_logFile;
@ -222,7 +230,7 @@ static void InitOpenGL( void )
GL_CheckErrors
==================
*/
void GL_CheckErrors( void ) {
void GL_CheckErrs( char *file, int line ) {
int err;
char s[64];
@ -257,7 +265,7 @@ void GL_CheckErrors( void ) {
break;
}
ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s );
ri.Error( ERR_FATAL, "GL_CheckErrors: %s in %s at line %d", s , file, line);
}
@ -772,6 +780,22 @@ void GL_SetDefaultState( void )
//
glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
if (glRefConfig.glsl)
{
glState.vertexAttribsState = 0;
glState.vertexAttribPointersSet = 0;
glState.currentProgram = 0;
qglUseProgramObjectARB(0);
}
if (glRefConfig.vertexBufferObject)
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL;
glState.currentIBO = NULL;
}
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
qglDepthMask( GL_TRUE );
qglDisable( GL_DEPTH_TEST );
@ -891,6 +915,9 @@ void R_Register( void )
r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_buffer_object = ri.Cvar_Get( "r_arb_vertex_buffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_shader_objects = ri.Cvar_Get( "r_arb_shader_objects", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_multi_draw_arrays = ri.Cvar_Get( "r_ext_multi_draw_arrays", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
"0", CVAR_ARCHIVE | CVAR_LATCH );
@ -966,6 +993,8 @@ void R_Register( void )
r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
r_mergeMultidraws = ri.Cvar_Get("r_mergeMultidraws", "1", CVAR_ARCHIVE);
r_mergeLeafSurfaces = ri.Cvar_Get("r_mergeLeafSurfaces", "1", CVAR_ARCHIVE);
//
// temporary variables that can change at any time
@ -1119,8 +1148,18 @@ void R_Init( void ) {
InitOpenGL();
if (glRefConfig.glsl)
{
GLSL_InitGPUShaders();
}
R_InitImages();
if (glRefConfig.vertexBufferObject)
{
R_InitVBOs();
}
R_InitShaders();
R_InitSkins();
@ -1161,6 +1200,14 @@ void RE_Shutdown( qboolean destroyWindow ) {
R_SyncRenderThread();
R_ShutdownCommandBuffers();
R_DeleteTextures();
if (glRefConfig.vertexBufferObject)
{
R_ShutdownVBOs();
}
if (glRefConfig.glsl)
{
GLSL_ShutdownGPUShaders();
}
}
R_DoneFreeType();

View file

@ -92,7 +92,7 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
// set the dlight bits in all the surfaces
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
surf = bmodel->firstSurface + i;
surf = tr.world->surfaces + bmodel->firstSurface + i;
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;

File diff suppressed because it is too large Load diff

View file

@ -43,6 +43,97 @@ refimport_t ri;
// point at this for their sorting surface
surfaceType_t entitySurface = SF_ENTITY;
/*
=================
R_FindSurfaceTriangleWithEdge
Tr3B - recoded from Q2E
=================
*/
static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore)
{
srfTriangle_t *tri;
int count, match;
int i;
count = 0;
match = -1;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
if((tri->indexes[0] == start && tri->indexes[1] == end) ||
(tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end))
{
if(i != ignore)
{
match = i;
}
count++;
}
else if((tri->indexes[1] == start && tri->indexes[0] == end) ||
(tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end))
{
count++;
}
}
// detect edges shared by three triangles and make them seams
if(count > 2)
{
match = -1;
}
return match;
}
/*
=================
R_CalcSurfaceTriangleNeighbors
Tr3B - recoded from Q2E
=================
*/
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i);
tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i);
tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i);
}
}
/*
=================
R_CalcSurfaceTrianglePlanes
=================
*/
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
float *v1, *v2, *v3;
vec3_t d1, d2;
v1 = verts[tri->indexes[0]].xyz;
v2 = verts[tri->indexes[1]].xyz;
v3 = verts[tri->indexes[2]].xyz;
VectorSubtract(v2, v1, d1);
VectorSubtract(v3, v1, d2);
CrossProduct(d2, d1, tri->plane);
tri->plane[3] = DotProduct(tri->plane, v1);
}
}
/*
=================
R_CullLocalBox
@ -50,7 +141,8 @@ R_CullLocalBox
Returns CULL_IN, CULL_CLIP, or CULL_OUT
=================
*/
int R_CullLocalBox (vec3_t bounds[2]) {
int R_CullLocalBox(vec3_t localBounds[2]) {
#if 0
int i, j;
vec3_t transformed[8];
float dists[8];
@ -104,6 +196,75 @@ int R_CullLocalBox (vec3_t bounds[2]) {
}
return CULL_CLIP; // partially clipped
#else
int j;
vec3_t transformed;
vec3_t v;
vec3_t worldBounds[2];
if(r_nocull->integer)
{
return CULL_CLIP;
}
// transform into world space
ClearBounds(worldBounds[0], worldBounds[1]);
for(j = 0; j < 8; j++)
{
v[0] = localBounds[j & 1][0];
v[1] = localBounds[(j >> 1) & 1][1];
v[2] = localBounds[(j >> 2) & 1][2];
R_LocalPointToWorld(v, transformed);
AddPointToBounds(transformed, worldBounds[0], worldBounds[1]);
}
return R_CullBox(worldBounds);
#endif
}
/*
=================
R_CullBox
Returns CULL_IN, CULL_CLIP, or CULL_OUT
=================
*/
int R_CullBox(vec3_t worldBounds[2]) {
int i;
cplane_t *frust;
qboolean anyClip;
int r;
// check against frustum planes
anyClip = qfalse;
for(i = 0; i < 4 /*FRUSTUM_PLANES*/; i++)
{
frust = &tr.viewParms.frustum[i];
r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], frust);
if(r == 2)
{
// completely outside frustum
return CULL_OUT;
}
if(r == 3)
{
anyClip = qtrue;
}
}
if(!anyClip)
{
// completely inside frustum
return CULL_IN;
}
// partially clipped
return CULL_CLIP;
}
/*
@ -578,6 +739,40 @@ void R_SetupProjectionZ(viewParms_t *dest)
dest->projectionMatrix[6] = 0;
dest->projectionMatrix[10] = -( zFar + zNear ) / depth;
dest->projectionMatrix[14] = -2 * zFar * zNear / depth;
if (dest->isPortal)
{
float plane[4];
float plane2[4];
vec4_t q, c;
// transform portal plane into camera space
plane[0] = dest->portalPlane.normal[0];
plane[1] = dest->portalPlane.normal[1];
plane[2] = dest->portalPlane.normal[2];
plane[3] = dest->portalPlane.dist;
plane2[0] = -DotProduct (dest->or.axis[1], plane);
plane2[1] = DotProduct (dest->or.axis[2], plane);
plane2[2] = -DotProduct (dest->or.axis[0], plane);
plane2[3] = DotProduct (plane, dest->or.origin) - plane[3];
// Lengyel, Eric. “Modifying the Projection Matrix to Perform Oblique Near-plane Clipping”.
// Terathon Software 3D Graphics Library, 2004. http://www.terathon.com/code/oblique.html
q[0] = (SGN(plane2[0]) + dest->projectionMatrix[8]) / dest->projectionMatrix[0];
q[1] = (SGN(plane2[1]) + dest->projectionMatrix[9]) / dest->projectionMatrix[5];
q[2] = -1.0f;
q[3] = (1.0f + dest->projectionMatrix[10]) / dest->projectionMatrix[14];
VectorScale4(plane2, 2.0f / DotProduct4(plane2, q), c);
dest->projectionMatrix[2] = c[0];
dest->projectionMatrix[6] = c[1];
dest->projectionMatrix[10] = c[2] + 1.0f;
dest->projectionMatrix[14] = c[3];
}
}
/*
@ -622,7 +817,7 @@ R_PlaneForSurface
void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
srfTriangles_t *tri;
srfPoly_t *poly;
drawVert_t *v1, *v2, *v3;
srfVert_t *v1, *v2, *v3;
vec4_t plane4;
if (!surfType) {
@ -636,9 +831,9 @@ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
return;
case SF_TRIANGLES:
tri = (srfTriangles_t *)surfType;
v1 = tri->verts + tri->indexes[0];
v2 = tri->verts + tri->indexes[1];
v3 = tri->verts + tri->indexes[2];
v1 = tri->verts + tri->triangles[0].indexes[0];
v2 = tri->verts + tri->triangles[0].indexes[1];
v3 = tri->verts + tri->triangles[0].indexes[2];
PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz );
VectorCopy( plane4, plane->normal );
plane->dist = plane4[3];
@ -1314,6 +1509,8 @@ R_DebugPolygon
================
*/
void R_DebugPolygon( int color, int numPoints, float *points ) {
// FIXME: implement this
#if 0
int i;
GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
@ -1337,6 +1534,7 @@ void R_DebugPolygon( int color, int numPoints, float *points ) {
}
qglEnd();
qglDepthRange( 0, 1 );
#endif
}
/*

View file

@ -134,7 +134,8 @@ R_BoxSurfaces_r
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {
int s, c;
msurface_t *surf, **mark;
msurface_t *surf;
int *mark;
// do the tail recursion in a loop
while ( node->contents == -1 ) {
@ -150,37 +151,39 @@ void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **li
}
// add the individual surfaces
mark = node->firstmarksurface;
mark = tr.world->marksurfaces + node->firstmarksurface;
c = node->nummarksurfaces;
while (c--) {
int *surfViewCount;
//
if (*listlength >= listsize) break;
//
surf = *mark;
surfViewCount = &tr.world->surfacesViewCount[*mark];
surf = tr.world->surfaces + *mark;
// check if the surface has NOIMPACT or NOMARKS set
if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
surf->viewCount = tr.viewCount;
*surfViewCount = tr.viewCount;
}
// extra check for surfaces to avoid list overflows
else if (*(surf->data) == SF_FACE) {
// the face plane should go through the box
s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
s = BoxOnPlaneSide( mins, maxs, &surf->cullinfo.plane );
if (s == 1 || s == 2) {
surf->viewCount = tr.viewCount;
} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) {
*surfViewCount = tr.viewCount;
} else if (DotProduct(surf->cullinfo.plane.normal, dir) > -0.5) {
// don't add faces that make sharp angles with the projection direction
surf->viewCount = tr.viewCount;
*surfViewCount = tr.viewCount;
}
}
else if (*(surfaceType_t *) (surf->data) != SF_GRID &&
*(surfaceType_t *) (surf->data) != SF_TRIANGLES)
surf->viewCount = tr.viewCount;
else if (*(surf->data) != SF_GRID &&
*(surf->data) != SF_TRIANGLES)
*surfViewCount = tr.viewCount;
// check the viewCount because the surface may have
// already been added if it spans multiple leafs
if (surf->viewCount != tr.viewCount) {
surf->viewCount = tr.viewCount;
list[*listlength] = (surfaceType_t *) surf->data;
if (*surfViewCount != tr.viewCount) {
*surfViewCount = tr.viewCount;
list[*listlength] = surf->data;
(*listlength)++;
}
mark++;
@ -266,11 +269,11 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
int numClipPoints;
float *v;
srfGridMesh_t *cv;
drawVert_t *dv;
srfTriangle_t *tri;
srfVert_t *dv;
vec3_t normal;
vec3_t projectionDir;
vec3_t v1, v2;
int *indexes;
//increment view count for double check prevention
tr.viewCount++;
@ -407,11 +410,12 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
continue;
}
indexes = (int *)( (byte *)surf + surf->ofsIndices );
for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
for ( j = 0 ; j < 3 ; j++ ) {
v = surf->points[0] + VERTEXSIZE * indexes[k+j];;
VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
{
for(j = 0; j < 3; j++)
{
v = surf->verts[tri->indexes[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
}
// add the fragments of this face
@ -429,12 +433,12 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
srfTriangles_t *surf = (srfTriangles_t *) surfaces[i];
for (k = 0; k < surf->numIndexes; k += 3)
for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
{
for(j = 0; j < 3; j++)
{
v = surf->verts[surf->indexes[k + j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->verts[surf->indexes[k + j]].normal, clipPoints[0][j]);
v = surf->verts[tri->indexes[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->verts[tri->indexes[j]].normal, clipPoints[0][j]);
}
// add the fragments of this face

View file

@ -75,14 +75,14 @@ static float ProjectRadius( float r, vec3_t location )
R_CullModel
=============
*/
static int R_CullModel( md3Header_t *header, trRefEntity_t *ent ) {
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
vec3_t bounds[2];
md3Frame_t *oldFrame, *newFrame;
mdvFrame_t *oldFrame, *newFrame;
int i;
// compute frame pointers
newFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
oldFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.oldframe;
newFrame = model->frames + ent->e.frame;
oldFrame = model->frames + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
@ -167,7 +167,7 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
float radius;
float flod, lodscale;
float projectedRadius;
md3Frame_t *frame;
mdvFrame_t *frame;
#ifdef RAVENMD4
mdrHeader_t *mdr;
mdrFrame_t *mdrframe;
@ -200,7 +200,8 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
else
#endif
{
frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame = tr.currentModel->mdv[0]->frames;
frame += ent->e.frame;
@ -248,10 +249,10 @@ R_ComputeFogNum
=================
*/
int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
int i, j;
fog_t *fog;
md3Frame_t *md3Frame;
mdvFrame_t *mdvFrame;
vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
@ -259,15 +260,15 @@ int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
}
// FIXME: non-normalized axis issues
md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin );
mdvFrame = model->frames + ent->e.frame;
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - md3Frame->radius >= fog->bounds[1][j] ) {
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
break;
}
if ( localOrigin[j] + md3Frame->radius <= fog->bounds[0][j] ) {
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
break;
}
}
@ -287,9 +288,8 @@ R_AddMD3Surfaces
*/
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i;
md3Header_t *header = NULL;
md3Surface_t *surface = NULL;
md3Shader_t *md3Shader = NULL;
mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL;
shader_t *shader = NULL;
int cull;
int lod;
@ -300,8 +300,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->md3[0]->numFrames;
ent->e.oldframe %= tr.currentModel->md3[0]->numFrames;
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
}
//
@ -310,9 +310,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ( (ent->e.frame >= tr.currentModel->md3[0]->numFrames)
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->md3[0]->numFrames)
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.oldframe < 0) ) {
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame,
@ -326,13 +326,13 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
//
lod = R_ComputeLOD( ent );
header = tr.currentModel->md3[lod];
model = tr.currentModel->mdv[lod];
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_CullModel ( header, ent );
cull = R_CullModel ( model, ent );
if ( cull == CULL_OUT ) {
return;
}
@ -347,13 +347,13 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
//
// see if we are in a fog volume
//
fogNum = R_ComputeFogNum( header, ent );
fogNum = R_ComputeFogNum( model, ent );
//
// draw all surfaces
//
surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces );
for ( i = 0 ; i < header->numSurfaces ; i++ ) {
surface = model->surfaces;
for ( i = 0 ; i < model->numSurfaces ; i++ ) {
if ( ent->e.customShader ) {
shader = R_GetShaderByHandle( ent->e.customShader );
@ -378,15 +378,29 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
else if (shader->defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
}
} else if ( surface->numShaders <= 0 ) {
shader = tr.defaultShader;
//} else if ( surface->numShaders <= 0 ) {
//shader = tr.defaultShader;
} else {
md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
md3Shader += ent->e.skinNum % surface->numShaders;
shader = tr.shaders[ md3Shader->shaderIndex ];
//md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
//md3Shader += ent->e.skinNum % surface->numShaders;
//shader = tr.shaders[ md3Shader->shaderIndex ];
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
}
if (model->numVBOSurfaces && glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer)
{
srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i];
// don't add third_person objects if not viewing through a portal
if(!personalModel)
{
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse );
}
}
else
{
// we will add shadows even if the main object isn't visible in the view
// stencil shadows can't do personal models unless I polyhedron clip
@ -410,8 +424,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
if ( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
}
}
surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
surface++;
}
}

View file

@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name );
static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, int bufferSize, const char *modName );
static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name );
#ifdef RAVENMD4
static qboolean R_LoadMDR (model_t *mod, void *buffer, int filesize, const char *name );
@ -182,12 +182,14 @@ qhandle_t RE_RegisterModel( const char *name ) {
fext = defex;
for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) {
int bufferSize;
if ( lod )
Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
else
Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
ri.FS_ReadFile( namebuf, &buf.v );
bufferSize = ri.FS_ReadFile( namebuf, &buf.v );
if ( !buf.u ) {
continue;
}
@ -203,7 +205,7 @@ qhandle_t RE_RegisterModel( const char *name ) {
goto fail;
}
loaded = R_LoadMD3( mod, lod, buf.u, name );
loaded = R_LoadMD3( mod, lod, buf.u, bufferSize, name );
}
ri.FS_FreeFile (buf.v);
@ -231,7 +233,7 @@ qhandle_t RE_RegisterModel( const char *name ) {
// loaded, in case the user changes r_lodbias on the fly
for ( lod-- ; lod >= 0 ; lod-- ) {
mod->numLods++;
mod->md3[lod] = mod->md3[lod+1];
mod->mdv[lod] = mod->mdv[lod+1];
}
return mod->index;
@ -255,152 +257,307 @@ fail:
R_LoadMD3
=================
*/
static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) {
static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, const char *modName)
{
int i, j;
md3Header_t *pinmodel;
md3Frame_t *frame;
md3Surface_t *surf;
md3Shader_t *shader;
md3Triangle_t *tri;
md3St_t *st;
md3XyzNormal_t *xyz;
md3Tag_t *tag;
md3Header_t *md3Model;
md3Frame_t *md3Frame;
md3Surface_t *md3Surf;
md3Shader_t *md3Shader;
md3Triangle_t *md3Tri;
md3St_t *md3st;
md3XyzNormal_t *md3xyz;
md3Tag_t *md3Tag;
mdvModel_t *mdvModel;
mdvFrame_t *frame;
mdvSurface_t *surf;//, *surface;
int *shaderIndex;
srfTriangle_t *tri;
mdvVertex_t *v;
mdvSt_t *st;
mdvTag_t *tag;
mdvTagName_t *tagName;
int version;
int size;
pinmodel = (md3Header_t *)buffer;
md3Model = (md3Header_t *) buffer;
version = LittleLong (pinmodel->version);
if (version != MD3_VERSION) {
ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n",
mod_name, version, MD3_VERSION);
version = LittleLong(md3Model->version);
if(version != MD3_VERSION)
{
ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MD3_VERSION);
return qfalse;
}
mod->type = MOD_MESH;
size = LittleLong(pinmodel->ofsEnd);
size = LittleLong(md3Model->ofsEnd);
mod->dataSize += size;
mod->md3[lod] = ri.Hunk_Alloc( size, h_low );
mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low);
Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) );
// Com_Memcpy(mod->md3[lod], buffer, LittleLong(md3Model->ofsEnd));
LL(mod->md3[lod]->ident);
LL(mod->md3[lod]->version);
LL(mod->md3[lod]->numFrames);
LL(mod->md3[lod]->numTags);
LL(mod->md3[lod]->numSurfaces);
LL(mod->md3[lod]->ofsFrames);
LL(mod->md3[lod]->ofsTags);
LL(mod->md3[lod]->ofsSurfaces);
LL(mod->md3[lod]->ofsEnd);
LL(md3Model->ident);
LL(md3Model->version);
LL(md3Model->numFrames);
LL(md3Model->numTags);
LL(md3Model->numSurfaces);
LL(md3Model->ofsFrames);
LL(md3Model->ofsTags);
LL(md3Model->ofsSurfaces);
LL(md3Model->ofsEnd);
if ( mod->md3[lod]->numFrames < 1 ) {
ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name );
if(md3Model->numFrames < 1)
{
ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has no frames\n", modName);
return qfalse;
}
// swap all the frames
frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames );
for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) {
frame->radius = LittleFloat( frame->radius );
for ( j = 0 ; j < 3 ; j++ ) {
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
mdvModel->numFrames = md3Model->numFrames;
mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low);
md3Frame = (md3Frame_t *) ((byte *) md3Model + md3Model->ofsFrames);
for(i = 0; i < md3Model->numFrames; i++, frame++, md3Frame++)
{
frame->radius = LittleFloat(md3Frame->radius);
for(j = 0; j < 3; j++)
{
frame->bounds[0][j] = LittleFloat(md3Frame->bounds[0][j]);
frame->bounds[1][j] = LittleFloat(md3Frame->bounds[1][j]);
frame->localOrigin[j] = LittleFloat(md3Frame->localOrigin[j]);
}
}
// swap all the tags
tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags );
for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) {
for ( j = 0 ; j < 3 ; j++ ) {
tag->origin[j] = LittleFloat( tag->origin[j] );
tag->axis[0][j] = LittleFloat( tag->axis[0][j] );
tag->axis[1][j] = LittleFloat( tag->axis[1][j] );
tag->axis[2][j] = LittleFloat( tag->axis[2][j] );
mdvModel->numTags = md3Model->numTags;
mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low);
md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
for(i = 0; i < md3Model->numTags * md3Model->numFrames; i++, tag++, md3Tag++)
{
for(j = 0; j < 3; j++)
{
tag->origin[j] = LittleFloat(md3Tag->origin[j]);
tag->axis[0][j] = LittleFloat(md3Tag->axis[0][j]);
tag->axis[1][j] = LittleFloat(md3Tag->axis[1][j]);
tag->axis[2][j] = LittleFloat(md3Tag->axis[2][j]);
}
}
mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low);
md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
for(i = 0; i < md3Model->numTags; i++, tagName++, md3Tag++)
{
Q_strncpyz(tagName->name, md3Tag->name, sizeof(tagName->name));
}
// swap all the surfaces
surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces );
for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) {
mdvModel->numSurfaces = md3Model->numSurfaces;
mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low);
LL(surf->ident);
LL(surf->flags);
LL(surf->numFrames);
LL(surf->numShaders);
LL(surf->numTriangles);
LL(surf->ofsTriangles);
LL(surf->numVerts);
LL(surf->ofsShaders);
LL(surf->ofsSt);
LL(surf->ofsXyzNormals);
LL(surf->ofsEnd);
md3Surf = (md3Surface_t *) ((byte *) md3Model + md3Model->ofsSurfaces);
for(i = 0; i < md3Model->numSurfaces; i++)
{
LL(md3Surf->ident);
LL(md3Surf->flags);
LL(md3Surf->numFrames);
LL(md3Surf->numShaders);
LL(md3Surf->numTriangles);
LL(md3Surf->ofsTriangles);
LL(md3Surf->numVerts);
LL(md3Surf->ofsShaders);
LL(md3Surf->ofsSt);
LL(md3Surf->ofsXyzNormals);
LL(md3Surf->ofsEnd);
if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
if(md3Surf->numVerts > SHADER_MAX_VERTEXES)
{
ri.Error(ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
modName, SHADER_MAX_VERTEXES, md3Surf->numVerts);
}
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
if(md3Surf->numTriangles * 3 > SHADER_MAX_INDEXES)
{
ri.Error(ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
modName, SHADER_MAX_INDEXES / 3, md3Surf->numTriangles);
}
// change to surface identifier
surf->ident = SF_MD3;
surf->surfaceType = SF_MDV;
// give pointer to model for Tess_SurfaceMDX
surf->model = mdvModel;
// copy surface name
Q_strncpyz(surf->name, md3Surf->name, sizeof(surf->name));
// lowercase the surface name so skin compares are faster
Q_strlwr( surf->name );
Q_strlwr(surf->name);
// strip off a trailing _1 or _2
// this is a crutch for q3data being a mess
j = strlen( surf->name );
if ( j > 2 && surf->name[j-2] == '_' ) {
surf->name[j-2] = 0;
j = strlen(surf->name);
if(j > 2 && surf->name[j - 2] == '_')
{
surf->name[j - 2] = 0;
}
// register the shaders
shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
surf->numShaderIndexes = md3Surf->numShaders;
surf->shaderIndexes = shaderIndex = ri.Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low);
md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders);
for(j = 0; j < md3Surf->numShaders; j++, shaderIndex++, md3Shader++)
{
shader_t *sh;
sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue );
if ( sh->defaultShader ) {
shader->shaderIndex = 0;
} else {
shader->shaderIndex = sh->index;
sh = R_FindShader(md3Shader->name, LIGHTMAP_NONE, qtrue);
if(sh->defaultShader)
{
*shaderIndex = 0;
}
else
{
*shaderIndex = sh->index;
}
}
// swap all the triangles
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
LL(tri->indexes[0]);
LL(tri->indexes[1]);
LL(tri->indexes[2]);
surf->numTriangles = md3Surf->numTriangles;
surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * md3Surf->numTriangles, h_low);
md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles);
for(j = 0; j < md3Surf->numTriangles; j++, tri++, md3Tri++)
{
tri->indexes[0] = LittleLong(md3Tri->indexes[0]);
tri->indexes[1] = LittleLong(md3Tri->indexes[1]);
tri->indexes[2] = LittleLong(md3Tri->indexes[2]);
}
R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);
// swap all the XyzNormals
surf->numVerts = md3Surf->numVerts;
surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low);
md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals);
for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++)
{
unsigned lat, lng;
unsigned short normal;
v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
v->xyz[2] = LittleShort(md3xyz->xyz[2]) * MD3_XYZ_SCALE;
normal = LittleShort(md3xyz->normal);
lat = ( normal >> 8 ) & 0xff;
lng = ( normal & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
v->normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
v->normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
}
// swap all the ST
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
st->st[0] = LittleFloat( st->st[0] );
st->st[1] = LittleFloat( st->st[1] );
}
surf->st = st = ri.Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low);
// swap all the XyzNormals
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
md3st = (md3St_t *) ((byte *) md3Surf + md3Surf->ofsSt);
for(j = 0; j < md3Surf->numVerts; j++, md3st++, st++)
{
xyz->xyz[0] = LittleShort( xyz->xyz[0] );
xyz->xyz[1] = LittleShort( xyz->xyz[1] );
xyz->xyz[2] = LittleShort( xyz->xyz[2] );
xyz->normal = LittleShort( xyz->normal );
st->st[0] = LittleFloat(md3st->st[0]);
st->st[1] = LittleFloat(md3st->st[1]);
}
// find the next surface
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
md3Surf = (md3Surface_t *) ((byte *) md3Surf + md3Surf->ofsEnd);
surf++;
}
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer)
{
srfVBOMDVMesh_t *vboSurf;
mdvModel->numVBOSurfaces = mdvModel->numSurfaces;
mdvModel->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low);
vboSurf = mdvModel->vboSurfaces;
surf = mdvModel->surfaces;
for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++)
{
vec3_t *verts;
vec3_t *normals;
vec2_t *texcoords;
byte *data;
int dataSize;
int ofs_xyz, ofs_normal, ofs_st;
dataSize = 0;
ofs_xyz = dataSize;
dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts);
ofs_normal = dataSize;
dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts);
ofs_st = dataSize;
dataSize += surf->numVerts * sizeof(*texcoords);
data = ri.Malloc(dataSize);
verts = (void *)(data + ofs_xyz);
normals = (void *)(data + ofs_normal);
texcoords = (void *)(data + ofs_st);
v = surf->verts;
for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
{
VectorCopy(v->xyz, verts[j]);
VectorCopy(v->normal, normals[j]);
}
st = surf->st;
for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
texcoords[j][0] = st->st[0];
texcoords[j][1] = st->st[1];
}
vboSurf->surfaceType = SF_VBO_MDVMESH;
vboSurf->mdvModel = mdvModel;
vboSurf->mdvSurface = surf;
vboSurf->numIndexes = surf->numTriangles * 3;
vboSurf->numVerts = surf->numVerts;
vboSurf->vbo = R_CreateVBO(va("staticMD3Mesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC);
vboSurf->vbo->ofs_xyz = ofs_xyz;
vboSurf->vbo->ofs_normal = ofs_normal;
vboSurf->vbo->ofs_st = ofs_st;
vboSurf->vbo->stride_xyz = sizeof(*verts);
vboSurf->vbo->stride_normal = sizeof(*normals);
vboSurf->vbo->stride_st = sizeof(*st);
vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts;
vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts;
ri.Free(data);
vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC);
}
}
return qtrue;
@ -915,7 +1072,9 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) {
R_SyncRenderThread();
tr.viewCluster = -1; // force markleafs to regenerate
tr.visIndex = 0;
memset(tr.visClusters, -2, sizeof(tr.visClusters)); // force markleafs to regenerate
R_ClearFlares();
RE_ClearScene();
@ -961,7 +1120,7 @@ void R_Modellist_f( void ) {
mod = tr.models[i];
lods = 1;
for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) {
if ( mod->md3[j] && mod->md3[j] != mod->md3[j-1] ) {
if ( mod->mdv[j] && mod->mdv[j] != mod->mdv[j-1] ) {
lods++;
}
}
@ -986,19 +1145,23 @@ void R_Modellist_f( void ) {
R_GetTag
================
*/
static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) {
md3Tag_t *tag;
static mdvTag_t *R_GetTag( mdvModel_t *mod, int frame, const char *_tagName ) {
int i;
mdvTag_t *tag;
mdvTagName_t *tagName;
if ( frame >= mod->numFrames ) {
// it is possible to have a bad frame while changing models, so don't error
frame = mod->numFrames - 1;
}
tag = (md3Tag_t *)((byte *)mod + mod->ofsTags) + frame * mod->numTags;
for ( i = 0 ; i < mod->numTags ; i++, tag++ ) {
if ( !strcmp( tag->name, tagName ) ) {
return tag; // found it
tag = mod->tags + frame * mod->numTags;
tagName = mod->tagNames;
for(i = 0; i < mod->numTags; i++, tag++, tagName++)
{
if(!strcmp(tagName->name, _tagName))
{
return tag;
}
}
@ -1058,7 +1221,7 @@ R_LerpTag
*/
int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
float frac, const char *tagName ) {
md3Tag_t *start, *end;
mdvTag_t *start, *end;
#ifdef RAVENMD4
md3Tag_t start_space, end_space;
#endif
@ -1067,7 +1230,7 @@ int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFram
model_t *model;
model = R_GetModelByHandle( handle );
if ( !model->md3[0] )
if ( !model->mdv[0] )
{
#ifdef RAVENMD4
if(model->md4)
@ -1089,8 +1252,8 @@ int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFram
}
else
{
start = R_GetTag( model->md3[0], startFrame, tagName );
end = R_GetTag( model->md3[0], endFrame, tagName );
start = R_GetTag( model->mdv[0], startFrame, tagName );
end = R_GetTag( model->mdv[0], endFrame, tagName );
if ( !start || !end ) {
AxisClear( tag->axis );
VectorClear( tag->origin );
@ -1121,8 +1284,8 @@ R_ModelBounds
*/
void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
model_t *model;
md3Header_t *header;
md3Frame_t *frame;
mdvModel_t *mdvModel;
mdvFrame_t *frame;
model = R_GetModelByHandle( handle );
@ -1132,15 +1295,15 @@ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
return;
}
if ( !model->md3[0] ) {
if ( !model->mdv[0] ) {
VectorClear( mins );
VectorClear( maxs );
return;
}
header = model->md3[0];
mdvModel = model->mdv[0];
frame = (md3Frame_t *)( (byte *)header + header->ofsFrames );
frame = mdvModel->frames;
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );

View file

@ -130,8 +130,10 @@ void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts
}
if ( !hShader ) {
ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
return;
// This isn't a useful warning, and an hShader of zero isn't a null shader, it's
// the default shader.
//ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
//return;
}
for ( j = 0; j < numPolys; j++ ) {

File diff suppressed because it is too large Load diff

View file

@ -57,7 +57,7 @@ static float *TableForFunc( genFunc_t func )
**
** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
*/
static float EvalWaveForm( const waveForm_t *wf )
float EvalWaveForm( const waveForm_t *wf )
{
float *table;
@ -66,7 +66,7 @@ static float EvalWaveForm( const waveForm_t *wf )
return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency );
}
static float EvalWaveFormClamped( const waveForm_t *wf )
float EvalWaveFormClamped( const waveForm_t *wf )
{
float glow = EvalWaveForm( wf );
@ -104,6 +104,24 @@ void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix )
{
float p;
texModInfo_t tmi;
p = 1.0f / EvalWaveForm( wf );
tmi.matrix[0][0] = p;
tmi.matrix[1][0] = 0;
tmi.translate[0] = 0.5f - 0.5f * p;
tmi.matrix[0][1] = 0;
tmi.matrix[1][1] = p;
tmi.translate[1] = 0.5f - 0.5f * p;
RB_CalcTransformTexMatrix( &tmi, matrix );
}
/*
====================================================================
@ -305,6 +323,7 @@ void DeformText( const char *text ) {
// clear the shader indexes
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
color[0] = color[1] = color[2] = color[3] = 255;
@ -368,6 +387,7 @@ static void AutospriteDeform( void ) {
oldVerts = tess.numVertexes;
tess.numVertexes = 0;
tess.numIndexes = 0;
tess.firstIndex = 0;
if ( backEnd.currentEntity != &tr.worldEntity ) {
GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir );
@ -542,6 +562,15 @@ void RB_DeformTessGeometry( void ) {
int i;
deformStage_t *ds;
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
if(!ShaderRequiresCPUDeforms(tess.shader))
{
// we don't need the following CPU deforms
return;
}
}
for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) {
ds = &tess.shader->deforms[ i ];
@ -934,6 +963,21 @@ void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
}
}
void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix )
{
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
// bit of a hack here, hide amplitude and now in the matrix
// the vertex program will extract them and perform a turbulent pass last if it's nonzero
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcScaleTexCoords
*/
@ -948,6 +992,14 @@ void RB_CalcScaleTexCoords( const float scale[2], float *st )
}
}
void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
{
matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcScrollTexCoords
*/
@ -972,6 +1024,26 @@ void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
}
}
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
{
float timeScale = tess.shaderTime;
float adjustedScrollS, adjustedScrollT;
adjustedScrollS = scrollSpeed[0] * timeScale;
adjustedScrollT = scrollSpeed[1] * timeScale;
// clamp so coordinates don't continuously get larger, causing problems
// with hardware limits
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcTransformTexCoords
*/
@ -989,6 +1061,14 @@ void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st )
}
}
void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix )
{
matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f;
matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcRotateTexCoords
*/
@ -1017,6 +1097,31 @@ void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue;
tmi.matrix[1][0] = -sinValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexMatrix( &tmi, matrix );
}

View file

@ -1551,6 +1551,7 @@ static qboolean ParseShader( char **text )
else if ( !Q_stricmp(token, "portal") )
{
shader.sort = SS_PORTAL;
shader.isPortal = qtrue;
continue;
}
// skyparms <cloudheight> <outerbox> <innerbox>
@ -1634,6 +1635,11 @@ static void ComputeStageIteratorFunc( void )
{
shader.optimalStageIteratorFunc = RB_StageIteratorGeneric;
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
shader.optimalStageIteratorFunc = RB_StageIteratorGenericVBO;
}
//
// see if this should go into the sky path
//
@ -1648,6 +1654,12 @@ static void ComputeStageIteratorFunc( void )
return;
}
if ( glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer )
{
// VBOs don't support the fast path!
return;
}
//
// see if this can go into the vertex lit fast path
//
@ -1704,6 +1716,133 @@ done:
return;
}
/*
===================
ComputeVertexAttribs
Check which vertex attributes we only need, so we
don't need to submit/copy all of them.
===================
*/
static void ComputeVertexAttribs()
{
int i, stage;
shader.vertexAttribs = ATTR_POSITION;
// portals always need normals, for SurfIsOffscreen()
if (shader.isPortal)
{
shader.vertexAttribs |= ATTR_NORMAL;
}
if (shader.defaultShader)
{
shader.vertexAttribs |= ATTR_TEXCOORD;
return;
}
if(shader.numDeforms)
{
for ( i = 0; i < shader.numDeforms; i++)
{
deformStage_t *ds = &shader.deforms[i];
switch (ds->deformation)
{
case DEFORM_BULGE:
shader.vertexAttribs |= ATTR_NORMAL | ATTR_TEXCOORD;
break;
case DEFORM_AUTOSPRITE:
shader.vertexAttribs |= ATTR_NORMAL | ATTR_COLOR;
break;
case DEFORM_WAVE:
case DEFORM_NORMALS:
case DEFORM_TEXT0:
case DEFORM_TEXT1:
case DEFORM_TEXT2:
case DEFORM_TEXT3:
case DEFORM_TEXT4:
case DEFORM_TEXT5:
case DEFORM_TEXT6:
case DEFORM_TEXT7:
shader.vertexAttribs |= ATTR_NORMAL;
break;
default:
case DEFORM_NONE:
case DEFORM_MOVE:
case DEFORM_PROJECTION_SHADOW:
case DEFORM_AUTOSPRITE2:
break;
}
}
}
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
{
shaderStage_t *pStage = &stages[stage];
if ( !pStage->active )
{
break;
}
for (i = 0; i < 2; i++)
{
if (i == 1 && ( pStage->bundle[1].image[0] == 0 ))
{
break;
}
switch(pStage->bundle[i].tcGen)
{
case TCGEN_TEXTURE:
shader.vertexAttribs |= ATTR_TEXCOORD;
break;
case TCGEN_LIGHTMAP:
shader.vertexAttribs |= ATTR_LIGHTCOORD;
break;
case TCGEN_ENVIRONMENT_MAPPED:
shader.vertexAttribs |= ATTR_NORMAL;
break;
default:
break;
}
}
switch(pStage->rgbGen)
{
case CGEN_EXACT_VERTEX:
case CGEN_VERTEX:
case CGEN_ONE_MINUS_VERTEX:
shader.vertexAttribs |= ATTR_COLOR;
break;
default:
break;
}
switch(pStage->alphaGen)
{
case AGEN_LIGHTING_SPECULAR:
shader.vertexAttribs |= ATTR_NORMAL;
break;
case AGEN_VERTEX:
case AGEN_ONE_MINUS_VERTEX:
shader.vertexAttribs |= ATTR_COLOR;
break;
default:
break;
}
}
}
typedef struct {
int blendA;
int blendB;
@ -2284,7 +2423,8 @@ static shader_t *FinishShader( void ) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
} else {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
shader.lightmapIndex = LIGHTMAP_NONE;
// Don't set this, it will just add duplicate shaders to the hash
//shader.lightmapIndex = LIGHTMAP_NONE;
}
}
@ -2301,6 +2441,9 @@ static shader_t *FinishShader( void ) {
// determine which stage iterator function is appropriate
ComputeStageIteratorFunc();
// determine which vertex attributes this shader needs
ComputeVertexAttribs();
return GeneratePermanentShader();
}
@ -2486,12 +2629,6 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
stages[i].bundle[0].texMods = texMods[i];
}
// FIXME: set these "need" values apropriately
shader.needsNormal = qtrue;
shader.needsST1 = qtrue;
shader.needsST2 = qtrue;
shader.needsColor = qtrue;
//
// attempt to define shader from an explicit parameter file
//
@ -2622,12 +2759,6 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_
stages[i].bundle[0].texMods = texMods[i];
}
// FIXME: set these "need" values apropriately
shader.needsNormal = qtrue;
shader.needsST1 = qtrue;
shader.needsST2 = qtrue;
shader.needsColor = qtrue;
//
// create the default shading commands
//
@ -2848,6 +2979,8 @@ void R_ShaderList_f (void) {
if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) {
ri.Printf( PRINT_ALL, "gen " );
} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorGenericVBO ) {
ri.Printf( PRINT_ALL, "genv" );
} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) {
ri.Printf( PRINT_ALL, "sky " );
} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorLightmappedMultitexture ) {

View file

@ -384,6 +384,105 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
}
}
static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int maxs[2] )
{
int s, t;
//int firstVertex = tess.numVertexes;
//int firstIndex = tess.numIndexes;
matrix_t matrix;
vec4_t color;
tess.numVertexes = 0;
tess.numIndexes = 0;
tess.firstIndex = 0;
GL_Bind( image );
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
tess.xyz[tess.numVertexes][0] = s_skyPoints[t][s][0];
tess.xyz[tess.numVertexes][1] = s_skyPoints[t][s][1];
tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2];
tess.xyz[tess.numVertexes][3] = 1.0;
tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
tess.numVertexes++;
if(tess.numVertexes >= SHADER_MAX_VERTEXES)
{
ri.Error(ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySideVBO()\n");
}
}
}
for ( t = 0; t < maxs[1] - mins[1]; t++ )
{
for ( s = 0; s < maxs[0] - mins[0]; s++ )
{
if (tess.numIndexes + 6 >= SHADER_MAX_INDEXES)
{
ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()\n");
}
tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1);
}
}
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = GLSL_GetGenericShaderProgram();
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniform_ModelViewProjectionMatrix(sp, glState.modelviewProjection);
GLSL_SetUniform_FogAdjustColors(sp, 0);
GLSL_SetUniform_DeformGen(sp, DGEN_NONE);
GLSL_SetUniform_TCGen0(sp, TCGEN_TEXTURE);
Matrix16Identity(matrix);
GLSL_SetUniform_Texture0Matrix(sp, matrix);
GLSL_SetUniform_Texture1Env(sp, 0);
GLSL_SetUniform_ColorGen(sp, CGEN_CONST);
GLSL_SetUniform_AlphaGen(sp, AGEN_CONST);
color[0] = tr.identityLight;
color[1] = tr.identityLight;
color[2] = tr.identityLight;
color[3] = 1.0f;
GLSL_SetUniform_Color(sp, color);
}
else
{
qglEnableClientState( GL_VERTEX_ARRAY );
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
qglVertexPointer(3, GL_FLOAT, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz));
qglTexCoordPointer( 2, GL_FLOAT, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st) );
}
qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex));
//R_BindNullVBO();
//R_BindNullIBO();
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
}
static void DrawSkyBox( shader_t *shader )
{
int i;
@ -447,11 +546,21 @@ static void DrawSkyBox( shader_t *shader )
}
}
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
DrawSkySideVBO( shader->sky.outerbox[sky_texorder[i]],
sky_mins_subd,
sky_maxs_subd );
}
else
{
DrawSkySide( shader->sky.outerbox[sky_texorder[i]],
sky_mins_subd,
sky_maxs_subd );
}
}
}
static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
@ -617,6 +726,7 @@ void R_BuildCloudData( shaderCommands_t *input )
// set up for drawing
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
if ( input->shader->sky.cloudHeight )
{
@ -708,8 +818,17 @@ void RB_DrawSun( void ) {
if ( !r_drawSun->integer ) {
return;
}
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
//qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
{
// FIXME: this could be a lot cleaner
matrix_t trans, product;
Matrix16Translation( backEnd.viewParms.or.origin, trans );
Matrix16Multiply( backEnd.viewParms.world.modelMatrix, trans, product );
GL_SetModelviewMatrix( product );
}
dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
size = dist * 0.4;
@ -816,22 +935,45 @@ void RB_StageIteratorSky( void ) {
// draw the outer skybox
if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
matrix_t oldmodelview;
if (!(glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer &&
glRefConfig.glsl && r_arb_shader_objects->integer))
{
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
}
qglPushMatrix ();
GL_State( 0 );
qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
{
// FIXME: this could be a lot cleaner
matrix_t trans, product;
Matrix16Copy( glState.modelview, oldmodelview );
Matrix16Translation( backEnd.viewParms.or.origin, trans );
Matrix16Multiply( glState.modelview, trans, product );
GL_SetModelviewMatrix( product );
}
DrawSkyBox( tess.shader );
qglPopMatrix();
GL_SetModelviewMatrix( oldmodelview );
}
// generate the vertexes for all the clouds, which will be drawn
// by the generic shader routine
R_BuildCloudData( &tess );
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
RB_StageIteratorGenericVBO();
}
else
{
RB_StageIteratorGeneric();
}
// draw the inner skybox

View file

@ -67,6 +67,21 @@ void RB_CheckOverflow( int verts, int indexes ) {
}
void RB_CheckVBOandIBO(VBO_t *vbo, IBO_t *ibo)
{
if (!(vbo == glState.currentVBO && ibo == glState.currentIBO) || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES)
{
RB_EndSurface();
RB_BeginSurface(tess.shader, tess.fogNum);
R_BindVBO(vbo);
R_BindIBO(ibo);
}
tess.useInternalVBO = qfalse;
}
/*
==============
RB_AddQuadStampExt
@ -148,6 +163,97 @@ void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ) {
RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 );
}
/*
==============
RB_InstantQuad
based on Tess_InstantQuad from xreal
==============
*/
void RB_InstantQuad(vec4_t quadVerts[4])
{
matrix_t matrix;
GLimp_LogComment("--- RB_InstantQuad ---\n");
tess.numVertexes = 0;
tess.numIndexes = 0;
tess.firstIndex = 0;
VectorCopy4(quadVerts[0], tess.xyz[tess.numVertexes]);
tess.texCoords[tess.numVertexes][0][0] = 0;
tess.texCoords[tess.numVertexes][0][1] = 0;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
VectorCopy4(quadVerts[1], tess.xyz[tess.numVertexes]);
tess.texCoords[tess.numVertexes][0][0] = 1;
tess.texCoords[tess.numVertexes][0][1] = 0;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
VectorCopy4(quadVerts[2], tess.xyz[tess.numVertexes]);
tess.texCoords[tess.numVertexes][0][0] = 1;
tess.texCoords[tess.numVertexes][0][1] = 1;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
VectorCopy4(quadVerts[3], tess.xyz[tess.numVertexes]);
tess.texCoords[tess.numVertexes][0][0] = 0;
tess.texCoords[tess.numVertexes][0][1] = 1;
tess.texCoords[tess.numVertexes][0][2] = 0;
tess.texCoords[tess.numVertexes][0][3] = 1;
tess.numVertexes++;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 1;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 3;
// FIXME: A lot of this can probably be removed for speed
RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = &tr.genericShader[0];
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniform_ModelViewProjectionMatrix(sp, glState.modelviewProjection);
GLSL_SetUniform_FogAdjustColors(sp, 0);
GLSL_SetUniform_DeformGen(sp, DGEN_NONE);
GLSL_SetUniform_TCGen0(sp, TCGEN_TEXTURE);
Matrix16Identity(matrix);
GLSL_SetUniform_Texture0Matrix(sp, matrix);
GLSL_SetUniform_Texture1Env(sp, 0);
GLSL_SetUniform_ColorGen(sp, CGEN_IDENTITY);
GLSL_SetUniform_AlphaGen(sp, AGEN_IDENTITY);
}
else
{
qglEnableClientState( GL_VERTEX_ARRAY );
qglVertexPointer(3, GL_FLOAT, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz));
qglEnableClientState( GL_NORMAL_ARRAY );
qglNormalPointer(GL_FLOAT, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal));
}
qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(0));
//R_BindNullVBO();
//R_BindNullIBO();
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
}
/*
==============
RB_SurfaceSprite
@ -217,40 +323,35 @@ static void RB_SurfacePolychain( srfPoly_t *p ) {
tess.numVertexes = numv;
}
/*
=============
RB_SurfaceTriangles
=============
*/
static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits)
{
int i;
drawVert_t *dv;
srfTriangle_t *tri;
srfVert_t *dv;
float *xyz, *normal, *texCoords;
glIndex_t *index;
byte *color;
int dlightBits;
qboolean needsNormal;
dlightBits = srf->dlightBits[backEnd.smpFrame];
tess.dlightBits |= dlightBits;
RB_CHECKOVERFLOW( numVerts, numTriangles * 3 );
RB_CHECKOVERFLOW( srf->numVerts, srf->numIndexes );
for ( i = 0 ; i < srf->numIndexes ; i += 3 ) {
tess.indexes[ tess.numIndexes + i + 0 ] = tess.numVertexes + srf->indexes[ i + 0 ];
tess.indexes[ tess.numIndexes + i + 1 ] = tess.numVertexes + srf->indexes[ i + 1 ];
tess.indexes[ tess.numIndexes + i + 2 ] = tess.numVertexes + srf->indexes[ i + 2 ];
tri = triangles;
index = &tess.indexes[ tess.numIndexes ];
for ( i = 0 ; i < numTriangles ; i++, tri++ ) {
*index++ = tess.numVertexes + tri->indexes[0];
*index++ = tess.numVertexes + tri->indexes[1];
*index++ = tess.numVertexes + tri->indexes[2];
}
tess.numIndexes += srf->numIndexes;
tess.numIndexes += numTriangles * 3;
dv = srf->verts;
dv = verts;
xyz = tess.xyz[ tess.numVertexes ];
normal = tess.normal[ tess.numVertexes ];
texCoords = tess.texCoords[ tess.numVertexes ][0];
color = tess.vertexColors[ tess.numVertexes ];
needsNormal = tess.shader->needsNormal;
needsNormal = tess.shader->vertexAttribs & ATTR_NORMAL;
for ( i = 0 ; i < srf->numVerts ; i++, dv++, xyz += 4, normal += 4, texCoords += 4, color += 4 ) {
for ( i = 0 ; i < numVerts ; i++, dv++, xyz += 4, normal += 4, texCoords += 4, color += 4 ) {
xyz[0] = dv->xyz[0];
xyz[1] = dv->xyz[1];
xyz[2] = dv->xyz[2];
@ -267,14 +368,127 @@ static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
texCoords[2] = dv->lightmap[0];
texCoords[3] = dv->lightmap[1];
*(int *)color = *(int *)dv->color;
*(int *)color = *(int *)dv->vertexColors;
}
for ( i = 0 ; i < srf->numVerts ; i++ ) {
tess.vertexDlightBits[ tess.numVertexes + i] = dlightBits;
#if 0 // nothing even uses vertex dlightbits
for ( i = 0 ; i < numVerts ; i++ ) {
tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits;
}
#endif
tess.dlightBits |= dlightBits;
tess.numVertexes += numVerts;
}
static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int dlightBits, qboolean shaderCheck)
{
if( glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && vbo && ibo)
{
int i, mergeForward, mergeBack;
GLvoid *firstIndexOffset, *lastIndexOffset;
if (shaderCheck && !(!ShaderRequiresCPUDeforms(tess.shader) && !tess.shader->isSky && !tess.shader->isPortal))
{
return qfalse;
}
tess.numVertexes += srf->numVerts;
RB_CheckVBOandIBO(vbo, ibo);
tess.dlightBits |= dlightBits;
// merge this into any existing multidraw primitives
mergeForward = -1;
mergeBack = -1;
firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE));
lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(GL_INDEX_TYPE));
if (r_mergeMultidraws->integer)
{
i = 0;
if (r_mergeMultidraws->integer == 1)
{
// lazy merge, only check the last primitive
if (tess.multiDrawPrimitives)
{
i = tess.multiDrawPrimitives - 1;
}
}
for (; i < tess.multiDrawPrimitives; i++)
{
if (tess.multiDrawLastIndex[i] == firstIndexOffset)
{
mergeBack = i;
}
if (lastIndexOffset == tess.multiDrawFirstIndex[i])
{
mergeForward = i;
}
}
}
if (mergeBack != -1 && mergeForward == -1)
{
tess.multiDrawNumIndexes[mergeBack] += numIndexes;
tess.multiDrawLastIndex[mergeBack] = (byte *)tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack] * sizeof(GL_INDEX_TYPE);
backEnd.pc.c_multidrawsMerged++;
}
else if (mergeBack == -1 && mergeForward != -1)
{
tess.multiDrawNumIndexes[mergeForward] += numIndexes;
tess.multiDrawFirstIndex[mergeForward] = firstIndexOffset;
tess.multiDrawLastIndex[mergeForward] = (byte *)tess.multiDrawFirstIndex[mergeForward] + tess.multiDrawNumIndexes[mergeForward] * sizeof(GL_INDEX_TYPE);
backEnd.pc.c_multidrawsMerged++;
}
else if (mergeBack != -1 && mergeForward != -1)
{
tess.multiDrawNumIndexes[mergeBack] += numIndexes + tess.multiDrawNumIndexes[mergeForward];
tess.multiDrawLastIndex[mergeBack] = (byte *)tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack] * sizeof(GL_INDEX_TYPE);
tess.multiDrawPrimitives--;
if (mergeForward != tess.multiDrawPrimitives)
{
tess.multiDrawNumIndexes[mergeForward] = tess.multiDrawNumIndexes[tess.multiDrawPrimitives];
tess.multiDrawFirstIndex[mergeForward] = tess.multiDrawFirstIndex[tess.multiDrawPrimitives];
}
backEnd.pc.c_multidrawsMerged += 2;
}
else if (mergeBack == -1 && mergeForward == -1)
{
tess.multiDrawNumIndexes[tess.multiDrawPrimitives] = numIndexes;
tess.multiDrawFirstIndex[tess.multiDrawPrimitives] = firstIndexOffset;
tess.multiDrawLastIndex[tess.multiDrawPrimitives] = lastIndexOffset;
tess.multiDrawPrimitives++;
}
backEnd.pc.c_multidraws++;
tess.numIndexes += numIndexes;
tess.numVertexes += numVerts;
return qtrue;
}
return qfalse;
}
/*
=============
RB_SurfaceTriangles
=============
*/
static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
{
return;
}
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame]);
}
@ -293,6 +507,8 @@ static void RB_SurfaceBeam( void )
vec3_t direction, normalized_direction;
vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
vec3_t oldorigin, origin;
matrix_t matrix;
vec4_t color;
e = &backEnd.currentEntity->e;
@ -326,6 +542,69 @@ static void RB_SurfaceBeam( void )
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
// FIXME: Quake3 doesn't use this, so I never tested it
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
tess.numVertexes = 0;
tess.numIndexes = 0;
tess.firstIndex = 0;
for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
VectorCopy(end_points [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
}
for ( i = 0; i < NUM_BEAM_SEGS; i++ ) {
tess.indexes[tess.numIndexes++] = i * 2;
tess.indexes[tess.numIndexes++] = (i + 1) * 2;
tess.indexes[tess.numIndexes++] = 1 + i * 2;
tess.indexes[tess.numIndexes++] = 1 + i * 2;
tess.indexes[tess.numIndexes++] = (i + 1) * 2;
tess.indexes[tess.numIndexes++] = 1 + (i + 1) * 2;
}
// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
RB_UpdateVBOs(ATTR_POSITION);
if (glRefConfig.glsl && r_arb_shader_objects->integer)
{
shaderProgram_t *sp = GLSL_GetGenericShaderProgram();
GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp);
GLSL_SetUniform_ModelViewProjectionMatrix(sp, glState.modelviewProjection);
GLSL_SetUniform_FogAdjustColors(sp, 0);
GLSL_SetUniform_DeformGen(sp, DGEN_NONE);
GLSL_SetUniform_TCGen0(sp, TCGEN_IDENTITY);
Matrix16Identity(matrix);
GLSL_SetUniform_Texture0Matrix(sp, matrix);
GLSL_SetUniform_Texture1Env(sp, 0);
GLSL_SetUniform_ColorGen(sp, CGEN_CONST);
GLSL_SetUniform_AlphaGen(sp, AGEN_CONST);
color[0] = 1.0f;
color[1] = 0.0f;
color[2] = 0.0f;
color[3] = 1.0f;
GLSL_SetUniform_Color(sp, color);
}
else
{
qglEnableClientState( GL_VERTEX_ARRAY );
qglVertexPointer(3, GL_FLOAT, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz));
}
qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex));
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.firstIndex = 0;
}
else
{
qglColor3f( 1, 0, 0 );
qglBegin( GL_TRIANGLE_STRIP );
@ -334,6 +613,7 @@ static void RB_SurfaceBeam( void )
qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] );
}
qglEnd();
}
}
//================================================================================
@ -740,8 +1020,9 @@ static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
}
#endif
static void LerpMeshVertexes_scalar(md3Surface_t *surf, float backlerp)
static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
{
#if 0
short *oldXyz, *newXyz, *oldNormals, *newNormals;
float *outXyz, *outNormal;
float oldXyzScale, newXyzScale;
@ -836,10 +1117,59 @@ static void LerpMeshVertexes_scalar(md3Surface_t *surf, float backlerp)
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}
#endif
float *outXyz, *outNormal;
mdvVertex_t *newVerts;
int vertNum;
newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
if (backlerp == 0)
{
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
VectorCopy(newVerts->xyz, outXyz);
VectorCopy(newVerts->normal, outNormal);
newVerts++;
outXyz += 4;
outNormal += 4;
}
}
else
{
//
// interpolate and copy the vertex and normal
//
mdvVertex_t *oldVerts;
oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts;
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
VectorLerp(newVerts->xyz, oldVerts->xyz, backlerp, outXyz);
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, outNormal);
//VectorNormalize(outNormal);
newVerts++;
oldVerts++;
outXyz += 4;
outNormal += 4;
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], surf->numVerts);
}
}
static void LerpMeshVertexes(md3Surface_t *surf, float backlerp)
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
#if 0
#if idppc_altivec
if (com_altivec->integer) {
// must be in a seperate function or G3 systems will crash.
@ -847,6 +1177,7 @@ static void LerpMeshVertexes(md3Surface_t *surf, float backlerp)
return;
}
#endif // idppc_altivec
#endif
LerpMeshVertexes_scalar( surf, backlerp );
}
@ -856,11 +1187,11 @@ static void LerpMeshVertexes(md3Surface_t *surf, float backlerp)
RB_SurfaceMesh
=============
*/
static void RB_SurfaceMesh(md3Surface_t *surface) {
static void RB_SurfaceMesh(mdvSurface_t *surface) {
int j;
float backlerp;
int *triangles;
float *texCoords;
srfTriangle_t *triangles;
mdvSt_t *texCoords;
int indexes;
int Bob, Doug;
int numVerts;
@ -875,11 +1206,11 @@ static void RB_SurfaceMesh(md3Surface_t *surface) {
LerpMeshVertexes (surface, backlerp);
triangles = (int *) ((byte *)surface + surface->ofsTriangles);
triangles = surface->triangles;
indexes = surface->numTriangles * 3;
Bob = tess.numIndexes;
Doug = tess.numVertexes;
// JBravo: Mirrored models
if (backEnd.currentEntity->mirrored) {
// Makro - this should be done differently, but since we're copying
// indices in a loop anyway (see below), reversing them in the same loop
@ -890,18 +1221,20 @@ static void RB_SurfaceMesh(md3Surface_t *surface) {
tess.indexes[Bob + j + 2] = Doug + triangles[j + 1];
}
} else {
for (j = 0 ; j < indexes ; j++) {
tess.indexes[Bob + j] = Doug + triangles[j];
for (j = 0 ; j < surface->numTriangles ; j++) {
tess.indexes[Bob + j*3 + 0] = Doug + triangles[j].indexes[0];
tess.indexes[Bob + j*3 + 1] = Doug + triangles[j].indexes[1];
tess.indexes[Bob + j*3 + 2] = Doug + triangles[j].indexes[2];
}
}
tess.numIndexes += indexes;
texCoords = (float *) ((byte *)surface + surface->ofsSt);
texCoords = surface->st;
numVerts = surface->numVerts;
for ( j = 0; j < numVerts; j++ ) {
tess.texCoords[Doug + j][0][0] = texCoords[j*2+0];
tess.texCoords[Doug + j][0][1] = texCoords[j*2+1];
tess.texCoords[Doug + j][0][0] = texCoords[j].st[0];
tess.texCoords[Doug + j][0][1] = texCoords[j].st[1];
// FIXME: fill in lightmapST for completeness?
}
@ -915,56 +1248,13 @@ static void RB_SurfaceMesh(md3Surface_t *surface) {
RB_SurfaceFace
==============
*/
static void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
int i;
unsigned *indices, *tessIndexes;
float *v;
float *normal;
int ndx;
int Bob;
int numPoints;
int dlightBits;
RB_CHECKOVERFLOW( surf->numPoints, surf->numIndices );
dlightBits = surf->dlightBits[backEnd.smpFrame];
tess.dlightBits |= dlightBits;
indices = ( unsigned * ) ( ( ( char * ) surf ) + surf->ofsIndices );
Bob = tess.numVertexes;
tessIndexes = tess.indexes + tess.numIndexes;
for ( i = surf->numIndices-1 ; i >= 0 ; i-- ) {
tessIndexes[i] = indices[i] + Bob;
static void RB_SurfaceFace( srfSurfaceFace_t *srf ) {
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
{
return;
}
tess.numIndexes += surf->numIndices;
v = surf->points[0];
ndx = tess.numVertexes;
numPoints = surf->numPoints;
if ( tess.shader->needsNormal ) {
normal = surf->plane.normal;
for ( i = 0, ndx = tess.numVertexes; i < numPoints; i++, ndx++ ) {
VectorCopy( normal, tess.normal[ndx] );
}
}
for ( i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++ ) {
VectorCopy( v, tess.xyz[ndx]);
tess.texCoords[ndx][0][0] = v[3];
tess.texCoords[ndx][0][1] = v[4];
tess.texCoords[ndx][1][0] = v[5];
tess.texCoords[ndx][1][1] = v[6];
* ( unsigned int * ) &tess.vertexColors[ndx] = * ( unsigned int * ) &v[7];
tess.vertexDlightBits[ndx] = dlightBits;
}
tess.numVertexes += surf->numPoints;
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame]);
}
@ -1005,13 +1295,13 @@ RB_SurfaceGrid
Just copy the grid of points and triangulate
=============
*/
static void RB_SurfaceGrid( srfGridMesh_t *cv ) {
static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
int i, j;
float *xyz;
float *texCoords;
float *normal;
unsigned char *color;
drawVert_t *dv;
srfVert_t *dv;
int rows, irows, vrows;
int used;
int widthTable[MAX_GRID_SIZE];
@ -1020,37 +1310,42 @@ static void RB_SurfaceGrid( srfGridMesh_t *cv ) {
int lodWidth, lodHeight;
int numVertexes;
int dlightBits;
int *vDlightBits;
//int *vDlightBits;
qboolean needsNormal;
dlightBits = cv->dlightBits[backEnd.smpFrame];
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
{
return;
}
dlightBits = srf->dlightBits[backEnd.smpFrame];
tess.dlightBits |= dlightBits;
// determine the allowable discrepance
lodError = LodErrorForVolume( cv->lodOrigin, cv->lodRadius );
lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius );
// determine which rows and columns of the subdivision
// we are actually going to use
widthTable[0] = 0;
lodWidth = 1;
for ( i = 1 ; i < cv->width-1 ; i++ ) {
if ( cv->widthLodError[i] <= lodError ) {
for ( i = 1 ; i < srf->width-1 ; i++ ) {
if ( srf->widthLodError[i] <= lodError ) {
widthTable[lodWidth] = i;
lodWidth++;
}
}
widthTable[lodWidth] = cv->width-1;
widthTable[lodWidth] = srf->width-1;
lodWidth++;
heightTable[0] = 0;
lodHeight = 1;
for ( i = 1 ; i < cv->height-1 ; i++ ) {
if ( cv->heightLodError[i] <= lodError ) {
for ( i = 1 ; i < srf->height-1 ; i++ ) {
if ( srf->heightLodError[i] <= lodError ) {
heightTable[lodHeight] = i;
lodHeight++;
}
}
heightTable[lodHeight] = cv->height-1;
heightTable[lodHeight] = srf->height-1;
lodHeight++;
@ -1088,12 +1383,12 @@ static void RB_SurfaceGrid( srfGridMesh_t *cv ) {
normal = tess.normal[numVertexes];
texCoords = tess.texCoords[numVertexes][0];
color = ( unsigned char * ) &tess.vertexColors[numVertexes];
vDlightBits = &tess.vertexDlightBits[numVertexes];
needsNormal = tess.shader->needsNormal;
//vDlightBits = &tess.vertexDlightBits[numVertexes];
needsNormal = tess.shader->vertexAttribs & ATTR_NORMAL;
for ( i = 0 ; i < rows ; i++ ) {
for ( j = 0 ; j < lodWidth ; j++ ) {
dv = cv->verts + heightTable[ used + i ] * cv->width
dv = srf->verts + heightTable[ used + i ] * srf->width
+ widthTable[ j ];
xyz[0] = dv->xyz[0];
@ -1108,8 +1403,8 @@ static void RB_SurfaceGrid( srfGridMesh_t *cv ) {
normal[1] = dv->normal[1];
normal[2] = dv->normal[2];
}
* ( unsigned int * ) color = * ( unsigned int * ) dv->color;
*vDlightBits++ = dlightBits;
* ( unsigned int * ) color = * ( unsigned int * ) dv->vertexColors;
//*vDlightBits++ = dlightBits;
xyz += 4;
normal += 4;
texCoords += 4;
@ -1173,6 +1468,8 @@ Draws x/y/z lines from the origin for orientation debugging
===================
*/
static void RB_SurfaceAxis( void ) {
// FIXME: implement this
#if 0
GL_Bind( tr.whiteImage );
qglLineWidth( 3 );
qglBegin( GL_LINES );
@ -1187,6 +1484,7 @@ static void RB_SurfaceAxis( void ) {
qglVertex3f( 0,0,16 );
qglEnd();
qglLineWidth( 1 );
#endif
}
//===========================================================================
@ -1232,6 +1530,57 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
}
static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf)
{
RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qfalse );
}
void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
{
mdvModel_t *mdvModel;
mdvSurface_t *mdvSurface;
refEntity_t *refEnt;
GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n");
if(!surface->vbo || !surface->ibo)
return;
//RB_CheckVBOandIBO(surface->vbo, surface->ibo);
RB_EndSurface();
RB_BeginSurface(tess.shader, tess.fogNum);
R_BindVBO(surface->vbo);
R_BindIBO(surface->ibo);
tess.useInternalVBO = qfalse;
tess.numIndexes += surface->numIndexes;
tess.numVertexes += surface->numVerts;
mdvModel = surface->mdvModel;
mdvSurface = surface->mdvSurface;
refEnt = &backEnd.currentEntity->e;
if(refEnt->oldframe == refEnt->frame)
{
glState.vertexAttribsInterpolation = 0;
}
else
{
glState.vertexAttribsInterpolation = refEnt->backlerp;
}
glState.vertexAttribsOldFrame = refEnt->oldframe;
glState.vertexAttribsNewFrame = refEnt->frame;
RB_EndSurface();
// So we don't lerp surfaces that shouldn't be lerped
glState.vertexAttribsInterpolation = 0;
}
static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {
// all apropriate state must be set in RB_BeginSurface
// this isn't implemented yet...
@ -1249,12 +1598,14 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceGrid, // SF_GRID,
(void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
(void(*)(void*))RB_SurfacePolychain, // SF_POLY,
(void(*)(void*))RB_SurfaceMesh, // SF_MD3,
(void(*)(void*))RB_SurfaceMesh, // SF_MDV,
(void(*)(void*))RB_SurfaceAnim, // SF_MD4,
#ifdef RAVENMD4
(void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
#endif
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceDisplayList // SF_DISPLAY_LIST
(void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST
(void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH,
(void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH
};

View file

@ -0,0 +1,785 @@
/*
===========================================================================
Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
This file is part of XreaL source code.
XreaL source code 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.
XreaL source code 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 XreaL source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_vbo.c
#include "tr_local.h"
/*
============
R_CreateVBO
============
*/
VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage)
{
VBO_t *vbo;
int glUsage;
switch (usage)
{
case VBO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB;
break;
case VBO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB;
break;
default:
Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
return NULL;
}
if(strlen(name) >= MAX_QPATH)
{
ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long\n", name);
}
if ( tr.numVBOs == MAX_VBOS ) {
ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit\n");
}
// make sure the render thread is stopped
R_SyncRenderThread();
vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
tr.numVBOs++;
memset(vbo, 0, sizeof(*vbo));
Q_strncpyz(vbo->name, name, sizeof(vbo->name));
vbo->vertexesSize = vertexesSize;
qglGenBuffersARB(1, &vbo->vertexesVBO);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL;
GL_CheckErrors();
return vbo;
}
/*
============
R_CreateVBO2
============
*/
VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage)
{
VBO_t *vbo;
int i;
byte *data;
int dataSize;
int dataOfs;
int glUsage;
switch (usage)
{
case VBO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB;
break;
case VBO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB;
break;
default:
Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
return NULL;
}
if(!numVertexes)
return NULL;
if(strlen(name) >= MAX_QPATH)
{
ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long\n", name);
}
if ( tr.numVBOs == MAX_VBOS ) {
ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit\n");
}
// make sure the render thread is stopped
R_SyncRenderThread();
vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
tr.numVBOs++;
memset(vbo, 0, sizeof(*vbo));
Q_strncpyz(vbo->name, name, sizeof(vbo->name));
if (usage == VBO_USAGE_STATIC)
{
// since these vertex attributes are never altered, interleave them
vbo->ofs_xyz = 0;
dataSize = sizeof(verts[0].xyz);
if(stateBits & ATTR_NORMAL)
{
vbo->ofs_normal = dataSize;
dataSize += sizeof(verts[0].normal);
}
if(stateBits & ATTR_TEXCOORD)
{
vbo->ofs_st = dataSize;
dataSize += sizeof(verts[0].st);
}
if(stateBits & ATTR_LIGHTCOORD)
{
vbo->ofs_lightmap = dataSize;
dataSize += sizeof(verts[0].lightmap);
}
if(stateBits & ATTR_COLOR)
{
vbo->ofs_vertexcolor = dataSize;
dataSize += sizeof(verts[0].vertexColors);
}
vbo->stride_xyz = dataSize;
vbo->stride_normal = dataSize;
vbo->stride_st = dataSize;
vbo->stride_lightmap = dataSize;
vbo->stride_vertexcolor = dataSize;
// create VBO
dataSize *= numVertexes;
data = ri.Hunk_AllocateTempMemory(dataSize);
dataOfs = 0;
//ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
//vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);
for (i = 0; i < numVertexes; i++)
{
// xyz
memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
dataOfs += sizeof(verts[i].xyz);
// normal
if(stateBits & ATTR_NORMAL)
{
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
dataOfs += sizeof(verts[i].normal);
}
// vertex texcoords
if(stateBits & ATTR_TEXCOORD)
{
memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
dataOfs += sizeof(verts[i].st);
}
// feed vertex lightmap texcoords
if(stateBits & ATTR_LIGHTCOORD)
{
memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
dataOfs += sizeof(verts[i].lightmap);
}
// feed vertex colors
if(stateBits & ATTR_COLOR)
{
memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
dataOfs += sizeof(verts[i].vertexColors);
}
}
}
else
{
// since these vertex attributes may be changed, put them in flat arrays
dataSize = sizeof(verts[0].xyz);
if(stateBits & ATTR_NORMAL)
{
dataSize += sizeof(verts[0].normal);
}
if(stateBits & ATTR_TEXCOORD)
{
dataSize += sizeof(verts[0].st);
}
if(stateBits & ATTR_LIGHTCOORD)
{
dataSize += sizeof(verts[0].lightmap);
}
if(stateBits & ATTR_COLOR)
{
dataSize += sizeof(verts[0].vertexColors);
}
// create VBO
dataSize *= numVertexes;
data = ri.Hunk_AllocateTempMemory(dataSize);
dataOfs = 0;
vbo->ofs_xyz = 0;
vbo->ofs_normal = 0;
vbo->ofs_st = 0;
vbo->ofs_lightmap = 0;
vbo->ofs_vertexcolor = 0;
vbo->stride_xyz = sizeof(verts[0].xyz);
vbo->stride_normal = sizeof(verts[0].normal);
vbo->stride_vertexcolor = sizeof(verts[0].vertexColors);
vbo->stride_st = sizeof(verts[0].st);
vbo->stride_lightmap = sizeof(verts[0].lightmap);
//ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
//vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);
// xyz
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
dataOfs += sizeof(verts[i].xyz);
}
// normal
if(stateBits & ATTR_NORMAL)
{
vbo->ofs_normal = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
dataOfs += sizeof(verts[i].normal);
}
}
// vertex texcoords
if(stateBits & ATTR_TEXCOORD)
{
vbo->ofs_st = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
dataOfs += sizeof(verts[i].st);
}
}
// feed vertex lightmap texcoords
if(stateBits & ATTR_LIGHTCOORD)
{
vbo->ofs_lightmap = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
dataOfs += sizeof(verts[i].lightmap);
}
}
// feed vertex colors
if(stateBits & ATTR_COLOR)
{
vbo->ofs_vertexcolor = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
dataOfs += sizeof(verts[i].vertexColors);
}
}
}
vbo->vertexesSize = dataSize;
qglGenBuffersARB(1, &vbo->vertexesVBO);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage);
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL;
GL_CheckErrors();
ri.Hunk_FreeTempMemory(data);
return vbo;
}
/*
============
R_CreateIBO
============
*/
IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage)
{
IBO_t *ibo;
int glUsage;
switch (usage)
{
case VBO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB;
break;
case VBO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB;
break;
default:
Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
return NULL;
}
if(strlen(name) >= MAX_QPATH)
{
ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long\n", name);
}
if ( tr.numIBOs == MAX_IBOS ) {
ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit\n");
}
// make sure the render thread is stopped
R_SyncRenderThread();
ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
tr.numIBOs++;
Q_strncpyz(ibo->name, name, sizeof(ibo->name));
ibo->indexesSize = indexesSize;
qglGenBuffersARB(1, &ibo->indexesVBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glState.currentIBO = NULL;
GL_CheckErrors();
return ibo;
}
/*
============
R_CreateIBO2
============
*/
IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage)
{
IBO_t *ibo;
int i, j;
byte *indexes;
int indexesSize;
int indexesOfs;
srfTriangle_t *tri;
glIndex_t index;
int glUsage;
switch (usage)
{
case VBO_USAGE_STATIC:
glUsage = GL_STATIC_DRAW_ARB;
break;
case VBO_USAGE_DYNAMIC:
glUsage = GL_DYNAMIC_DRAW_ARB;
break;
default:
Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
return NULL;
}
if(!numTriangles)
return NULL;
if(strlen(name) >= MAX_QPATH)
{
ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long\n", name);
}
if ( tr.numIBOs == MAX_IBOS ) {
ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit\n");
}
// make sure the render thread is stopped
R_SyncRenderThread();
ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
tr.numIBOs++;
Q_strncpyz(ibo->name, name, sizeof(ibo->name));
indexesSize = numTriangles * 3 * sizeof(int);
indexes = ri.Hunk_AllocateTempMemory(indexesSize);
indexesOfs = 0;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
for(j = 0; j < 3; j++)
{
index = tri->indexes[j];
memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t));
indexesOfs += sizeof(glIndex_t);
}
}
ibo->indexesSize = indexesSize;
qglGenBuffersARB(1, &ibo->indexesVBO);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glState.currentIBO = NULL;
GL_CheckErrors();
ri.Hunk_FreeTempMemory(indexes);
return ibo;
}
/*
============
R_BindVBO
============
*/
void R_BindVBO(VBO_t * vbo)
{
if(!vbo)
{
//R_BindNullVBO();
ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo");
return;
}
if(r_logFile->integer)
{
// don't just call LogComment, or we will get a call to va() every frame!
GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name));
}
if(glState.currentVBO != vbo)
{
glState.currentVBO = vbo;
glState.vertexAttribPointersSet = 0;
glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0;
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
backEnd.pc.c_vboVertexBuffers++;
}
}
/*
============
R_BindNullVBO
============
*/
void R_BindNullVBO(void)
{
GLimp_LogComment("--- R_BindNullVBO ---\n");
if(glState.currentVBO)
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glState.currentVBO = NULL;
}
GL_CheckErrors();
}
/*
============
R_BindIBO
============
*/
void R_BindIBO(IBO_t * ibo)
{
if(!ibo)
{
//R_BindNullIBO();
ri.Error(ERR_DROP, "R_BindIBO: NULL ibo");
return;
}
if(r_logFile->integer)
{
// don't just call LogComment, or we will get a call to va() every frame!
GLimp_LogComment(va("--- R_BindIBO( %s ) ---\n", ibo->name));
}
if(glState.currentIBO != ibo)
{
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
glState.currentIBO = ibo;
backEnd.pc.c_vboIndexBuffers++;
}
}
/*
============
R_BindNullIBO
============
*/
void R_BindNullIBO(void)
{
GLimp_LogComment("--- R_BindNullIBO ---\n");
if(glState.currentIBO)
{
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glState.currentIBO = NULL;
glState.vertexAttribPointersSet = 0;
}
}
/*
============
R_InitVBOs
============
*/
void R_InitVBOs(void)
{
int dataSize;
byte *data;
ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n");
tr.numVBOs = 0;
tr.numIBOs = 0;
dataSize = sizeof(tess.xyz[0]);
dataSize += sizeof(tess.normal[0]);
dataSize += sizeof(tess.vertexColors[0]);
dataSize += sizeof(tess.texCoords[0][0]) * 2;
dataSize *= SHADER_MAX_VERTEXES;
data = ri.Malloc(dataSize);
memset(data, 0, dataSize);
tess.vbo = R_CreateVBO("tessVertexArray_VBO", data, dataSize, VBO_USAGE_DYNAMIC);
ri.Free(data);
tess.vbo->ofs_xyz = 0;
tess.vbo->ofs_normal = tess.vbo->ofs_xyz + sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
// these next two are actually interleaved
tess.vbo->ofs_st = tess.vbo->ofs_normal + sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_lightmap = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]);
tess.vbo->ofs_vertexcolor = tess.vbo->ofs_st + sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
tess.vbo->stride_xyz = sizeof(tess.xyz[0]);
tess.vbo->stride_normal = sizeof(tess.normal[0]);
tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]);
tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2;
tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2;
dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES;
data = ri.Malloc(dataSize);
memset(data, 0, dataSize);
tess.ibo = R_CreateIBO("tessVertexArray_IBO", data, dataSize, VBO_USAGE_DYNAMIC);
ri.Free(data);
R_BindNullVBO();
R_BindNullIBO();
GL_CheckErrors();
}
/*
============
R_ShutdownVBOs
============
*/
void R_ShutdownVBOs(void)
{
int i;
VBO_t *vbo;
IBO_t *ibo;
ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n");
R_BindNullVBO();
R_BindNullIBO();
for(i = 0; i < tr.numVBOs; i++)
{
vbo = tr.vbos[i];
if(vbo->vertexesVBO)
{
qglDeleteBuffersARB(1, &vbo->vertexesVBO);
}
//ri.Free(vbo);
}
for(i = 0; i < tr.numIBOs; i++)
{
ibo = tr.ibos[i];
if(ibo->indexesVBO)
{
qglDeleteBuffersARB(1, &ibo->indexesVBO);
}
//ri.Free(ibo);
}
tr.numVBOs = 0;
tr.numIBOs = 0;
}
/*
============
R_VBOList_f
============
*/
void R_VBOList_f(void)
{
int i;
VBO_t *vbo;
IBO_t *ibo;
int vertexesSize = 0;
int indexesSize = 0;
ri.Printf(PRINT_ALL, " size name\n");
ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
for(i = 0; i < tr.numVBOs; i++)
{
vbo = tr.vbos[i];
ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024),
(vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name);
vertexesSize += vbo->vertexesSize;
}
for(i = 0; i < tr.numIBOs; i++)
{
ibo = tr.ibos[i];
ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024),
(ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name);
indexesSize += ibo->indexesSize;
}
ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs);
ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024),
(vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs);
ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024),
(indexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
}
/*
==============
RB_UpdateVBOs
Adapted from Tess_UpdateVBOs from xreal
Tr3B: update the default VBO to replace the client side vertex arrays
==============
*/
void RB_UpdateVBOs(unsigned int attribBits)
{
GLimp_LogComment("--- RB_UpdateVBOs ---\n");
backEnd.pc.c_dynamicVboDraws++;
// update the default VBO
if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES)
{
R_BindVBO(tess.vbo);
if(attribBits & ATTR_BITS)
{
if(attribBits & ATTR_POSITION)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz);
}
if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD)
{
// these are interleaved, so we update both if either need it
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
}
if(attribBits & ATTR_NORMAL)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
}
if(attribBits & ATTR_COLOR)
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
}
}
else
{
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
}
}
// update the default IBO
if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
{
R_BindIBO(tess.ibo);
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
}
}

View file

@ -23,230 +23,97 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/*
=================
R_CullTriSurf
Returns true if the grid is completely culled away.
Also sets the clipped hint bit in tess
=================
*/
static qboolean R_CullTriSurf( srfTriangles_t *cv ) {
int boxCull;
boxCull = R_CullLocalBox( cv->bounds );
if ( boxCull == CULL_OUT ) {
return qtrue;
}
return qfalse;
}
/*
=================
R_CullGrid
Returns true if the grid is completely culled away.
Also sets the clipped hint bit in tess
=================
*/
static qboolean R_CullGrid( srfGridMesh_t *cv ) {
int boxCull;
int sphereCull;
if ( r_nocurves->integer ) {
return qtrue;
}
if ( tr.currentEntityNum != ENTITYNUM_WORLD ) {
sphereCull = R_CullLocalPointAndRadius( cv->localOrigin, cv->meshRadius );
} else {
sphereCull = R_CullPointAndRadius( cv->localOrigin, cv->meshRadius );
}
boxCull = CULL_OUT;
// check for trivial reject
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_patch_out++;
return qtrue;
}
// check bounding box if necessary
else if ( sphereCull == CULL_CLIP )
{
tr.pc.c_sphere_cull_patch_clip++;
boxCull = R_CullLocalBox( cv->meshBounds );
if ( boxCull == CULL_OUT )
{
tr.pc.c_box_cull_patch_out++;
return qtrue;
}
else if ( boxCull == CULL_IN )
{
tr.pc.c_box_cull_patch_in++;
}
else
{
tr.pc.c_box_cull_patch_clip++;
}
}
else
{
tr.pc.c_sphere_cull_patch_in++;
}
return qfalse;
}
/*
================
R_CullSurface
Tries to back face cull surfaces before they are lighted or
Tries to cull surfaces before they are lighted or
added to the sorting list.
This will also allow mirrors on both sides of a model without recursion.
================
*/
static qboolean R_CullSurface( surfaceType_t *surface, shader_t *shader ) {
srfSurfaceFace_t *sface;
static qboolean R_CullSurface( msurface_t *surf ) {
if ( r_nocull->integer || surf->cullinfo.type == CULLINFO_NONE) {
return qfalse;
}
if (surf->cullinfo.type & CULLINFO_PLANE)
{
// Only true for SF_FACE, so treat like its own function
float d;
if ( r_nocull->integer ) {
return qfalse;
}
if ( *surface == SF_GRID ) {
return R_CullGrid( (srfGridMesh_t *)surface );
}
if ( *surface == SF_TRIANGLES ) {
return R_CullTriSurf( (srfTriangles_t *)surface );
}
if ( *surface != SF_FACE ) {
return qfalse;
}
if ( shader->cullType == CT_TWO_SIDED ) {
return qfalse;
}
// face culling
if ( !r_facePlaneCull->integer ) {
return qfalse;
}
sface = ( srfSurfaceFace_t * ) surface;
d = DotProduct (tr.or.viewOrigin, sface->plane.normal);
if (surf->shader->cullType == CT_TWO_SIDED)
{
return qfalse;
}
d = DotProduct (tr.or.viewOrigin, surf->cullinfo.plane.normal);
// don't cull exactly on the plane, because there are levels of rounding
// through the BSP, ICD, and hardware that may cause pixel gaps if an
// epsilon isn't allowed here
if ( shader->cullType == CT_FRONT_SIDED ) {
if ( d < sface->plane.dist - 8 ) {
if ( surf->shader->cullType == CT_FRONT_SIDED ) {
if ( d < surf->cullinfo.plane.dist - 8 ) {
return qtrue;
}
} else {
if ( d > sface->plane.dist + 8 ) {
if ( d > surf->cullinfo.plane.dist + 8 ) {
return qtrue;
}
}
return qfalse;
}
if (surf->cullinfo.type & CULLINFO_SPHERE)
{
int sphereCull;
if ( tr.currentEntityNum != ENTITYNUM_WORLD ) {
sphereCull = R_CullLocalPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius );
} else {
sphereCull = R_CullPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius );
}
if ( sphereCull == CULL_OUT )
{
return qtrue;
}
if ( sphereCull == CULL_IN )
{
return qfalse;
}
}
if (surf->cullinfo.type & CULLINFO_BOX)
{
int boxCull;
if ( tr.currentEntityNum != ENTITYNUM_WORLD ) {
boxCull = R_CullLocalBox( surf->cullinfo.bounds );
} else {
boxCull = R_CullBox( surf->cullinfo.bounds );
}
if ( boxCull == CULL_OUT )
{
return qtrue;
}
if ( boxCull == CULL_IN )
{
return qfalse;
}
}
return qfalse;
}
static int R_DlightFace( srfSurfaceFace_t *face, int dlightBits ) {
float d;
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
d = DotProduct( dl->origin, face->plane.normal ) - face->plane.dist;
if ( d < -dl->radius || d > dl->radius ) {
// dlight doesn't reach the plane
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
face->dlightBits[ tr.smpFrame ] = dlightBits;
return dlightBits;
}
static int R_DlightGrid( srfGridMesh_t *grid, int dlightBits ) {
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
grid->dlightBits[ tr.smpFrame ] = dlightBits;
return dlightBits;
}
static int R_DlightTrisurf( srfTriangles_t *surf, int dlightBits ) {
// FIXME: more dlight culling to trisurfs...
surf->dlightBits[ tr.smpFrame ] = dlightBits;
return dlightBits;
#if 0
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
grid->dlightBits[ tr.smpFrame ] = dlightBits;
return dlightBits;
#endif
}
/*
====================
R_DlightSurface
@ -257,12 +124,52 @@ more dlights if possible.
====================
*/
static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
float d;
int i;
dlight_t *dl;
if ( surf->cullinfo.type & CULLINFO_PLANE )
{
int i;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
d = DotProduct( dl->origin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist;
if ( d < -dl->radius || d > dl->radius ) {
// dlight doesn't reach the plane
dlightBits &= ~( 1 << i );
}
}
}
else if ( surf->cullinfo.type & CULLINFO_BOX )
{
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if ( dl->origin[0] - dl->radius > surf->cullinfo.bounds[1][0]
|| dl->origin[0] + dl->radius < surf->cullinfo.bounds[0][0]
|| dl->origin[1] - dl->radius > surf->cullinfo.bounds[1][1]
|| dl->origin[1] + dl->radius < surf->cullinfo.bounds[0][1]
|| dl->origin[2] - dl->radius > surf->cullinfo.bounds[1][2]
|| dl->origin[2] + dl->radius < surf->cullinfo.bounds[0][2] ) {
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
}
if ( *surf->data == SF_FACE ) {
dlightBits = R_DlightFace( (srfSurfaceFace_t *)surf->data, dlightBits );
((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits;
} else if ( *surf->data == SF_GRID ) {
dlightBits = R_DlightGrid( (srfGridMesh_t *)surf->data, dlightBits );
((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits;
} else if ( *surf->data == SF_TRIANGLES ) {
dlightBits = R_DlightTrisurf( (srfTriangles_t *)surf->data, dlightBits );
((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits;
} else if ( *surf->data == SF_VBO_MESH ) {
((srfVBOMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits;
} else {
dlightBits = 0;
}
@ -274,23 +181,16 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
return dlightBits;
}
/*
======================
R_AddWorldSurface
======================
*/
static void R_AddWorldSurface( msurface_t *surf, int dlightBits ) {
if ( surf->viewCount == tr.viewCount ) {
return; // already in this view
}
surf->viewCount = tr.viewCount;
// FIXME: bmodel fog?
// try to cull before dlighting or adding
if ( R_CullSurface( surf->data, surf->shader ) ) {
if ( R_CullSurface( surf ) ) {
return;
}
@ -334,7 +234,13 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
R_DlightBmodel( bmodel );
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
R_AddWorldSurface( bmodel->firstSurface + i, tr.currentEntity->needDlights );
int surf = bmodel->firstSurface + i;
if (tr.world->surfacesViewCount[surf] != tr.viewCount)
{
tr.world->surfacesViewCount[surf] = tr.viewCount;
R_AddWorldSurface( tr.world->surfaces + surf, tr.currentEntity->needDlights );
}
}
}
@ -359,7 +265,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
int newDlights[2];
// if the node wasn't marked as potentially visible, exit
if (node->visframe != tr.visCount) {
if (node->visCounts[tr.visIndex] != tr.visCounts[tr.visIndex]) {
return;
}
@ -453,7 +359,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
{
// leaf node, so add mark surfaces
int c;
msurface_t *surf, **mark;
int surf, *view;
tr.pc.c_leafs++;
@ -478,15 +384,27 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
tr.viewParms.visBounds[1][2] = node->maxs[2];
}
// add the individual surfaces
mark = node->firstmarksurface;
// add merged and unmerged surfaces
if (tr.world->viewSurfaces)
view = tr.world->viewSurfaces + node->firstmarksurface;
else
view = tr.world->marksurfaces + node->firstmarksurface;
c = node->nummarksurfaces;
while (c--) {
// the surface may have already been added if it
// spans multiple leafs
surf = *mark;
R_AddWorldSurface( surf, dlightBits );
mark++;
// just mark it as visible, so we don't jump out of the cache derefencing the surface
surf = *view;
if (surf < 0)
{
tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount;
tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits;
}
else
{
tr.world->surfacesViewCount[surf] = tr.viewCount;
tr.world->surfacesDlightBits[surf] = dlightBits;
}
view++;
}
}
@ -583,12 +501,37 @@ static void R_MarkLeaves (void) {
// if the cluster is the same and the area visibility matrix
// hasn't changed, we don't need to mark everything again
for(i = 0; i < MAX_VISCOUNTS; i++)
{
if(tr.visClusters[i] == cluster)
{
//tr.visIndex = i;
break;
}
}
// if r_showcluster was just turned on, remark everything
if ( tr.viewCluster == cluster && !tr.refdef.areamaskModified
&& !r_showcluster->modified ) {
if(i != MAX_VISCOUNTS && !tr.refdef.areamaskModified && !r_showcluster->modified)// && !r_dynamicBspOcclusionCulling->modified)
{
if(tr.visClusters[i] != tr.visClusters[tr.visIndex] && r_showcluster->integer)
{
ri.Printf(PRINT_ALL, "found cluster:%i area:%i index:%i\n", cluster, leaf->area, i);
}
tr.visIndex = i;
return;
}
// if the areamask was modified, invalidate all visclusters
// this caused doors to open into undrawn areas
if (tr.refdef.areamaskModified)
{
memset(tr.visClusters, -2, sizeof(tr.visClusters));
}
tr.visIndex = (tr.visIndex + 1) % MAX_VISCOUNTS;
tr.visCounts[tr.visIndex]++;
tr.visClusters[tr.visIndex] = cluster;
if ( r_showcluster->modified || r_showcluster->integer ) {
r_showcluster->modified = qfalse;
if ( r_showcluster->integer ) {
@ -596,19 +539,18 @@ static void R_MarkLeaves (void) {
}
}
tr.visCount++;
tr.viewCluster = cluster;
if ( r_novis->integer || tr.viewCluster == -1 ) {
// set all nodes to visible if there is no vis
// this caused some levels to simply not render
if (r_novis->integer || !tr.world->vis || tr.visClusters[tr.visIndex] == -1) {
for (i=0 ; i<tr.world->numnodes ; i++) {
if (tr.world->nodes[i].contents != CONTENTS_SOLID) {
tr.world->nodes[i].visframe = tr.visCount;
tr.world->nodes[i].visCounts[tr.visIndex] = tr.visCounts[tr.visIndex];
}
}
return;
}
vis = R_ClusterPVS (tr.viewCluster);
vis = R_ClusterPVS(tr.visClusters[tr.visIndex]);
for (i=0,leaf=tr.world->nodes ; i<tr.world->numnodes ; i++, leaf++) {
cluster = leaf->cluster;
@ -628,9 +570,9 @@ static void R_MarkLeaves (void) {
parent = leaf;
do {
if (parent->visframe == tr.visCount)
if(parent->visCounts[tr.visIndex] == tr.visCounts[tr.visIndex])
break;
parent->visframe = tr.visCount;
parent->visCounts[tr.visIndex] = tr.visCounts[tr.visIndex];
parent = parent->parent;
} while (parent);
}
@ -660,9 +602,30 @@ void R_AddWorldSurfaces (void) {
// clear out the visible min/max
ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
// perform frustum culling and add all the potentially visible surfaces
// perform frustum culling and flag all the potentially visible surfaces
if ( tr.refdef.num_dlights > 32 ) {
tr.refdef.num_dlights = 32 ;
}
R_RecursiveWorldNode( tr.world->nodes, 15, ( 1 << tr.refdef.num_dlights ) - 1 );
// now add all the potentially visible surfaces
{
int i;
for (i = 0; i < tr.world->numWorldSurfaces; i++)
{
if (tr.world->surfacesViewCount[i] != tr.viewCount)
continue;
R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i] );
}
for (i = 0; i < tr.world->numMergedSurfaces; i++)
{
if (tr.world->mergedSurfacesViewCount[i] != tr.viewCount)
continue;
R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i] );
}
}
}

View file

@ -50,6 +50,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
typedef CGLContextObj QGLContext;
#define GLimp_GetCurrentContext() CGLGetCurrentContext()
#define GLimp_SetCurrentContext(ctx) CGLSetCurrentContext(ctx)
#elif defined(_WIN32)
typedef struct
{
HDC hDC; // handle to device context
HGLRC hGLRC; // handle to GL rendering context
} QGLContext_t;
typedef QGLContext_t QGLContext;
#else
typedef void *QGLContext;
#define GLimp_GetCurrentContext() (NULL)
@ -58,6 +65,40 @@ typedef void *QGLContext;
static QGLContext opengl_context;
#ifdef _WIN32
#include "SDL_syswm.h"
static QGLContext GLimp_GetCurrentContext(void)
{
SDL_SysWMinfo info;
QGLContext newcontext;
SDL_VERSION(&info.version);
if(!SDL_GetWMInfo(&info))
{
ri.Printf(PRINT_WARNING, "Failed to obtain HWND from SDL (InputRegistry)");
newcontext.hDC = 0;
newcontext.hGLRC = 0;
return newcontext;
}
newcontext.hDC = GetDC(info.window);
newcontext.hGLRC = info.hglrc;
return newcontext;
}
#ifdef SMP
static void GLimp_SetCurrentContext(qboolean enable)
{
if(enable)
wglMakeCurrent(opengl_context.hDC, opengl_context.hGLRC);
else
wglMakeCurrent(opengl_context.hDC, NULL);
}
#endif
#endif
typedef enum
{
RSERR_OK,
@ -83,6 +124,92 @@ void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
void (APIENTRYP qglUnlockArraysEXT) (void);
// GL_EXT_multi_draw_arrays
void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
// GL_ARB_vertex_shader
void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
GLint * size, GLenum * type, GLcharARB * name);
GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
// GL_ARB_vertex_program
void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid * pointer);
void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
// GL_ARB_vertex_buffer_object
void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
// GL_ARB_shader_objects
void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
const GLint * length);
void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
GLhandleARB * obj);
GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
GLint * size, GLenum * type, GLcharARB * name);
void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
#if defined(WIN32)
// WGL_ARB_create_context
HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList);
#endif
#if 0 //defined(__linux__)
// GLX_ARB_create_context
GLXContext (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
#endif
/*
===============
GLimp_Shutdown
@ -96,6 +223,7 @@ void GLimp_Shutdown( void )
screen = NULL;
Com_Memset( &glConfig, 0, sizeof( glConfig ) );
Com_Memset( &glRefConfig, 0, sizeof( glRefConfig ) );
Com_Memset( &glState, 0, sizeof( glState ) );
}
@ -119,6 +247,7 @@ GLimp_LogComment
*/
void GLimp_LogComment( char *comment )
{
//ri.Printf(PRINT_ALL, comment);
}
/*
@ -434,6 +563,76 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder)
break;
}
// try to initialize an OpenGL 3.1 context
#if 0 //defined(WIN32)
qwglCreateContextAttribsARB = SDL_GL_GetProcAddress("wglCreateContextAttribsARB");
if(qwglCreateContextAttribsARB)
{
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB,
3,
WGL_CONTEXT_MINOR_VERSION_ARB,
1,
WGL_CONTEXT_FLAGS_ARB,
0, //WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
//WGL_CONTEXT_PROFILE_MASK_ARB,
//WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
ri.Printf(PRINT_ALL, "Initializing OpenGL 3.1 context...");
opengl_context.hGLRC = qwglCreateContextAttribsARB(opengl_context.hDC, opengl_context.hGLRC, attribs);
if(wglMakeCurrent(opengl_context.hDC, opengl_context.hGLRC))
{
ri.Printf(PRINT_ALL, " done\n");
}
else
{
ri.Printf(PRINT_ALL, " failed\n");
}
}
#elif 0 //defined(__linux__)
// TODO
/*
// GLX_ARB_create_context
#ifndef GLX_ARB_create_context
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GLX_CONTEXT_FLAGS_ARB 0x2094
extern GLXContext (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
*/
qglXCreateContextAttribsARB = SDL_GL_GetProcAddress("glXCreateContextAttribsARB");
if(qglXCreateContextAttribsARB)
{
int attribs[3];
ri.Printf(PRINT_ALL, "Initializing OpenGL 3.0 context...");
attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attribs[1] = 3;
attribs[2] = 0; //terminate first pair
opengl_context->hGLRC = qglXCreateContextAttribsARB(opengl_context->, attribs);
if(wglMakeCurrent(opengl_context->hDC, opengl_context->hGLRC))
{
ri.Printf(PRINT_ALL, " done\n");
glConfig.driverType = GLDRV_OPENGL3;
}
else
{
ri.Printf(PRINT_ALL, " failed\n");
}
}
#endif
GLimp_DetectAvailableModes();
if (!vidscreen)
@ -659,19 +858,19 @@ static void GLimp_InitExtensions( void )
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
textureFilterAnisotropic = qfalse;
glRefConfig.textureFilterAnisotropic = qfalse;
if ( GLimp_HaveExtension( "GL_EXT_texture_filter_anisotropic" ) )
{
if ( r_ext_texture_filter_anisotropic->integer ) {
qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *)&maxAnisotropy );
if ( maxAnisotropy <= 0 ) {
qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *)&glRefConfig.maxAnisotropy );
if ( glRefConfig.maxAnisotropy <= 0 ) {
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" );
maxAnisotropy = 0;
glRefConfig.maxAnisotropy = 0;
}
else
{
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", maxAnisotropy );
textureFilterAnisotropic = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", glRefConfig.maxAnisotropy );
glRefConfig.textureFilterAnisotropic = qtrue;
}
}
else
@ -683,6 +882,205 @@ static void GLimp_InitExtensions( void )
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
}
// GL_EXT_multi_draw_arrays
glRefConfig.multiDrawArrays = qfalse;
qglMultiDrawArraysEXT = NULL;
qglMultiDrawElementsEXT = NULL;
if( GLimp_HaveExtension( "GL_EXT_multi_draw_arrays"))
{
qglMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawArraysEXT");
qglMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawElementsEXT");
ri.Printf(PRINT_ALL, "...using GL_EXT_multi_draw_arrays\n");
glRefConfig.multiDrawArrays = qtrue;
}
else
{
ri.Printf(PRINT_ALL, "...GL_EXT_multi_draw_arrays not found\n");
}
// GL_ARB_vertex_program
glRefConfig.vertexProgram = qfalse;
qglVertexAttrib4fARB = NULL;
qglVertexAttrib4fvARB = NULL;
qglVertexAttribPointerARB = NULL;
qglEnableVertexAttribArrayARB = NULL;
qglDisableVertexAttribArrayARB = NULL;
if( GLimp_HaveExtension( "GL_ARB_vertex_program"))
{
qglVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fARB");
qglVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fvARB");
qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) SDL_GL_GetProcAddress("glVertexAttribPointerARB");
qglEnableVertexAttribArrayARB =
(PFNGLENABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArrayARB");
qglDisableVertexAttribArrayARB =
(PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArrayARB");
ri.Printf(PRINT_ALL, "...using GL_ARB_vertex_program\n");
glRefConfig.vertexProgram = qtrue;
}
else
{
ri.Printf(PRINT_ALL, "...GL_ARB_vertex_program not found\n");
}
// GL_ARB_vertex_buffer_object
glRefConfig.vertexBufferObject = qfalse;
qglBindBufferARB = NULL;
qglDeleteBuffersARB = NULL;
qglGenBuffersARB = NULL;
qglIsBufferARB = NULL;
qglBufferDataARB = NULL;
qglBufferSubDataARB = NULL;
qglGetBufferSubDataARB = NULL;
qglGetBufferParameterivARB = NULL;
qglGetBufferPointervARB = NULL;
if( GLimp_HaveExtension( "GL_ARB_vertex_buffer_object"))
{
qglBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
qglIsBufferARB = (PFNGLISBUFFERARBPROC) SDL_GL_GetProcAddress("glIsBufferARB");
qglBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB");
qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glGetBufferSubDataARB");
qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetBufferParameterivARB");
qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) SDL_GL_GetProcAddress("glGetBufferPointervARB");
ri.Printf(PRINT_ALL, "...using GL_ARB_vertex_buffer_object\n");
glRefConfig.vertexBufferObject = qtrue;
}
else
{
ri.Printf(PRINT_ALL, "...GL_ARB_vertex_buffer_object not found\n");
}
// GL_ARB_shader_objects
glRefConfig.shaderObjects = qfalse;
qglDeleteObjectARB = NULL;
qglGetHandleARB = NULL;
qglDetachObjectARB = NULL;
qglCreateShaderObjectARB = NULL;
qglShaderSourceARB = NULL;
qglCompileShaderARB = NULL;
qglCreateProgramObjectARB = NULL;
qglAttachObjectARB = NULL;
qglLinkProgramARB = NULL;
qglUseProgramObjectARB = NULL;
qglValidateProgramARB = NULL;
qglUniform1fARB = NULL;
qglUniform2fARB = NULL;
qglUniform3fARB = NULL;
qglUniform4fARB = NULL;
qglUniform1iARB = NULL;
qglUniform2iARB = NULL;
qglUniform3iARB = NULL;
qglUniform4iARB = NULL;
qglUniform2fvARB = NULL;
qglUniform3fvARB = NULL;
qglUniform4fvARB = NULL;
qglUniform2ivARB = NULL;
qglUniform3ivARB = NULL;
qglUniform4ivARB = NULL;
qglUniformMatrix2fvARB = NULL;
qglUniformMatrix3fvARB = NULL;
qglUniformMatrix4fvARB = NULL;
qglGetObjectParameterfvARB = NULL;
qglGetObjectParameterivARB = NULL;
qglGetInfoLogARB = NULL;
qglGetAttachedObjectsARB = NULL;
qglGetUniformLocationARB = NULL;
qglGetActiveUniformARB = NULL;
qglGetUniformfvARB = NULL;
qglGetUniformivARB = NULL;
qglGetShaderSourceARB = NULL;
if( GLimp_HaveExtension( "GL_ARB_shader_objects"))
{
qglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
qglGetHandleARB = (PFNGLGETHANDLEARBPROC) SDL_GL_GetProcAddress("glGetHandleARB");
qglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) SDL_GL_GetProcAddress("glDetachObjectARB");
qglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
qglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
qglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
qglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
qglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
qglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
qglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
qglValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) SDL_GL_GetProcAddress("glValidateProgramARB");
qglUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB");
qglUniform2fARB = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB");
qglUniform3fARB = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB");
qglUniform4fARB = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB");
qglUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB");
qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB");
qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB");
qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB");
qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB");
qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB");
qglUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) SDL_GL_GetProcAddress("glUniform2ivARB");
qglUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) SDL_GL_GetProcAddress("glUniform3ivARB");
qglUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) SDL_GL_GetProcAddress("glUniform4ivARB");
qglUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix2fvARB");
qglUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix3fvARB");
qglUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix4fvARB");
qglGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterfvARB");
qglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
qglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
qglGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) SDL_GL_GetProcAddress("glGetAttachedObjectsARB");
qglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
qglGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB");
qglGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) SDL_GL_GetProcAddress("glGetUniformfvARB");
qglGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) SDL_GL_GetProcAddress("glGetUniformivARB");
qglGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glGetShaderSourceARB");
ri.Printf(PRINT_ALL, "...using GL_ARB_shader_objects\n");
glRefConfig.shaderObjects = qtrue;
}
else
{
ri.Printf(PRINT_ALL, "...GL_ARB_shader_objects not found\n");
}
// GL_ARB_vertex_shader
glRefConfig.vertexShader = qfalse;
qglBindAttribLocationARB = NULL;
qglGetActiveAttribARB = NULL;
qglGetAttribLocationARB = NULL;
if( GLimp_HaveExtension( "GL_ARB_vertex_shader"))
{
int reservedComponents;
//qglGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig.maxVertexUniforms);
//qglGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &glConfig.maxVaryingFloats);
//qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig.maxVertexAttribs);
reservedComponents = 16 * 10; // approximation how many uniforms we have besides the bone matrices
#if 0
if(glConfig.driverType == GLDRV_MESA)
{
// HACK
// restrict to number of vertex uniforms to 512 because of:
// xreal.x86_64: nv50_program.c:4181: nv50_program_validate_data: Assertion `p->param_nr <= 512' failed
glConfig.maxVertexUniforms = Q_bound(0, glConfig.maxVertexUniforms, 512);
}
#endif
//glConfig.maxVertexSkinningBones = (int) Q_bound(0.0, (Q_max(glConfig.maxVertexUniforms - reservedComponents, 0) / 16), MAX_BONES);
//glConfig.vboVertexSkinningAvailable = r_vboVertexSkinning->integer && ((glConfig.maxVertexSkinningBones >= 12) ? qtrue : qfalse);
qglBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB");
qglGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) SDL_GL_GetProcAddress("glGetActiveAttribARB");
qglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetAttribLocationARB");
ri.Printf(PRINT_ALL, "...using GL_ARB_vertex_shader\n");
glRefConfig.vertexShader = qtrue;
}
else
{
ri.Printf(PRINT_ALL, "...GL_ARB_vertex_shader not found\n");
}
glRefConfig.glsl = glRefConfig.vertexProgram && glRefConfig.shaderObjects && glRefConfig.vertexShader;
}
#define R_MODE_FALLBACK 3 // 640 * 480
@ -750,12 +1148,40 @@ success:
glConfig.deviceSupportsGamma = SDL_SetGamma( 1.0f, 1.0f, 1.0f ) >= 0;
// get our config strings
{
char *string;
string = (char *) qglGetString (GL_VENDOR);
if (string)
Q_strncpyz( glConfig.vendor_string, (char *) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
else
glConfig.vendor_string[0] = '\0';
string = (char *) qglGetString (GL_RENDERER);
if (string)
Q_strncpyz( glConfig.renderer_string, (char *) qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
else
glConfig.renderer_string[0] = '\0';
if (*glConfig.renderer_string && glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] == '\n')
glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] = 0;
string = (char *) qglGetString(GL_VERSION);
if (string)
Q_strncpyz( glConfig.version_string, (char *) qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
Q_strncpyz( glConfig.extensions_string, (char *) qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
else
glConfig.version_string[0] = '\0';
string = (char *) qglGetString (GL_EXTENSIONS);
if (string)
{
Q_strncpyz( glConfig.extensions_string, string, sizeof( glConfig.extensions_string ) );
}
else
{
glConfig.extensions_string[0] = '\0';
}
}
// initialize extensions
GLimp_InitExtensions( );