X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_backend.c;h=9ef466a94e605eb96b37ee1a04caffd5f89f4c6c;hb=2a0508542fefcd4635626511f844f2fb0909ce09;hp=d953b47b92f46ee19a1671f07183ee457b9fec83;hpb=94adef9176f6ea2f948d9fdcc51288d07e502e2e;p=xonotic%2Fdarkplaces.git diff --git a/gl_backend.c b/gl_backend.c index d953b47b..9ef466a9 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -9,13 +9,15 @@ cvar_t gl_mesh_prefer_short_elements = {0, "gl_mesh_prefer_short_elements", "1", cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"}; cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"}; -cvar_t r_render = {0, "r_render", "1", "enables rendering calls (you want this on!)"}; +cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"}; +cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"}; cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"}; cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"}; cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"}; cvar_t gl_lockarrays = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"}; cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"}; cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"}; +cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"}; cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"}; qboolean v_flipped_state = false; @@ -64,6 +66,11 @@ void GL_PrintError(int errornumber, char *filename, int linenumber) case GL_TABLE_TOO_LARGE: Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber); break; +#endif +#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT + case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: + Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber); + break; #endif default: Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber); @@ -76,10 +83,9 @@ void GL_PrintError(int errornumber, char *filename, int linenumber) void SCR_ScreenShot_f (void); -static matrix4x4_t backend_viewmatrix; +static r_viewport_t backend_viewport; static matrix4x4_t backend_modelmatrix; static matrix4x4_t backend_modelviewmatrix; -static matrix4x4_t backend_projectmatrix; static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive; @@ -246,6 +252,7 @@ void gl_backend_init(void) } Cvar_RegisterVariable(&r_render); + Cvar_RegisterVariable(&r_renderview); Cvar_RegisterVariable(&r_waterwarp); Cvar_RegisterVariable(&gl_polyblend); Cvar_RegisterVariable(&v_flipped); @@ -255,9 +262,6 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_vbo); Cvar_RegisterVariable(&gl_paranoid); Cvar_RegisterVariable(&gl_printcheckerror); -#ifdef NORENDER - Cvar_SetValue("r_render", 0); -#endif Cvar_RegisterVariable(&gl_mesh_drawrangeelements); Cvar_RegisterVariable(&gl_mesh_testarrayelement); @@ -271,183 +275,31 @@ void gl_backend_init(void) void GL_SetMirrorState(qboolean state); -void GL_SetupView_Orientation_Identity (void) -{ - backend_viewmatrix = identitymatrix; - GL_SetMirrorState(false); - memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix)); -} - -void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix) +void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out) { - matrix4x4_t tempmatrix, basematrix; - Matrix4x4_Invert_Full(&tempmatrix, matrix); - Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0); - Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1); - Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix); - - GL_SetMirrorState(v_flipped.integer); - if(v_flipped_state) - { - Matrix4x4_Transpose(&basematrix, &backend_viewmatrix); - Matrix4x4_ConcatScale3(&basematrix, -1, 1, 1); - Matrix4x4_Transpose(&backend_viewmatrix, &basematrix); - } - - //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0); - //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0); - //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1); - //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]); - - // force an update of the model matrix by copying it off, resetting it, and then calling the R_Mesh_Matrix function with it - tempmatrix = backend_modelmatrix; - memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix)); - R_Mesh_Matrix(&tempmatrix); -} - -static void GL_BuildFrustum(double m[16], double left, double right, double bottom, double top, double nearVal, double farVal) -{ - m[0] = 2 * nearVal / (right - left); - m[1] = 0; - m[2] = 0; - m[3] = 0; - - m[4] = 0; - m[5] = 2 * nearVal / (top - bottom); - m[6] = 0; - m[7] = 0; - - m[8] = (right + left) / (right - left); - m[9] = (top + bottom) / (top - bottom); - m[10] = - (farVal + nearVal) / (farVal - nearVal); - m[11] = -1; - - m[12] = 0; - m[13] = 0; - m[14] = - 2 * farVal * nearVal / (farVal - nearVal); - m[15] = 0; -} - -void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar) -{ - double m[16]; - - // set up viewpoint - CHECKGLERROR - qglMatrixMode(GL_PROJECTION);CHECKGLERROR - // set view pyramid -#if 1 - // avoid glGetDoublev whenever possible, it may stall the render pipeline - // in the tested cases (nvidia) no measurable fps difference, but it sure - // makes a difference over a network line with GLX - GL_BuildFrustum(m, -frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar); - qglLoadMatrixd(m);CHECKGLERROR -#else - qglLoadIdentity();CHECKGLERROR - qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR - qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR -#endif - Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m); - qglMatrixMode(GL_MODELVIEW);CHECKGLERROR - GL_SetupView_Orientation_Identity(); - CHECKGLERROR -} - -void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear) -{ - double nudge, m[16]; - - // set up viewpoint - CHECKGLERROR - qglMatrixMode(GL_PROJECTION);CHECKGLERROR - qglLoadIdentity();CHECKGLERROR - // set view pyramid - nudge = 1.0 - 1.0 / (1<<23); - m[ 0] = 1.0 / frustumx; - m[ 1] = 0; - m[ 2] = 0; - m[ 3] = 0; - m[ 4] = 0; - m[ 5] = 1.0 / frustumy; - m[ 6] = 0; - m[ 7] = 0; - m[ 8] = 0; - m[ 9] = 0; - m[10] = -nudge; - m[11] = -1; - m[12] = 0; - m[13] = 0; - m[14] = -2 * zNear * nudge; - m[15] = 0; - qglLoadMatrixd(m);CHECKGLERROR - qglMatrixMode(GL_MODELVIEW);CHECKGLERROR - GL_SetupView_Orientation_Identity(); - CHECKGLERROR - Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m); -} - -static void GL_BuildOrtho(double m[16], double left, double right, double bottom, double top, double zNear, double zFar) -{ - m[0] = 2/(right - left); - m[1] = 0; - m[2] = 0; - m[3] = 0; - - m[4] = 0; - m[5] = 2/(top - bottom); - m[6] = 0; - m[7] = 0; - - m[8] = 0; - m[9] = 0; - m[10] = -2/(zFar - zNear); - m[11] = 0; - - m[12] = - (right + left)/(right - left); - m[13] = - (top + bottom)/(top - bottom); - m[14] = - (zFar + zNear)/(zFar - zNear); - m[15] = 1; -} - -void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar) -{ - double m[16]; - - // set up viewpoint - CHECKGLERROR - qglMatrixMode(GL_PROJECTION);CHECKGLERROR -#if 1 - // avoid glGetDoublev whenever possible, it may stall the render pipeline - // in the tested cases (nvidia) no measurable fps difference, but it sure - // makes a difference over a network line with GLX - GL_BuildOrtho(m, x1, x2, y2, y1, zNear, zFar); - qglLoadMatrixd(m);CHECKGLERROR -#else - qglLoadIdentity();CHECKGLERROR - qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR - qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR -#endif - Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m); - qglMatrixMode(GL_MODELVIEW);CHECKGLERROR - GL_SetupView_Orientation_Identity(); - CHECKGLERROR + vec4_t temp; + float iw; + Matrix4x4_Transform4 (&v->viewmatrix, in, temp); + Matrix4x4_Transform4 (&v->projectmatrix, temp, out); + iw = 1.0f / out[3]; + out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f; + out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f; + out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f; } -void GL_SetupView_ApplyCustomNearClipPlane(double normalx, double normaly, double normalz, double dist) +static void R_Viewport_ApplyNearClipPlane(r_viewport_t *v, double normalx, double normaly, double normalz, double dist) { - double matrix[16]; double q[4]; double d; float clipPlane[4], v3[3], v4[3]; float normal[3]; - // This is Olique Depth Projection from http://www.terathon.com/code/oblique.php - // modified to fit in this codebase. + // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php VectorSet(normal, normalx, normaly, normalz); - Matrix4x4_Transform3x3(&backend_viewmatrix, normal, clipPlane); + Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane); VectorScale(normal, dist, v3); - Matrix4x4_Transform(&backend_viewmatrix, v3, v4); + Matrix4x4_Transform(&v->viewmatrix, v3, v4); // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique clipPlane[3] = -DotProduct(v4, clipPlane); @@ -468,28 +320,281 @@ void GL_SetupView_ApplyCustomNearClipPlane(double normalx, double normaly, doubl // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and // transform it into camera space by multiplying it // by the inverse of the projection matrix - Matrix4x4_ToArrayDoubleGL(&backend_projectmatrix, matrix); - - q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + matrix[8]) / matrix[0]; - q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + matrix[9]) / matrix[5]; + q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + v->m[8]) / v->m[0]; + q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + v->m[9]) / v->m[5]; q[2] = -1.0f; - q[3] = (1.0f + matrix[10]) / matrix[14]; + q[3] = (1.0f + v->m[10]) / v->m[14]; // Calculate the scaled plane vector d = 2.0f / DotProduct4(clipPlane, q); // Replace the third row of the projection matrix - matrix[2] = clipPlane[0] * d; - matrix[6] = clipPlane[1] * d; - matrix[10] = clipPlane[2] * d + 1.0f; - matrix[14] = clipPlane[3] * d; + v->m[2] = clipPlane[0] * d; + v->m[6] = clipPlane[1] * d; + v->m[10] = clipPlane[2] * d + 1.0f; + v->m[14] = clipPlane[3] * d; +} + +void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, double x1, double y1, double x2, double y2, double nearclip, double farclip, const double *nearplane) +{ + float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip; + memset(v, 0, sizeof(*v)); + v->type = R_VIEWPORTTYPE_ORTHO; + v->cameramatrix = *cameramatrix; + v->x = x; + v->y = y; + v->z = 0; + v->width = width; + v->height = height; + v->depth = 1; + v->m[0] = 2/(right - left); + v->m[5] = 2/(top - bottom); + v->m[10] = -2/(zFar - zNear); + v->m[12] = - (right + left)/(right - left); + v->m[13] = - (top + bottom)/(top - bottom); + v->m[14] = - (zFar + zNear)/(zFar - zNear); + v->m[15] = 1; + + Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix); + Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m); + + if (nearplane) + R_Viewport_ApplyNearClipPlane(v, nearplane[0], nearplane[1], nearplane[2], nearplane[3]); - // Load it back into OpenGL +#if 0 + { + vec4_t test1; + vec4_t test2; + Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f); + R_Viewport_TransformToScreen(v, test1, test2); + Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]); + } +#endif +} + +void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, double frustumx, double frustumy, double nearclip, double farclip, const double *nearplane) +{ + matrix4x4_t tempmatrix, basematrix; + memset(v, 0, sizeof(*v)); + + if(v_flipped.integer) + frustumx = -frustumx; + + v->type = R_VIEWPORTTYPE_PERSPECTIVE; + v->cameramatrix = *cameramatrix; + v->x = x; + v->y = y; + v->z = 0; + v->width = width; + v->height = height; + v->depth = 1; + v->m[0] = 1.0 / frustumx; + v->m[5] = 1.0 / frustumy; + v->m[10] = -(farclip + nearclip) / (farclip - nearclip); + v->m[11] = -1; + v->m[14] = -2 * nearclip * farclip / (farclip - nearclip); + + Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix); + Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0); + Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1); + Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); + + Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m); + + if (nearplane) + R_Viewport_ApplyNearClipPlane(v, nearplane[0], nearplane[1], nearplane[2], nearplane[3]); +} + +void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, double frustumx, double frustumy, double nearclip, const double *nearplane) +{ + matrix4x4_t tempmatrix, basematrix; + const double nudge = 1.0 - 1.0 / (1<<23); + memset(v, 0, sizeof(*v)); + + if(v_flipped.integer) + frustumx = -frustumx; + + v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP; + v->cameramatrix = *cameramatrix; + v->x = x; + v->y = y; + v->z = 0; + v->width = width; + v->height = height; + v->depth = 1; + v->m[ 0] = 1.0 / frustumx; + v->m[ 5] = 1.0 / frustumy; + v->m[10] = -nudge; + v->m[11] = -1; + v->m[14] = -2 * nearclip * nudge; + + Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix); + Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0); + Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1); + Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); + + Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m); + + if (nearplane) + R_Viewport_ApplyNearClipPlane(v, nearplane[0], nearplane[1], nearplane[2], nearplane[3]); +} + +float cubeviewmatrix[6][16] = +{ + // standard cubemap projections + { // +X + 0, 0,-1, 0, + 0,-1, 0, 0, + -1, 0, 0, 0, + 0, 0, 0, 1, + }, + { // -X + 0, 0, 1, 0, + 0,-1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + }, + { // +Y + 1, 0, 0, 0, + 0, 0,-1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1, + }, + { // -Y + 1, 0, 0, 0, + 0, 0, 1, 0, + 0,-1, 0, 0, + 0, 0, 0, 1, + }, + { // +Z + 1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0,-1, 0, + 0, 0, 0, 1, + }, + { // -Z + -1, 0, 0, 0, + 0,-1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }, +}; +float rectviewmatrix[6][16] = +{ + // sign-preserving cubemap projections + { // +X + 0, 0,-1, 0, + 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + }, + { // -X + 0, 0, 1, 0, + 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + }, + { // +Y + 1, 0, 0, 0, + 0, 0,-1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1, + }, + { // -Y + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1, + }, + { // +Z + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0,-1, 0, + 0, 0, 0, 1, + }, + { // -Z + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }, +}; + +void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane) +{ + matrix4x4_t tempmatrix, basematrix; + memset(v, 0, sizeof(*v)); + v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE; + v->cameramatrix = *cameramatrix; + v->width = size; + v->height = size; + v->depth = 1; + v->m[0] = v->m[5] = 1.0f; + v->m[10] = -(farclip + nearclip) / (farclip - nearclip); + v->m[11] = -1; + v->m[14] = -2 * nearclip * farclip / (farclip - nearclip); + + Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]); + Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix); + Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); + Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m); + + if (nearplane) + R_Viewport_ApplyNearClipPlane(v, nearplane[0], nearplane[1], nearplane[2], nearplane[3]); +} + +void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane) +{ + matrix4x4_t tempmatrix, basematrix; + if (border > size - 2) + border = size - 2; + memset(v, 0, sizeof(*v)); + v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE; + v->cameramatrix = *cameramatrix; + v->x = (side & 1) * size; + v->y = (side >> 1) * size; + v->width = size; + v->height = size; + v->depth = 1; + v->m[0] = v->m[5] = 1.0f * ((float)size - border) / size; + v->m[10] = -(farclip + nearclip) / (farclip - nearclip); + v->m[11] = -1; + v->m[14] = -2 * nearclip * farclip / (farclip - nearclip); + + Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]); + Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix); + Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); + Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m); + + if (nearplane) + R_Viewport_ApplyNearClipPlane(v, nearplane[0], nearplane[1], nearplane[2], nearplane[3]); +} + +void R_SetViewport(const r_viewport_t *v) +{ + float glmatrix[16]; + backend_viewport = *v; + + CHECKGLERROR + qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR + + // Load the projection matrix into OpenGL qglMatrixMode(GL_PROJECTION);CHECKGLERROR - qglLoadMatrixd(matrix);CHECKGLERROR + qglLoadMatrixd(backend_viewport.m);CHECKGLERROR qglMatrixMode(GL_MODELVIEW);CHECKGLERROR - CHECKGLERROR - Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, matrix); + + // FIXME: v_flipped_state is evil, this probably breaks somewhere + GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP)); + + // directly force an update of the modelview matrix + Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewport.viewmatrix, &backend_modelmatrix); + Matrix4x4_ToArrayFloatGL(&backend_modelviewmatrix, glmatrix); + qglLoadMatrixf(glmatrix);CHECKGLERROR +} + +void R_GetViewport(r_viewport_t *v) +{ + *v = backend_viewport; } typedef struct gltextureunit_s @@ -497,7 +602,7 @@ typedef struct gltextureunit_s const void *pointer_texcoord; size_t pointer_texcoord_offset; int pointer_texcoord_buffer; - int t1d, t2d, t3d, tcubemap; + int t1d, t2d, t3d, tcubemap, trectangle; int arrayenabled; unsigned int arraycomponents; int rgbscale, alphascale; @@ -603,6 +708,10 @@ void GL_SetupTextureState(void) { qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR } + if (gl_texturerectangle) + { + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR + } } for (i = 0;i < backendarrayunits;i++) @@ -626,6 +735,10 @@ void GL_SetupTextureState(void) { qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR } + if (gl_texturerectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } qglMatrixMode(GL_TEXTURE);CHECKGLERROR qglLoadIdentity();CHECKGLERROR qglMatrixMode(GL_MODELVIEW);CHECKGLERROR @@ -696,6 +809,12 @@ void GL_Backend_ResetState(void) qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } + if (gl_support_ext_framebuffer_object) + { + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR @@ -924,7 +1043,7 @@ void GL_LockArrays(int first, int count) qglUnlockArraysEXT(); CHECKGLERROR } - if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer) + if (count && gl_supportslockarrays && gl_lockarrays.integer) { gl_state.lockrange_first = first; gl_state.lockrange_count = count; @@ -938,7 +1057,7 @@ void GL_LockArrays(int first, int count) void GL_Scissor (int x, int y, int width, int height) { CHECKGLERROR - qglScissor(x, vid.height - (y + height),width,height); + qglScissor(x, y,width,height); CHECKGLERROR } @@ -961,18 +1080,6 @@ void GL_Clear(int mask) qglClear(mask);CHECKGLERROR } -void GL_TransformToScreen(const vec4_t in, vec4_t out) -{ - vec4_t temp; - float iw; - Matrix4x4_Transform4 (&backend_viewmatrix, in, temp); - Matrix4x4_Transform4 (&backend_projectmatrix, temp, out); - iw = 1.0f / out[3]; - out[0] = r_refdef.view.x + (out[0] * iw + 1.0f) * r_refdef.view.width * 0.5f; - out[1] = r_refdef.view.y + r_refdef.view.height - (out[1] * iw + 1.0f) * r_refdef.view.height * 0.5f; - out[2] = r_refdef.view.z + (out[2] * iw + 1.0f) * r_refdef.view.depth * 0.5f; -} - // called at beginning of frame void R_Mesh_Start(void) { @@ -1091,7 +1198,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri if (numvertices < 3 || numtriangles < 1) { if (numvertices < 0 || numtriangles < 0 || developer.integer >= 100) - Con_Printf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %i, %i);\n", firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, bufferobject3i, bufferobject3s); + Con_Printf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %i, %i);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3s, bufferobject3i, bufferobject3s); return; } if (!gl_mesh_prefer_short_elements.integer) @@ -1183,7 +1290,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri } CHECKGLERROR } - if (r_render.integer) + if (r_render.integer || r_refdef.draw2dstage) { CHECKGLERROR if (gl_mesh_testmanualfeeding.integer) @@ -1279,7 +1386,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(bufferobject3s); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3]))); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3]))); CHECKGLERROR } else @@ -1293,7 +1400,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(bufferobject3i); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3]))); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3]))); CHECKGLERROR } else @@ -1307,7 +1414,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(0); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_SHORT, element3s); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s); CHECKGLERROR } else @@ -1321,7 +1428,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri GL_BindEBO(0); if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { - qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, element3i); + qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i); CHECKGLERROR } else @@ -1355,6 +1462,10 @@ void R_Mesh_Finish(void) { qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR } + if (gl_texturerectangle) + { + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR + } } for (i = 0;i < backendarrayunits;i++) { @@ -1374,6 +1485,10 @@ void R_Mesh_Finish(void) { qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR } + if (gl_texturerectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR if (gl_combine.integer) { @@ -1407,7 +1522,7 @@ int R_Mesh_CreateStaticBufferObject(unsigned int target, void *data, size_t size } qglBufferDataARB(target, size, data, GL_STATIC_DRAW_ARB); - info = Mem_ExpandableArray_AllocRecord(&gl_bufferobjectinfoarray); + info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_AllocRecord(&gl_bufferobjectinfoarray); memset(info, 0, sizeof(*info)); info->target = target; info->object = bufferobject; @@ -1427,7 +1542,7 @@ void R_Mesh_DestroyBufferObject(int bufferobject) endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray); for (i = 0;i < endindex;i++) { - info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i); + info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i); if (!info) continue; if (info->object == bufferobject) @@ -1447,7 +1562,7 @@ void GL_Mesh_ListVBOs(qboolean printeach) endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray); for (i = 0;i < endindex;i++) { - info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i); + info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i); if (!info) continue; switch(info->target) @@ -1464,18 +1579,18 @@ void R_Mesh_Matrix(const matrix4x4_t *matrix) { if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t))) { - double glmatrix[16]; + float glmatrix[16]; backend_modelmatrix = *matrix; - Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix); - Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix); + Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewport.viewmatrix, &backend_modelmatrix); + Matrix4x4_ToArrayFloatGL(&backend_modelviewmatrix, glmatrix); CHECKGLERROR - qglLoadMatrixd(glmatrix);CHECKGLERROR + qglLoadMatrixf(glmatrix);CHECKGLERROR } } void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset) { - if (!gl_vbo.integer) + if (!gl_vbo.integer || gl_mesh_testarrayelement.integer) bufferobject = 0; if (gl_state.pointer_vertex != vertex3f || gl_state.pointer_vertex_buffer != bufferobject || gl_state.pointer_vertex_offset != bufferoffset) { @@ -1495,7 +1610,7 @@ void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferof // means that a valid vbo may be supplied even if there is no color array. if (color4f) { - if (!gl_vbo.integer) + if (!gl_vbo.integer || gl_mesh_testarrayelement.integer) bufferobject = 0; // caller wants color array enabled if (!gl_state.pointer_color_enabled) @@ -1537,7 +1652,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, co // that involve a valid bufferobject also supply a texcoord array if (texcoord) { - if (!gl_vbo.integer) + if (!gl_vbo.integer || gl_mesh_testarrayelement.integer) bufferobject = 0; // texture array unit is enabled, enable the array if (!unit->arrayenabled) @@ -1570,7 +1685,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, co } } -void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap) +void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap, int texrectangle) { gltextureunit_t *unit = gl_state.units + unitnum; if (unitnum >= backendimageunits) @@ -1671,6 +1786,30 @@ void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, in unit->tcubemap = texcubemap; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle != texrectangle) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (texrectangle) + { + if (unit->trectangle == 0) + { + qglEnable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + else + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + } + unit->trectangle = texrectangle; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } void R_Mesh_TexBind1D(unsigned int unitnum, int texnum) @@ -1744,6 +1883,20 @@ void R_Mesh_TexBind1D(unsigned int unitnum, int texnum) unit->tcubemap = 0; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + unit->trectangle = 0; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } void R_Mesh_TexBind(unsigned int unitnum, int texnum) @@ -1817,6 +1970,20 @@ void R_Mesh_TexBind(unsigned int unitnum, int texnum) unit->tcubemap = 0; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle != 0) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + unit->trectangle = 0; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } void R_Mesh_TexBind3D(unsigned int unitnum, int texnum) @@ -1890,6 +2057,20 @@ void R_Mesh_TexBind3D(unsigned int unitnum, int texnum) unit->tcubemap = 0; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle != 0) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + unit->trectangle = 0; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum) @@ -1963,6 +2144,107 @@ void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum) unit->tcubemap = texnum; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle != 0) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + unit->trectangle = 0; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } +} + +void R_Mesh_TexBindRectangle(unsigned int unitnum, int texnum) +{ + gltextureunit_t *unit = gl_state.units + unitnum; + if (unitnum >= backendimageunits) + return; + // update 1d texture binding + if (unit->t1d) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->t1d) + { + qglDisable(GL_TEXTURE_1D);CHECKGLERROR + } + } + unit->t1d = 0; + qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR + } + // update 2d texture binding + if (unit->t2d) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->t2d) + { + qglDisable(GL_TEXTURE_2D);CHECKGLERROR + } + } + unit->t2d = 0; + qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR + } + // update 3d texture binding + if (unit->t3d) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->t3d) + { + qglDisable(GL_TEXTURE_3D);CHECKGLERROR + } + } + unit->t3d = 0; + qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR + } + // update cubemap texture binding + if (unit->tcubemap != 0) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (unit->tcubemap) + { + qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR + } + } + unit->tcubemap = 0; + qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR + } + // update rectangle texture binding + if (unit->trectangle != texnum) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + if (texnum) + { + if (unit->trectangle == 0) + { + qglEnable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + else + { + if (unit->trectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + } + } + unit->trectangle = texnum; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } static const double gl_identitymatrix[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; @@ -2069,7 +2351,7 @@ void R_Mesh_TextureState(const rmeshstate_t *m) } for (i = 0;i < backendimageunits;i++) - R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]); + R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i], m->texrectangle[i]); for (i = 0;i < backendarrayunits;i++) { if (m->pointer_texcoord3f[i]) @@ -2146,6 +2428,17 @@ void R_Mesh_ResetTextureState(void) unit->tcubemap = 0; qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + // update rectangle texture binding + if (unit->trectangle) + { + GL_ActiveTexture(unitnum); + if (unitnum < backendunits) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + } + unit->trectangle = 0; + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } for (unitnum = 0;unitnum < backendarrayunits;unitnum++) {