mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-10 07:11:36 +00:00
Adding the new renderer
This commit is contained in:
parent
2b5d779adf
commit
615d28dd92
29 changed files with 8977 additions and 835 deletions
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
//===========================================================================
|
||||
|
||||
|
|
|
@ -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
|
@ -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 ) );
|
||||
|
|
|
@ -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;
|
||||
|
|
125
reaction/code/renderer/tr_extramath.c
Normal file
125
reaction/code/renderer/tr_extramath.c
Normal 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;
|
||||
}
|
57
reaction/code/renderer/tr_extramath.h
Normal file
57
reaction/code/renderer/tr_extramath.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
1138
reaction/code/renderer/tr_glsl.c
Normal file
1138
reaction/code/renderer/tr_glsl.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
785
reaction/code/renderer/tr_vbo.c
Normal file
785
reaction/code/renderer/tr_vbo.c
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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( );
|
||||
|
|
Loading…
Reference in a new issue