diff options
Diffstat (limited to 'src/refresh/gl/state.c')
-rw-r--r-- | src/refresh/gl/state.c | 427 |
1 files changed, 277 insertions, 150 deletions
diff --git a/src/refresh/gl/state.c b/src/refresh/gl/state.c index 732c103..3d8c6b4 100644 --- a/src/refresh/gl/state.c +++ b/src/refresh/gl/state.c @@ -21,89 +21,45 @@ with this program; if not, write to the Free Software Foundation, Inc., glState_t gls; -void GL_BindTexture(int texnum) +// for uploading +void GL_ForceTexture(GLuint tmu, GLuint texnum) { -#ifdef _DEBUG - if (gl_nobind->integer && !gls.tmu) { - texnum = TEXNUM_DEFAULT; - } -#endif + GL_ActiveTexture(tmu); - if (gls.texnum[gls.tmu] == texnum) { + if (gls.texnums[tmu] == texnum) { return; } qglBindTexture(GL_TEXTURE_2D, texnum); - gls.texnum[gls.tmu] = texnum; + gls.texnums[tmu] = texnum; c.texSwitches++; } -void GL_SelectTMU(int tmu) +// for drawing +void GL_BindTexture(GLuint tmu, GLuint texnum) { - if (gls.tmu == tmu) { - return; - } - - if (tmu < 0 || tmu >= gl_config.numTextureUnits) { - Com_Error(ERR_FATAL, "GL_SelectTMU: bad tmu %d", tmu); +#ifdef _DEBUG + if (gl_nobind->integer && !tmu) { + texnum = TEXNUM_DEFAULT; } +#endif - qglActiveTextureARB(GL_TEXTURE0_ARB + tmu); - qglClientActiveTextureARB(GL_TEXTURE0_ARB + tmu); - - gls.tmu = tmu; -} - -void GL_TexEnv(GLenum texenv) -{ - if (gls.texenv[gls.tmu] == texenv) { + if (gls.texnums[tmu] == texnum) { return; } - switch (texenv) { - case GL_REPLACE: - case GL_MODULATE: - case GL_BLEND: - case GL_ADD: - qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texenv); - break; - default: - Com_Error(ERR_FATAL, "GL_TexEnv: bad texenv"); - break; - } - - gls.texenv[gls.tmu] = texenv; -} + GL_ActiveTexture(tmu); -void GL_CullFace(glCullFace_t cull) -{ - if (gls.cull == cull) { - return; - } - switch (cull) { - case GLS_CULL_DISABLE: - qglDisable(GL_CULL_FACE); - break; - case GLS_CULL_FRONT: - qglEnable(GL_CULL_FACE); - qglCullFace(GL_FRONT); - break; - case GLS_CULL_BACK: - qglEnable(GL_CULL_FACE); - qglCullFace(GL_BACK); - break; - default: - Com_Error(ERR_FATAL, "GL_CullFace: bad cull"); - break; - } + qglBindTexture(GL_TEXTURE_2D, texnum); + gls.texnums[tmu] = texnum; - gls.cull = cull; + c.texSwitches++; } -void GL_Bits(glStateBits_t bits) +void GL_StateBits(glStateBits_t bits) { - glStateBits_t diff = bits ^ gls.bits; + glStateBits_t diff = bits ^ gls.state_bits; if (!diff) { return; @@ -148,17 +104,165 @@ void GL_Bits(glStateBits_t bits) } } - gls.bits = bits; + if (diff & GLS_TEXTURE_REPLACE) { + GL_ActiveTexture(0); + if (bits & GLS_TEXTURE_REPLACE) { + qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } else { + qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + } + + if (diff & GLS_FLOW_ENABLE) { + GL_ActiveTexture(0); + qglMatrixMode(GL_TEXTURE); + + if (bits & GLS_FLOW_ENABLE) { + float scaled, scroll; + + if (bits & GLS_WARP_ENABLE) { + scaled = glr.fd.time * 0.5f; + scroll = -scaled; + } else { + scaled = glr.fd.time / 40; + scroll = -64 * (scaled - (int)scaled); + } + + qglTranslatef(scroll, 0, 0); + } else { + qglLoadIdentity(); + } + + qglMatrixMode(GL_MODELVIEW); + } + + if (diff & GLS_LIGHTMAP_ENABLE) { + GL_ActiveTexture(1); + if (bits & GLS_LIGHTMAP_ENABLE) { + qglEnable(GL_TEXTURE_2D); + } else { + qglDisable(GL_TEXTURE_2D); + } + } + + if ((diff & GLS_WARP_ENABLE) && gl_static.prognum_warp) { + if (bits & GLS_WARP_ENABLE) { + vec4_t param; + + qglEnable(GL_FRAGMENT_PROGRAM_ARB); + qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp); + param[0] = glr.fd.time; + param[1] = glr.fd.time; + param[2] = param[3] = 0; + qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param); + } else { + qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); + qglDisable(GL_FRAGMENT_PROGRAM_ARB); + } + } + + if (diff & GLS_CULL_DISABLE) { + if (bits & GLS_CULL_DISABLE) { + qglDisable(GL_CULL_FACE); + } else { + qglEnable(GL_CULL_FACE); + } + } + + if (diff & GLS_SHADE_SMOOTH) { + if (bits & GLS_SHADE_SMOOTH) { + qglShadeModel(GL_SMOOTH); + } else { + qglShadeModel(GL_FLAT); + } + } + + gls.state_bits = bits; } -void GL_Setup2D(void) +void GL_ArrayBits(glArrayBits_t bits) { - qglViewport(0, 0, r_config.width, r_config.height); + glArrayBits_t diff = bits ^ gls.array_bits; + + if (!diff) { + return; + } + + if (diff & GLA_VERTEX) { + if (bits & GLA_VERTEX) { + qglEnableClientState(GL_VERTEX_ARRAY); + } else { + qglDisableClientState(GL_VERTEX_ARRAY); + } + } + + if (diff & GLA_TC) { + GL_ClientActiveTexture(0); + if (bits & GLA_TC) { + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + } else { + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + + if (diff & GLA_LMTC) { + GL_ClientActiveTexture(1); + if (bits & GLA_LMTC) { + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + } else { + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + + if (diff & GLA_COLOR) { + if (bits & GLA_COLOR) { + qglEnableClientState(GL_COLOR_ARRAY); + } else { + qglDisableClientState(GL_COLOR_ARRAY); + } + } + + gls.array_bits = bits; +} + +void GL_Ortho(GLfloat xmin, GLfloat xmax, GLfloat ymin, GLfloat ymax, GLfloat znear, GLfloat zfar) +{ + GLfloat width, height, depth; + GLfloat matrix[16]; + + width = xmax - xmin; + height = ymax - ymin; + depth = zfar - znear; + + matrix[0] = 2 / width; + matrix[4] = 0; + matrix[8] = 0; + matrix[12] = -(xmax + xmin) / width; + + matrix[1] = 0; + matrix[5] = 2 / height; + matrix[9] = 0; + matrix[13] = -(ymax + ymin) / height; + + matrix[2] = 0; + matrix[6] = 0; + matrix[10] = -2 / depth; + matrix[14] = -(zfar + znear) / depth; + + matrix[3] = 0; + matrix[7] = 0; + matrix[11] = 0; + matrix[15] = 1; qglMatrixMode(GL_PROJECTION); - qglLoadIdentity(); + qglLoadMatrixf(matrix); +} - qglOrtho(0, r_config.width, r_config.height, 0, -1, 1); +void GL_Setup2D(void) +{ + qglViewport(0, 0, r_config.width, r_config.height); + + GL_Ortho(0, r_config.width, r_config.height, 0, -1, 1); draw.scale = 1; draw.colors[0].u32 = U32_WHITE; @@ -172,63 +276,99 @@ void GL_Setup2D(void) qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); - - GL_Bits(GLS_DEPTHTEST_DISABLE); - GL_CullFace(GLS_CULL_DISABLE); } -void GL_Setup3D(void) +static void GL_Frustum(void) { - GLdouble xmin, xmax, ymin, ymax, zfar; - int yb = glr.fd.y + glr.fd.height; + GLfloat xmin, xmax, ymin, ymax, zfar, znear; + GLfloat width, height, depth; + GLfloat matrix[16]; - qglViewport(glr.fd.x, r_config.height - yb, - glr.fd.width, glr.fd.height); + znear = gl_znear->value; - qglMatrixMode(GL_PROJECTION); - qglLoadIdentity(); + if (glr.fd.rdflags & RDF_NOWORLDMODEL) + zfar = 2048; + else + zfar = gl_static.world.size * 2; - ymax = gl_znear->value * tan(glr.fd.fov_y * M_PI / 360.0); + ymax = znear * tan(glr.fd.fov_y * M_PI / 360.0); ymin = -ymax; - xmax = gl_znear->value * tan(glr.fd.fov_x * M_PI / 360.0); + xmax = znear * tan(glr.fd.fov_x * M_PI / 360.0); xmin = -xmax; - if (glr.fd.rdflags & RDF_NOWORLDMODEL) - zfar = 2048; - else - zfar = gl_static.world.size * 2; + width = xmax - xmin; + height = ymax - ymin; + depth = zfar - znear; - qglFrustum(xmin, xmax, ymin, ymax, gl_znear->value, zfar); + matrix[0] = 2 * znear / width; + matrix[4] = 0; + matrix[8] = (xmax + xmin) / width; + matrix[12] = 0; - qglMatrixMode(GL_MODELVIEW); + matrix[1] = 0; + matrix[5] = 2 * znear / height; + matrix[9] = (ymax + ymin) / height; + matrix[13] = 0; + + matrix[2] = 0; + matrix[6] = 0; + matrix[10] = -(zfar + znear) / depth; + matrix[14] = -2 * zfar * znear / depth; + + matrix[3] = 0; + matrix[7] = 0; + matrix[11] = -1; + matrix[15] = 0; + + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(matrix); +} + +static void GL_RotateForViewer(void) +{ + GLfloat *matrix = glr.viewmatrix; AnglesToAxis(glr.fd.viewangles, glr.viewaxis); - glr.viewmatrix[0] = -glr.viewaxis[1][0]; - glr.viewmatrix[4] = -glr.viewaxis[1][1]; - glr.viewmatrix[8] = -glr.viewaxis[1][2]; - glr.viewmatrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg); + matrix[0] = -glr.viewaxis[1][0]; + matrix[4] = -glr.viewaxis[1][1]; + matrix[8] = -glr.viewaxis[1][2]; + matrix[12] = DotProduct(glr.viewaxis[1], glr.fd.vieworg); - glr.viewmatrix[1] = glr.viewaxis[2][0]; - glr.viewmatrix[5] = glr.viewaxis[2][1]; - glr.viewmatrix[9] = glr.viewaxis[2][2]; - glr.viewmatrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg); + matrix[1] = glr.viewaxis[2][0]; + matrix[5] = glr.viewaxis[2][1]; + matrix[9] = glr.viewaxis[2][2]; + matrix[13] = -DotProduct(glr.viewaxis[2], glr.fd.vieworg); - glr.viewmatrix[2] = -glr.viewaxis[0][0]; - glr.viewmatrix[6] = -glr.viewaxis[0][1]; - glr.viewmatrix[10] = -glr.viewaxis[0][2]; - glr.viewmatrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg); + matrix[2] = -glr.viewaxis[0][0]; + matrix[6] = -glr.viewaxis[0][1]; + matrix[10] = -glr.viewaxis[0][2]; + matrix[14] = DotProduct(glr.viewaxis[0], glr.fd.vieworg); - glr.viewmatrix[3] = 0; - glr.viewmatrix[7] = 0; - glr.viewmatrix[11] = 0; - glr.viewmatrix[15] = 1; + matrix[3] = 0; + matrix[7] = 0; + matrix[11] = 0; + matrix[15] = 1; - qglLoadMatrixf(glr.viewmatrix); + qglMatrixMode(GL_MODELVIEW); + qglLoadMatrixf(matrix); - GL_Bits(GLS_DEFAULT); - GL_CullFace(GLS_CULL_BACK); + // forced matrix upload + gls.currentmatrix = matrix; +} + +void GL_Setup3D(void) +{ + qglViewport(glr.fd.x, r_config.height - (glr.fd.y + glr.fd.height), + glr.fd.width, glr.fd.height); + + GL_Frustum(); + + GL_RotateForViewer(); + + // enable depth writes before clearing + GL_StateBits(GLS_DEFAULT); qglClear(GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit); } @@ -246,22 +386,35 @@ void GL_SetDefaultState(void) qglDisable(GL_BLEND); qglDisable(GL_ALPHA_TEST); qglAlphaFunc(GL_GREATER, 0.666f); - qglFrontFace(GL_CW); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + qglFrontFace(GL_CW); + qglCullFace(GL_BACK); + qglEnable(GL_CULL_FACE); + qglShadeModel(GL_FLAT); + + if (qglActiveTextureARB && qglClientActiveTextureARB) { + qglActiveTextureARB(GL_TEXTURE1_ARB); + qglBindTexture(GL_TEXTURE_2D, 0); + qglDisable(GL_TEXTURE_2D); + qglClientActiveTextureARB(GL_TEXTURE1_ARB); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + qglActiveTextureARB(GL_TEXTURE0_ARB); + qglBindTexture(GL_TEXTURE_2D, 0); + qglEnable(GL_TEXTURE_2D); + qglClientActiveTextureARB(GL_TEXTURE0_ARB); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } else { + qglBindTexture(GL_TEXTURE_2D, 0); + qglEnable(GL_TEXTURE_2D); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + } - qglActiveTextureARB(GL_TEXTURE1_ARB); - qglClientActiveTextureARB(GL_TEXTURE1_ARB); - qglBindTexture(GL_TEXTURE_2D, 0); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - - qglActiveTextureARB(GL_TEXTURE0_ARB); - qglClientActiveTextureARB(GL_TEXTURE0_ARB); - qglBindTexture(GL_TEXTURE_2D, 0); - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + qglMatrixMode(GL_TEXTURE); + qglLoadIdentity(); + qglMatrixMode(GL_MODELVIEW); - qglEnableClientState(GL_VERTEX_ARRAY); + qglDisableClientState(GL_VERTEX_ARRAY); qglDisableClientState(GL_COLOR_ARRAY); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | gl_static.stencil_buffer_bit); @@ -287,45 +440,19 @@ byte *IMG_ReadPixels(qboolean reverse, int *width, int *height) void GL_EnableOutlines(void) { - if (gls.fp_enabled) { - qglDisable(GL_FRAGMENT_PROGRAM_ARB); - } - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_BindTexture(0, TEXNUM_WHITE); + GL_StateBits(GLS_DEFAULT); + GL_ArrayBits(GLA_VERTEX); + qglColor4f(1, 1, 1, 1); + qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); qglDepthRange(0, 0); - qglColor4f(1, 1, 1, 1); } void GL_DisableOutlines(void) { qglDepthRange(0, 1); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglEnable(GL_TEXTURE_2D); - if (gls.fp_enabled) { - qglEnable(GL_FRAGMENT_PROGRAM_ARB); - } -} - -void GL_EnableWarp(void) -{ - vec4_t param; - - qglEnable(GL_FRAGMENT_PROGRAM_ARB); - qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gl_static.prognum_warp); - param[0] = glr.fd.time; - param[1] = glr.fd.time; - param[2] = param[3] = 0; - qglProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, param); - gls.fp_enabled = qtrue; -} - -void GL_DisableWarp(void) -{ - qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); - qglDisable(GL_FRAGMENT_PROGRAM_ARB); - gls.fp_enabled = qfalse; } void GL_InitPrograms(void) @@ -345,7 +472,8 @@ void GL_InitPrograms(void) Cvar_Set("gl_fragment_program", "0"); } - if (!qglProgramStringARB) { + if (!qglGenProgramsARB || !qglBindProgramARB || + !qglProgramStringARB || !qglDeleteProgramsARB) { return; } @@ -379,4 +507,3 @@ void GL_ShutdownPrograms(void) QGL_ShutdownExtensions(QGL_ARB_fragment_program); gl_config.ext_enabled &= ~QGL_ARB_fragment_program; } - |