/* ============= R_ShadowPassSetupGL ============= */ static void R_ShadowPassSetupGL( const plight_t *pl ) { // matrices already computed RI.worldviewMatrix = pl->modelviewMatrix; RI.projectionMatrix = pl->projectionMatrix; RI.worldviewProjectionMatrix = RI.projectionMatrix.Concat( RI.worldviewMatrix ); GLfloat dest[16]; // tell engine about worldviewprojection matrix so TriWorldToScreen and TriScreenToWorld // will be working properly RI.worldviewProjectionMatrix.CopyToArray( dest ); SET_ENGINE_WORLDVIEW_MATRIX( dest ); pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); GL_Cull( GL_FRONT ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); pglEnable( GL_POLYGON_OFFSET_FILL ); pglDisable( GL_TEXTURE_2D ); pglDepthMask( GL_TRUE ); pglPolygonOffset( 8, 30 ); pglEnable( GL_DEPTH_TEST ); pglDisable( GL_ALPHA_TEST ); pglDisable( GL_BLEND ); }
/* ============= R_SetupGL ============= */ static void R_SetupGL( void ) { if( RI.refdef.waterlevel >= 3 ) { float f; f = sin( cl.time * 0.4f * ( M_PI * 2.7f )); RI.refdef.fov_x += f; RI.refdef.fov_y -= f; } R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); // if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); if( RI.params & RP_CLIPPLANE ) { GLdouble clip[4]; mplane_t *p = &RI.clipPlane; clip[0] = p->normal[0]; clip[1] = p->normal[1]; clip[2] = p->normal[2]; clip[3] = -p->dist; pglClipPlane( GL_CLIP_PLANE0, clip ); pglEnable( GL_CLIP_PLANE0 ); } if( RI.params & RP_FLIPFRONTFACE ) GL_FrontFace( !glState.frontFace ); GL_Cull( GL_FRONT ); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); }
/* ============== R_ShadowBlend Draws projection shadow(s) from stenciled volume ============== */ void R_ShadowBlend (float shadowalpha) { const vec4_t color[4] = { {0, 0, 0, shadowalpha}, {0, 0, 0, shadowalpha}, {0, 0, 0, shadowalpha}, {0, 0, 0, shadowalpha} }; static const vec3_t verts[4] = { {10, 100, 100}, {10, -100, 100}, {10, -100, -100}, {10, 100, -100} }; static const uint32_t indices[6] = { 0, 1, 2, 0, 2, 3 }; if (r_shadows->value != 3) return; GL_PushMatrix(GL_MODELVIEW); GL_LoadMatrix(GL_MODELVIEW, glState.axisRotation); GL_Disable (GL_ALPHA_TEST); GL_Enable (GL_BLEND); GL_Disable (GL_DEPTH_TEST); GL_DisableTexture(0); GL_StencilFunc(GL_NOTEQUAL, 0, 255); glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); GL_Enable(GL_STENCIL_TEST); rb_vertex = rb_index = 0; memcpy(indexArray, indices, sizeof(indices)); memcpy(vertexArray, verts, sizeof(vec3_t) * 4); memcpy(colorArray, color, sizeof(vec4_t) * 4); rb_index += 6; rb_vertex += 4; RB_RenderMeshGeneric (false); GL_PopMatrix(GL_MODELVIEW); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Disable (GL_BLEND); GL_EnableTexture(0); GL_Enable (GL_DEPTH_TEST); GL_Disable(GL_STENCIL_TEST); //GL_Enable (GL_ALPHA_TEST); glColor4f(1,1,1,1); }
/* ============= R_LoadIdentity ============= */ void R_LoadIdentity( void ) { if( tr.modelviewIdentity ) return; Matrix4x4_LoadIdentity( RI.objectMatrix ); Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.modelviewMatrix ); tr.modelviewIdentity = true; }
/* =============== R_Set2DMode =============== */ void R_Set2DMode( qboolean enable ) { if( enable ) { if( glState.in2DMode ) return; // set 2D virtual screen size pglScissor( 0, 0, glState.width, glState.height ); pglViewport( 0, 0, glState.width, glState.height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); pglOrtho( 0, glState.width, glState.height, 0, -99999, 99999 ); pglMatrixMode( GL_MODELVIEW ); pglLoadIdentity(); GL_Cull( 0 ); pglDepthMask( GL_FALSE ); pglDisable( GL_DEPTH_TEST ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glState.in2DMode = true; RI.currententity = NULL; RI.currentmodel = NULL; } else { pglDepthMask( GL_TRUE ); pglEnable( GL_DEPTH_TEST ); glState.in2DMode = false; pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); } }
/* ============= R_TranslateForEntity ============= */ void R_TranslateForEntity( cl_entity_t *e ) { float scale = 1.0f; if( e == clgame.entities || R_StaticEntity( e )) { R_LoadIdentity(); return; } if( e->model->type != mod_brush && e->curstate.scale > 0.0f ) scale = e->curstate.scale; Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, scale ); Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.modelviewMatrix ); tr.modelviewIdentity = false; }
static void SetPerspectiveMatrix() { float r, l, t, b; float fovx, fovy; float m[4][4]; fovx = viewstate.fov * (PI / 360.0f); float x = (renderwidth / 2.0f) / atan(fovx); fovy = atan2(renderheight / 2.0f, x); // Calcuate right, left, top and bottom values r = viewstate.znear * fovx; l = -r; t = viewstate.znear * fovy; b = -t; m[0][0] = (2.0f * viewstate.znear) / (r - l); m[1][0] = 0; m[2][0] = (r + l) / (r - l); m[3][0] = 0; m[0][1] = 0; m[1][1] = (2.0f * viewstate.znear) / (t - b); m[2][1] = (t + b) / (t - b); m[3][1] = 0; m[0][2] = 0; m[1][2] = 0; m[2][2] = -(viewstate.zfar + viewstate.znear) / (viewstate.zfar - viewstate.znear); m[3][2] = -2.0f * viewstate.zfar * viewstate.znear / (viewstate.zfar - viewstate.znear); m[0][3] = 0; m[1][3] = 0; m[2][3] = -1; m[3][3] = 0; glMatrixMode(GL_PROJECTION); GL_LoadMatrix(m); }
void R_VR_DrawHud() { float fov = vr_hud_fov->value; float depth = vr_hud_depth->value; int numsegments = vr_hud_segments->value; int index = 0; vec_t mat[4][4], temp[4][4]; if (!vr_enabled->value) return; // enable alpha testing so only pixels that have alpha info get written out // prevents black pixels from being rendered into the view GL_Enable(GL_ALPHA_TEST); GL_AlphaFunc(GL_GREATER, 0.0f); // if hud transparency is enabled, enable blending if (vr_hud_transparency->value) { GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // bind the texture GL_MBind(0, hud.texture); // disable this for the loading screens since they are not at 60fps if ((vr_hud_bounce->value > 0) && !loadingScreen && ((int32_t) vr_aimmode->value > 0)) { // load the quaternion directly into a rotation matrix vec4_t q; VR_GetOrientationEMAQuat(q); q[2] = -q[2]; QuatToRotation(q, mat); } else { // identity matrix TranslationMatrix(0,0,0,mat); } // set proper mode // glEnableClientState (GL_TEXTURE_COORD_ARRAY); // glEnableClientState (GL_VERTEX_ARRAY); glDisableClientState (GL_COLOR_ARRAY); // bind vertex buffer and set tex coord parameters R_BindIVBO(&hudVBO,NULL,0); glTexCoordPointer(2,GL_FLOAT,sizeof(vert_t),(void *)( sizeof(GL_FLOAT) * 3)); glVertexPointer(3,GL_FLOAT,sizeof(vert_t),NULL); for (index = 0; index < 2; index++) { // bind the eye FBO R_BindFBO(vrState.eyeFBO[index]); // set the perspective matrix for that eye R_PerspectiveScale(vrState.renderParams[index].projection, 0.24, 251.0); // build the eye translation matrix if (vr_autoipd->value) { TranslationMatrix(-vrState.renderParams[index].viewOffset[0], vrState.renderParams[index].viewOffset[1], vrState.renderParams[index].viewOffset[2], temp); } else { float viewOffset = (vr_ipd->value / 2000.0); TranslationMatrix((-1 + index * 2) * -viewOffset, 0, 0, temp); } // load the view matrix MatrixMultiply(temp, mat, temp); GL_LoadMatrix(GL_MODELVIEW, temp); // draw the hud for that eye R_DrawIVBO(&hudVBO); } // teardown R_ReleaseIVBO(); GL_MBind(0, 0); glEnableClientState (GL_COLOR_ARRAY); glTexCoordPointer (2, GL_FLOAT, sizeof(texCoordArray[0][0]), texCoordArray[0][0]); glVertexPointer (3, GL_FLOAT, sizeof(vertexArray[0]), vertexArray[0]); GL_Disable(GL_BLEND); GL_Disable(GL_ALPHA_TEST); }
void R_DrawAliasModel (entity_t *ent, aliashdr_t *hdr, aliasstate_t *state, qbool showtris) { int v; trivertx_t *verts1, *verts2; float blend, iblend; qbool lerping; aliasmesh_t *mesh; trivertx_t *trivert1; trivertx_t *trivert2; float lerpnormal[3]; float alias_forward[3], alias_right[3], alias_up[3]; float r_plightvec[3], lightvec[3] = {-1, 0, 0}; r_aliasmesh_t *r_aliasmesh; float *r_aliasst; // hack the depth range to prevent view model from poking into walls if (ent->renderfx & RF_WEAPONMODEL) qglDepthRange (QGL_DEPTH_3D_BEGIN, QGL_DEPTH_VM_END); ent->angles[0] = -ent->angles[0]; // stupid quake bug AngleVectors (ent->angles, alias_forward, alias_right, alias_up); ent->angles[0] = -ent->angles[0]; // stupid quake bug // rotate the lighting vector into the model's frame of reference r_plightvec[0] = DotProduct (lightvec, alias_forward); r_plightvec[1] = -DotProduct (lightvec, alias_right); r_plightvec[2] = DotProduct (lightvec, alias_up); // go back to the world matrix GL_LoadMatrix (&ent->matrix, &r_world_matrix); if (state->origin[0] || state->origin[1] || state->origin[2]) GL_TranslateMatrix (&ent->matrix, state->origin[0], state->origin[1], state->origin[2]); if (state->angles[1]) GL_RotateMatrix (&ent->matrix, state->angles[1], 0, 0, 1); if (state->angles[0]) GL_RotateMatrix (&ent->matrix, -state->angles[0], 0, 1, 0); if (state->angles[2]) GL_RotateMatrix (&ent->matrix, state->angles[2], 1, 0, 0); GL_TranslateMatrix (&ent->matrix, hdr->scale_origin[0], hdr->scale_origin[1], hdr->scale_origin[2]); GL_ScaleMatrix (&ent->matrix, hdr->scale[0], hdr->scale[1], hdr->scale[2]); qglLoadMatrixf (ent->matrix.m16); r_aliasmesh = (r_aliasmesh_t *) r_meshbuffer; r_aliasst = (float *) (r_aliasmesh + hdr->numverts); mesh = (aliasmesh_t *) ((byte *) hdr + hdr->aliasmesh); if (state->pose1 != state->pose2) { lerping = true; verts1 = (trivertx_t *) ((byte *) hdr + hdr->vertexes + hdr->framevertexsize * state->pose1); verts2 = (trivertx_t *) ((byte *) hdr + hdr->vertexes + hdr->framevertexsize * state->pose2); blend = state->blend; iblend = 1.0f - blend; } else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled { lerping = false; verts1 = (trivertx_t *) ((byte *) hdr + hdr->vertexes + hdr->framevertexsize * state->pose1); verts2 = verts1; blend = iblend = 0; // avoid bogus compiler warning } GL_SetStreamSource (GLSTREAM_POSITION, 3, GL_FLOAT, sizeof (r_aliasmesh_t), r_aliasmesh->xyz); GL_SetStreamSource (GLSTREAM_COLOR, 4, GL_FLOAT, sizeof (r_aliasmesh_t), r_aliasmesh->rgba); if (showtris) { GL_SetStreamSource (GLSTREAM_TEXCOORD0, 0, GL_NONE, 0, NULL); GL_SetStreamSource (GLSTREAM_TEXCOORD1, 0, GL_NONE, 0, NULL); } else { GL_SetStreamSource (GLSTREAM_TEXCOORD0, 2, GL_FLOAT, 0, r_aliasst); if (state->fb) GL_SetStreamSource (GLSTREAM_TEXCOORD1, 2, GL_FLOAT, 0, r_aliasst); else GL_SetStreamSource (GLSTREAM_TEXCOORD1, 0, GL_NONE, 0, NULL); } GL_SetStreamSource (GLSTREAM_TEXCOORD2, 0, GL_NONE, 0, NULL); if (lerping) { for (v = 0; v < hdr->numverts; v++, r_aliasmesh++, mesh++) { trivert1 = &verts1[mesh->vertindex]; trivert2 = &verts2[mesh->vertindex]; // interpolate the normals lerpnormal[0] = r_avertexnormals[trivert1->lightnormalindex][0] * iblend + r_avertexnormals[trivert2->lightnormalindex][0] * blend; lerpnormal[1] = r_avertexnormals[trivert1->lightnormalindex][1] * iblend + r_avertexnormals[trivert2->lightnormalindex][1] * blend; lerpnormal[2] = r_avertexnormals[trivert1->lightnormalindex][2] * iblend + r_avertexnormals[trivert2->lightnormalindex][2] * blend; mesh->light = DotProduct (lerpnormal, r_plightvec) * -0.5f + 1.0f; r_aliasmesh->xyz[0] = trivert1->v[0] * iblend + trivert2->v[0] * blend; r_aliasmesh->xyz[1] = trivert1->v[1] * iblend + trivert2->v[1] * blend; r_aliasmesh->xyz[2] = trivert1->v[2] * iblend + trivert2->v[2] * blend; } } else { for (v = 0; v < hdr->numverts; v++, r_aliasmesh++, mesh++) { trivert1 = &verts1[mesh->vertindex]; mesh->light = DotProduct (r_avertexnormals[trivert1->lightnormalindex], r_plightvec) * -0.5f + 1.0f; r_aliasmesh->xyz[0] = trivert1->v[0]; r_aliasmesh->xyz[1] = trivert1->v[1]; r_aliasmesh->xyz[2] = trivert1->v[2]; } } // reset these for lighting r_aliasmesh = (r_aliasmesh_t *) r_meshbuffer; r_aliasst = (float *) (r_aliasmesh + hdr->numverts); mesh = (aliasmesh_t *) ((byte *) hdr + hdr->aliasmesh); if (showtris) { for (v = 0; v < hdr->numverts; v++, r_aliasmesh++, mesh++) { r_aliasmesh->rgba[0] = 1; r_aliasmesh->rgba[1] = 1; r_aliasmesh->rgba[2] = 1; r_aliasmesh->rgba[3] = 1; } } else { for (v = 0; v < hdr->numverts; v++, r_aliasmesh++, mesh++, r_aliasst += 2) { r_aliasst[0] = mesh->st[0]; r_aliasst[1] = mesh->st[1]; r_aliasmesh->rgba[0] = state->shadelight[0] * mesh->light; r_aliasmesh->rgba[1] = state->shadelight[1] * mesh->light; r_aliasmesh->rgba[2] = state->shadelight[2] * mesh->light; r_aliasmesh->rgba[3] = state->shadelight[3]; } } // for testing of light shading // glDisable (GL_TEXTURE_2D); GL_SetIndices (((byte *) hdr + hdr->indexes)); GL_DrawIndexedPrimitive (GL_TRIANGLES, hdr->numindexes, hdr->numverts); // glEnable (GL_TEXTURE_2D); // restore normal depth range if (ent->renderfx & RF_WEAPONMODEL) qglDepthRange (QGL_DEPTH_3D_BEGIN, QGL_DEPTH_3D_END); }
void R_DrawAliasShadows (entity_t **ents, int numents, void *meshbuffer) { if (r_shadows.value > 0.01f) { int i; qbool stateset = false; byte shadecolor[4] = {0, 0, 0, 128}; // extern int gl_stencilbits; for (i = 0; i < numents; i++) { entity_t *ent = ents[i]; glmatrix eshadow; if (!(ent->model->flags & MOD_NOSHADOW)) { aliasstate_t *state = &ent->aliasstate; aliashdr_t *hdr = Mod_Extradata (ent->model); float lheight = state->origin[2] - state->lightspot[2]; if (!stateset) { float *mesh = (float *) meshbuffer; qglDepthMask (GL_FALSE); qglEnable (GL_BLEND); GL_TexEnv (GL_TEXTURE1_ARB, GL_TEXTURE_2D, GL_NONE); GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_NONE); qglColor4f (0, 0, 0, r_shadows.value); shadecolor[3] = BYTE_CLAMPF (r_shadows.value); /* if (gl_stencilbits) { qglEnable (GL_STENCIL_TEST); qglStencilFunc (GL_EQUAL, 1, 2); qglStencilOp (GL_KEEP, GL_KEEP, GL_INCR); } */ GL_SetStreamSource (GLSTREAM_POSITION, 3, GL_FLOAT, sizeof (float) * 4, mesh); GL_SetStreamSource (GLSTREAM_COLOR, 4, GL_UNSIGNED_BYTE, sizeof (float) * 4, &mesh[3]); GL_SetStreamSource (GLSTREAM_TEXCOORD0, 0, GL_NONE, 0, NULL); GL_SetStreamSource (GLSTREAM_TEXCOORD1, 0, GL_NONE, 0, NULL); GL_SetStreamSource (GLSTREAM_TEXCOORD2, 0, GL_NONE, 0, NULL); stateset = true; } GL_LoadMatrix (&eshadow, &r_world_matrix); if (state->origin[0] || state->origin[1] || state->origin[2]) GL_TranslateMatrix (&eshadow, state->origin[0], state->origin[1], state->origin[2]); GL_TranslateMatrix (&eshadow, 0, 0, -lheight); GL_MultiplyMatrix (&eshadow, &shadowmatrix, &eshadow); GL_TranslateMatrix (&eshadow, 0, 0, lheight); if (state->angles[1]) GL_RotateMatrix (&eshadow, state->angles[1], 0, 0, 1); GL_TranslateMatrix (&eshadow, hdr->scale_origin[0], hdr->scale_origin[1], hdr->scale_origin[2]); GL_ScaleMatrix (&eshadow, hdr->scale[0], hdr->scale[1], hdr->scale[2]); qglLoadMatrixf (eshadow.m16); R_DrawAliasShadow (ent, hdr, state, (float *) meshbuffer, (float *) shadecolor); } } if (stateset) { /* if (gl_stencilbits) qglDisable (GL_STENCIL_TEST); */ GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_REPLACE); qglDisable (GL_BLEND); qglDepthMask (GL_TRUE); qglColor4f (1, 1, 1, 1); qglLoadMatrixf (r_world_matrix.m16); } } }
/* ============= R_SetupGL ============= */ static void R_SetupGL( void ) { if( r_underwater_distortion->value && RI.refdef.waterlevel >= 3 ) { float f; f = sin( cl.time * r_underwater_distortion->value * ( M_PI * 2.7f )); RI.refdef.fov_x += f; RI.refdef.fov_y -= f; } R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); // if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); if( RP_NORMALPASS( )) { int x, x2, y, y2; // set up viewport (main, playersetup) x = floor( RI.viewport[0] * glState.width / glState.width ); x2 = ceil(( RI.viewport[0] + RI.viewport[2] ) * glState.width / glState.width ); y = floor( glState.height - RI.viewport[1] * glState.height / glState.height ); y2 = ceil( glState.height - ( RI.viewport[1] + RI.viewport[3] ) * glState.height / glState.height ); pglViewport( x, y2, x2 - x, y - y2 ); } else { // envpass, mirrorpass pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); } pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); if( RI.params & RP_CLIPPLANE ) { GLdouble clip[4]; mplane_t *p = &RI.clipPlane; clip[0] = p->normal[0]; clip[1] = p->normal[1]; clip[2] = p->normal[2]; clip[3] = -p->dist; pglClipPlane( GL_CLIP_PLANE0, clip ); pglEnable( GL_CLIP_PLANE0 ); } if( RI.params & RP_FLIPFRONTFACE ) GL_FrontFace( !glState.frontFace ); GL_Cull( GL_FRONT ); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); }
/* ================= R_DrawAliasModelShadow ================= */ void R_DrawAliasModelShadow(entity_t *e) { int i; dmdl_t *hdr; float an; vec3_t bbox[8]; image_t *skin; float lightspot[3]; glmatrix shadowmatrix; float lheight; if (gl_shadows->value && (e->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW))) return; if (!(e->flags & RF_WEAPONMODEL)) { if (R_CullAliasModel(bbox, e)) return; } if (e->flags & RF_WEAPONMODEL) { if (r_lefthand->value == 2) return; } hdr = (dmdl_t *)e->model->extradata; if (e->flags & (RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE)) { VectorClear(gl_meshuboupdate.shadelight); if (e->flags & RF_SHELL_RED) gl_meshuboupdate.shadelight[0] = 1.0; if (e->flags & RF_SHELL_GREEN) gl_meshuboupdate.shadelight[1] = 1.0; if (e->flags & RF_SHELL_BLUE) gl_meshuboupdate.shadelight[2] = 1.0; } else if (e->flags & RF_FULLBRIGHT) { gl_meshuboupdate.shadelight[0] = 1.0; gl_meshuboupdate.shadelight[1] = 1.0; gl_meshuboupdate.shadelight[2] = 1.0; } else { R_LightPoint(e->currorigin, gl_meshuboupdate.shadelight, lightspot); // player lighting hack for communication back to server // big hack! if (e->flags & RF_WEAPONMODEL) { // pick the greatest component, which should be the same // as the mono value returned by software if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[1]) { if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[0]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } else { if (gl_meshuboupdate.shadelight[1] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[1]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } } } if (e->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) if (gl_meshuboupdate.shadelight[i] > 0.1) break; if (i == 3) { gl_meshuboupdate.shadelight[0] = 0.1; gl_meshuboupdate.shadelight[1] = 0.1; gl_meshuboupdate.shadelight[2] = 0.1; } } if (e->flags & RF_GLOW) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin(r_newrefdef.time * 7); for (i = 0; i < 3; i++) { min = gl_meshuboupdate.shadelight[i] * 0.8; gl_meshuboupdate.shadelight[i] += scale; if (gl_meshuboupdate.shadelight[i] < min) gl_meshuboupdate.shadelight[i] = min; } } an = e->angles[1] / 180 * M_PI; Q_sincos(-an, &gl_meshuboupdate.shadevector[1], &gl_meshuboupdate.shadevector[0]); gl_meshuboupdate.shadevector[2] = 1; VectorNormalize(gl_meshuboupdate.shadevector); // locate the proper data c_alias_polys += hdr->num_tris; // draw all the triangles GL_LoadMatrix(&gl_meshuboupdate.localMatrix, &r_mvpmatrix); GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, e->currorigin[0], e->currorigin[1], e->currorigin[2]); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, e->angles[1], 0, 0, 1); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, e->angles[0], 0, 1, 0); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, -e->angles[2], 1, 0, 0); // select skin if (e->skin) skin = e->skin; // custom player skin else { if (e->skinnum >= MAX_MD2SKINS) skin = e->model->skins[0]; else { skin = e->model->skins[e->skinnum]; if (!skin) skin = e->model->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_BindTexture(GL_TEXTURE0, GL_TEXTURE_2D, r_modelsampler, skin->texnum); if ((e->currframe >= hdr->num_frames) || (e->currframe < 0)) { VID_Printf(PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such frame %d\n", e->model->name, e->currframe); e->currframe = 0; e->lastframe = 0; } if ((e->lastframe >= hdr->num_frames) || (e->lastframe < 0)) { VID_Printf(PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such oldframe %d\n", e->model->name, e->lastframe); e->currframe = 0; e->lastframe = 0; } if (!r_lerpmodels->value) e->backlerp = 0; lheight = e->currorigin[2] - lightspot[2]; GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, 0.0f, 0.0f, -lheight); shadowmatrix.m[0][0] = 1; shadowmatrix.m[0][1] = 0; shadowmatrix.m[0][2] = 0; shadowmatrix.m[0][3] = 0; shadowmatrix.m[1][0] = 0; shadowmatrix.m[1][1] = 1; shadowmatrix.m[1][2] = 0; shadowmatrix.m[1][3] = 0; shadowmatrix.m[2][0] = SHADOW_SKEW_X; shadowmatrix.m[2][1] = SHADOW_SKEW_Y; shadowmatrix.m[2][2] = SHADOW_VSCALE; shadowmatrix.m[2][3] = 0; shadowmatrix.m[3][0] = 0; shadowmatrix.m[3][1] = 0; shadowmatrix.m[3][2] = SHADOW_HEIGHT; shadowmatrix.m[3][3] = 1; GL_MultMatrix(&gl_meshuboupdate.localMatrix, &gl_meshuboupdate.localMatrix, &shadowmatrix); GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, 0.0f, 0.0f, lheight); // draw shadow GL_DrawAliasFrameLerp(e, hdr, e->backlerp); }
/* ================= GL_LoadTexMatrix ================= */ void GL_LoadTexMatrix( cmatrix4x4 m ) { pglMatrixMode( GL_TEXTURE ); GL_LoadMatrix( m ); glState.texIdentityMatrix[glState.activeTMU] = false; }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i; dmdl_t *hdr; float an; vec3_t bbox[8]; image_t *skin; float lightspot[3]; if (!(e->flags & RF_WEAPONMODEL)) { if (R_CullAliasModel (bbox, e)) return; } if (e->flags & RF_WEAPONMODEL) { if (r_lefthand->value == 2) return; } hdr = (dmdl_t *) e->model->extradata; if (e->flags & (RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE)) { VectorClear (gl_meshuboupdate.shadelight); if (e->flags & RF_SHELL_RED) gl_meshuboupdate.shadelight[0] = 1.0; if (e->flags & RF_SHELL_GREEN) gl_meshuboupdate.shadelight[1] = 1.0; if (e->flags & RF_SHELL_BLUE) gl_meshuboupdate.shadelight[2] = 1.0; } else if (e->flags & RF_FULLBRIGHT) { gl_meshuboupdate.shadelight[0] = 1.0; gl_meshuboupdate.shadelight[1] = 1.0; gl_meshuboupdate.shadelight[2] = 1.0; } else { dlight_t *l; int i; // grab static lighting from lightmap R_LightPoint (e->currorigin, gl_meshuboupdate.shadelight, lightspot); // grab dynamic lighting glProgramUniform1i (gl_meshprog, u_meshMaxLights, r_newrefdef.num_dlights); glProgramUniform3fv (gl_meshprog, u_meshEntOrig, 1, e->currorigin); for (i = 0, l = r_newrefdef.dlights; i < r_newrefdef.num_dlights; i++, l++) { glProgramUniform3fv (gl_meshprog, u_meshLightPos[i], 1, l->origin); glProgramUniform3fv (gl_meshprog, u_meshLightColor[i], 1, l->color); glProgramUniform1f (gl_meshprog, u_meshLightAtten[i], l->radius); } // player lighting hack for communication back to server // big hack! if (e->flags & RF_WEAPONMODEL) { // pick the greatest component, which should be the same // as the mono value returned by software if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[1]) { if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[0]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } else { if (gl_meshuboupdate.shadelight[1] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[1]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } } } if (e->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) { if (gl_meshuboupdate.shadelight[i] > 0.1) break; } if (i == 3) { gl_meshuboupdate.shadelight[0] = 0.1; gl_meshuboupdate.shadelight[1] = 0.1; gl_meshuboupdate.shadelight[2] = 0.1; } } if (e->flags & RF_GLOW) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin (r_newrefdef.time * 7); for (i = 0; i < 3; i++) { min = gl_meshuboupdate.shadelight[i] * 0.8; gl_meshuboupdate.shadelight[i] += scale; if (gl_meshuboupdate.shadelight[i] < min) gl_meshuboupdate.shadelight[i] = min; } } an = e->angles[1] / 180 * M_PI; Q_sincos (-an, &gl_meshuboupdate.shadevector[1], &gl_meshuboupdate.shadevector[0]); gl_meshuboupdate.shadevector[2] = 1; VectorNormalize (gl_meshuboupdate.shadevector); // locate the proper data c_alias_polys += hdr->num_tris; // draw all the triangles if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls glDepthRange (gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin)); if ((e->flags & RF_WEAPONMODEL) && (r_lefthand->value == 1.0F)) { glmatrix gunmatrix; GL_LoadIdentity (&gunmatrix); GL_ScaleMatrix (&gunmatrix, -1, 1, 1); GL_PerspectiveMatrix (&gunmatrix, r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height); // eval a new mvp for left-handedness GL_LoadMatrix (&gl_meshuboupdate.localMatrix, &r_worldmatrix); GL_MultMatrix (&gl_meshuboupdate.localMatrix, &gl_meshuboupdate.localMatrix, &gunmatrix); glCullFace (GL_BACK); } else GL_LoadMatrix (&gl_meshuboupdate.localMatrix, &r_mvpmatrix); GL_TranslateMatrix (&gl_meshuboupdate.localMatrix, e->currorigin[0], e->currorigin[1], e->currorigin[2]); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, e->angles[1], 0, 0, 1); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, e->angles[0], 0, 1, 0); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, -e->angles[2], 1, 0, 0); // select skin if (e->skin) skin = e->skin; // custom player skin else { if (e->skinnum >= MAX_MD2SKINS) skin = e->model->skins[0]; else { skin = e->model->skins[e->skinnum]; if (!skin) skin = e->model->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_BindTexture (GL_TEXTURE0, GL_TEXTURE_2D, r_modelsampler, skin->texnum); if ((e->currframe >= hdr->num_frames) || (e->currframe < 0)) { VID_Printf (PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such frame %d\n", e->model->name, e->currframe); e->currframe = 0; e->lastframe = 0; } if ((e->lastframe >= hdr->num_frames) || (e->lastframe < 0)) { VID_Printf (PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such oldframe %d\n", e->model->name, e->lastframe); e->currframe = 0; e->lastframe = 0; } if (!r_lerpmodels->value) e->backlerp = 0; GL_DrawAliasFrameLerp (e, hdr, e->backlerp); if ((e->flags & RF_WEAPONMODEL) && (r_lefthand->value == 1.0F)) { glCullFace (GL_FRONT); } if (e->flags & RF_DEPTHHACK) glDepthRange (gldepthmin, gldepthmax); }
/* ================= R_BloomBlend ================= */ void R_BloomBlend( const ref_params_t *fd ) { if( !r_bloom->value ) return; if( !BLOOM_SIZE ) R_Bloom_InitTextures(); if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) return; // set up full screen workspace pglScissor( 0, 0, glState.width, glState.height ); pglViewport( 0, 0, glState.width, glState.height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); pglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); pglMatrixMode( GL_MODELVIEW ); pglLoadIdentity(); pglDisable( GL_DEPTH_TEST ); pglDisable( GL_ALPHA_TEST ); pglDepthMask( GL_FALSE ); pglDisable( GL_BLEND ); GL_Cull( 0 ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // set up current sizes curView_x = fd->viewport[0]; curView_y = fd->viewport[1]; curView_width = fd->viewport[2]; curView_height = fd->viewport[3]; screenTex_tcw = ( (float)curView_width / (float)screen_texture_width ); screenTex_tch = ( (float)curView_height / (float)screen_texture_height ); if( curView_height > curView_width ) { sampleText_tcw = ( (float)curView_width / (float)curView_height ); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ( (float)curView_height / (float)curView_width ); } sample_width = ( BLOOM_SIZE * sampleText_tcw ); sample_height = ( BLOOM_SIZE * sampleText_tch ); // copy the screen space we'll use to work into the backup texture GL_Bind( GL_TEXTURE0, r_bloombackuptexture ); pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width * sampleText_tcw, r_screenbackuptexture_height * sampleText_tch ); // create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds(); pglDisable( GL_BLEND ); // restore the screen-backup to the screen GL_Bind( GL_TEXTURE0, r_bloombackuptexture ); pglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, glState.height - (r_screenbackuptexture_height * sampleText_tch), r_screenbackuptexture_width * sampleText_tcw, r_screenbackuptexture_height * sampleText_tch, sampleText_tcw, sampleText_tch ); pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); R_Bloom_DrawEffect(); pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); pglEnable( GL_DEPTH_TEST ); pglDepthMask( GL_TRUE ); pglDisable( GL_BLEND ); GL_Cull( GL_FRONT ); }
/* ================== GL_Setup3D TODO: time is messed up ================== */ void GL_Setup3D (int time){ double clipPlane[4]; QGL_LogPrintf("---------- RB_Setup3D ----------\n"); backEnd.projection2D = false; backEnd.time = time; backEnd.floatTime = MS2SEC(Sys_Milliseconds()); backEnd.viewport.x = backEnd.viewParms.viewport.x; backEnd.viewport.y = backEnd.viewParms.viewport.y; backEnd.viewport.width = backEnd.viewParms.viewport.width; backEnd.viewport.height = backEnd.viewParms.viewport.height; backEnd.scissor.x = backEnd.viewParms.scissor.x; backEnd.scissor.y = backEnd.viewParms.scissor.y; backEnd.scissor.width = backEnd.viewParms.scissor.width; backEnd.scissor.height = backEnd.viewParms.scissor.height; backEnd.coordScale[0] = 1.0f / backEnd.viewport.width; backEnd.coordScale[1] = 1.0f / backEnd.viewport.height; backEnd.coordBias[0] = -backEnd.viewport.x * backEnd.coordScale[0]; backEnd.coordBias[1] = -backEnd.viewport.y * backEnd.coordScale[1]; backEnd.depthFilling = false; backEnd.debugRendering = false; backEnd.currentColorCaptured = SORT_BAD; backEnd.currentDepthCaptured = false; // Set up the viewport GL_Viewport(backEnd.viewport); // Set up the scissor GL_Scissor(backEnd.viewport); // Set up the depth bounds if (glConfig.depthBoundsTestAvailable) GL_DepthBounds(0.0f, 1.0f); // Set the projection matrix GL_LoadMatrix(GL_PROJECTION, backEnd.viewParms.projectionMatrix); // Set the modelview matrix GL_LoadIdentity(GL_MODELVIEW); // Set the GL state GL_PolygonMode(GL_FILL); GL_Disable(GL_CULL_FACE); GL_Disable(GL_POLYGON_OFFSET_FILL); GL_Disable(GL_BLEND); GL_Disable(GL_ALPHA_TEST); GL_Disable(GL_DEPTH_TEST); GL_Disable(GL_STENCIL_TEST); GL_DepthRange(0.0f, 1.0f); GL_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); GL_DepthMask(GL_TRUE); GL_StencilMask(255); // Enable the clip plane if needed if (backEnd.viewParms.viewType != VIEW_MIRROR) qglDisable(GL_CLIP_PLANE0); else { clipPlane[0] = -DotProduct(backEnd.viewParms.axis[1], backEnd.viewParms.clipPlane.normal); clipPlane[1] = DotProduct(backEnd.viewParms.axis[2], backEnd.viewParms.clipPlane.normal); clipPlane[2] = -DotProduct(backEnd.viewParms.axis[0], backEnd.viewParms.clipPlane.normal); clipPlane[3] = DotProduct(backEnd.viewParms.origin, backEnd.viewParms.clipPlane.normal) - backEnd.viewParms.clipPlane.dist; qglEnable(GL_CLIP_PLANE0); qglClipPlane(GL_CLIP_PLANE0, clipPlane); } // Enable multisampling if available if (glConfig.multiSamples > 1) qglEnable(GL_MULTISAMPLE); // Clear the buffers qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglClearDepth(1.0f); qglClearStencil(0); if (backEnd.viewParms.primaryView) qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); else qglClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Check for errors if (!r_ignoreGLErrors->integerValue) GL_CheckForErrors(); QGL_LogPrintf("--------------------\n"); }
/* ================== GL_Setup2D TODO: time is messed up ================== */ void GL_Setup2D (int time){ mat4_t projectionMatrix = {2.0f / backEnd.cropWidth, 0.0f, 0.0f, 0.0f, 0.0f, -2.0f / backEnd.cropHeight, 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 0.0f, -1.0f, 1.0f, -1.0f, 1.0f}; QGL_LogPrintf("---------- RB_Setup2D ----------\n"); backEnd.projection2D = true; backEnd.time = time; backEnd.floatTime = MS2SEC(Sys_Milliseconds()); backEnd.viewport.x = 0; backEnd.viewport.y = 0; backEnd.viewport.width = backEnd.cropWidth; backEnd.viewport.height = backEnd.cropHeight; backEnd.scissor.x = 0; backEnd.scissor.y = 0; backEnd.scissor.width = backEnd.cropWidth; backEnd.scissor.height = backEnd.cropHeight; backEnd.coordScale[0] = 1.0f / backEnd.viewport.width; backEnd.coordScale[1] = 1.0f / backEnd.viewport.height; backEnd.coordBias[0] = -backEnd.viewport.x * backEnd.coordScale[0]; backEnd.coordBias[1] = -backEnd.viewport.y * backEnd.coordScale[1]; backEnd.depthFilling = false; backEnd.debugRendering = false; backEnd.currentColorCaptured = SORT_BAD; backEnd.currentDepthCaptured = false; // Set up the viewport GL_Viewport(backEnd.viewport); // Set up the scissor GL_Scissor(backEnd.viewport); // Set up the depth bounds if (glConfig.depthBoundsTestAvailable) GL_DepthBounds(0.0f, 1.0f); // Set the projection matrix GL_LoadMatrix(GL_PROJECTION, projectionMatrix); // Set the modelview matrix GL_LoadIdentity(GL_MODELVIEW); // Set the GL state GL_PolygonMode(GL_FILL); GL_Disable(GL_CULL_FACE); GL_Disable(GL_POLYGON_OFFSET_FILL); GL_Disable(GL_BLEND); GL_Disable(GL_ALPHA_TEST); GL_Disable(GL_DEPTH_TEST); GL_Disable(GL_STENCIL_TEST); GL_DepthRange(0.0f, 1.0f); GL_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); GL_DepthMask(GL_FALSE); GL_StencilMask(255); // Disable the clip plane qglDisable(GL_CLIP_PLANE0); // Disable multisampling if available if (glConfig.multiSamples > 1) qglDisable(GL_MULTISAMPLE); // Check for errors if (!r_ignoreGLErrors->integerValue) GL_CheckForErrors(); QGL_LogPrintf("--------------------\n"); }