/* * ================= * R_Bloom_DrawEffect * ================= */ void R_Bloom_DrawEffect(void) { GL_Bind(r_bloomeffecttexture->texnum); GL_Enable(GL_BLEND); GL_BlendFunc(GL_ONE, GL_ONE); GL_TexEnv(GL_MODULATE); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex + 0; indexArray[rb_index++] = rb_vertex + 1; indexArray[rb_index++] = rb_vertex + 2; indexArray[rb_index++] = rb_vertex + 0; indexArray[rb_index++] = rb_vertex + 2; indexArray[rb_index++] = rb_vertex + 3; VA_SetElem2(texCoordArray[0][rb_vertex], 0, sampleText_tch); VA_SetElem3(vertexArray[rb_vertex], curView_x, curView_y, 0); VA_SetElem4(colorArray[rb_vertex], r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f); rb_vertex++; VA_SetElem2(texCoordArray[0][rb_vertex], 0, 0); VA_SetElem3(vertexArray[rb_vertex], curView_x, curView_y + curView_height, 0); VA_SetElem4(colorArray[rb_vertex], r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f); rb_vertex++; VA_SetElem2(texCoordArray[0][rb_vertex], sampleText_tcw, 0); VA_SetElem3(vertexArray[rb_vertex], curView_x + curView_width, curView_y + curView_height, 0); VA_SetElem4(colorArray[rb_vertex], r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f); rb_vertex++; VA_SetElem2(texCoordArray[0][rb_vertex], sampleText_tcw, sampleText_tch); VA_SetElem3(vertexArray[rb_vertex], curView_x + curView_width, curView_y, 0); VA_SetElem4(colorArray[rb_vertex], r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f); rb_vertex++; RB_DrawArrays(); rb_vertex = rb_index = 0; GL_Disable(GL_BLEND); }
/* ============= R_DrawPic ============= */ void R_DrawImage (int32_t x, int32_t y, image_t *gl) { int32_t i; vec2_t texCoord[4], verts[4]; if (scrap_dirty) Scrap_Upload (); GL_Bind (gl->texnum); Vector2Set(texCoord[0], gl->sl, gl->tl); Vector2Set(texCoord[1], gl->sh, gl->tl); Vector2Set(texCoord[2], gl->sh, gl->th); Vector2Set(texCoord[3], gl->sl, gl->th); Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+gl->width, y); Vector2Set(verts[2], x+gl->width, y+gl->height); Vector2Set(verts[3], x, y+gl->height); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, 1.0); rb_vertex++; } RB_RenderMeshGeneric (false); }
/* ================= R_DrawAliasPlanarShadow ================= */ void R_DrawAliasPlanarShadow (maliasmodel_t *paliashdr) { maliasmesh_t mesh; float height, lheight, thisAlpha; vec3_t point, shadevector; int i, j; R_ShadowLight (currententity->origin, shadevector); lheight = currententity->origin[2] - lightspot[2]; height = -lheight + 0.1f; if (currententity->flags & RF_TRANSLUCENT) thisAlpha = aliasShadowAlpha * currententity->alpha; // was r_shadowalpha->value else thisAlpha = aliasShadowAlpha; // was r_shadowalpha->value // don't draw shadows above view origin, thnx to MrG if (r_newrefdef.vieworg[2] < (currententity->origin[2] + height)) return; GL_Stencil (true, false); GL_BlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA); rb_vertex = rb_index = 0; for (i=0; i<paliashdr->num_meshes; i++) { mesh = paliashdr->meshes[i]; if (mesh.skins[currententity->skinnum].renderparms.nodraw || mesh.skins[currententity->skinnum].renderparms.alphatest || mesh.skins[currententity->skinnum].renderparms.noshadow) continue; for (j=0; j<mesh.num_verts; j++) { VectorCopy(tempVertexArray[i][j], point); point[0] -= shadevector[0]*(point[2]+lheight); point[1] -= shadevector[1]*(point[2]+lheight); point[2] = height; VA_SetElem3(vertexArray[rb_vertex], point[0], point[1], point[2]); VA_SetElem4(colorArray[rb_vertex], 0, 0, 0, thisAlpha); rb_vertex++; } for (j=0; j < mesh.num_tris; j++) { indexArray[rb_index++] = mesh.indexes[3*j+0]; indexArray[rb_index++] = mesh.indexes[3*j+1]; indexArray[rb_index++] = mesh.indexes[3*j+2]; } } RB_DrawArrays (GL_TRIANGLES); GL_Stencil (false, false); }
/* ============= R_DrawStretchImage ============= */ void R_DrawStretchImage (int32_t x, int32_t y, int32_t w, int32_t h, image_t *gl, float alpha) { int32_t i; vec2_t texCoord[4], verts[4]; if (scrap_dirty) Scrap_Upload (); // Psychospaz's transparent console support if (gl->has_alpha || alpha < 1.0) { GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_DepthMask (false); } GL_Bind (gl->texnum); Vector2Set(texCoord[0], gl->sl, gl->tl); Vector2Set(texCoord[1], gl->sh, gl->tl); Vector2Set(texCoord[2], gl->sh, gl->th); Vector2Set(texCoord[3], gl->sl, gl->th); Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+w, y); Vector2Set(verts[2], x+w, y+h); Vector2Set(verts[3], x, y+h); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, alpha); rb_vertex++; } RB_RenderMeshGeneric (false); // Psychospaz's transparent console support if (gl->has_alpha || alpha < 1.0) { GL_DepthMask (true); GL_TexEnv (GL_REPLACE); GL_Disable (GL_BLEND); GL_Enable (GL_ALPHA_TEST); } }
void R_DrawStretchRaw (int32_t x, int32_t y, int32_t w, int32_t h, const byte *raw, int32_t rawWidth, int32_t rawHeight) //qboolean noDraw) { int32_t i; vec2_t texCoord[4], verts[4]; // Make sure everything is flushed if needed //if (!noDraw) // RB_RenderMesh(); // Update the texture as appropriate GL_Bind(glMedia.rawtexture->texnum); if (rawWidth == glMedia.rawtexture->upload_width && rawHeight == glMedia.rawtexture->upload_height) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rawWidth, rawHeight, GL_RGBA, GL_UNSIGNED_BYTE, raw); else { glMedia.rawtexture->upload_width = rawWidth; glMedia.rawtexture->upload_height = rawHeight; glTexImage2D(GL_TEXTURE_2D, 0, gl_raw_tex_solid_format, rawWidth, rawHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw); } //if (noDraw) // return; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw it Vector2Set(texCoord[0], 0, 0); Vector2Set(texCoord[1], 1, 0); Vector2Set(texCoord[2], 1, 1); Vector2Set(texCoord[3], 0, 1); Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+w, y); Vector2Set(verts[2], x+w, y+h); Vector2Set(verts[3], x, y+h); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1, 1, 1, 1); rb_vertex++; } RB_RenderMeshGeneric (false); }
/* ====================== R_DrawFill Fills a box of pixels with a 24-bit color w/ alpha =========================== */ void R_DrawFill (int32_t x, int32_t y, int32_t w, int32_t h, int32_t red, int32_t green, int32_t blue, int32_t alpha) { int32_t i; vec2_t verts[4]; red = min(red, 255); green = min(green, 255); blue = min(blue, 255); alpha = max(min(alpha, 255), 1); // GL_DisableTexture (0); GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_DepthMask (false); GL_Bind (glMedia.whitetexture->texnum); Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+w, y); Vector2Set(verts[2], x+w, y+h); Vector2Set(verts[3], x, y+h); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], red*DIV255, green*DIV255, blue*DIV255, alpha*DIV255); rb_vertex++; } RB_RenderMeshGeneric (false); GL_DepthMask (true); GL_Disable (GL_BLEND); GL_TexEnv (GL_REPLACE); GL_Enable (GL_ALPHA_TEST); // GL_EnableTexture (0); }
void MakeSkyVec (float s, float t, int axis) { vec3_t v, b; int j, k; //Knightmare- 12/26/2001- variable back clipping plane distance b[0] = s * r_skydistance->value; b[1] = t * r_skydistance->value; b[2] = r_skydistance->value; //end Knightmare for (j=0 ; j<3 ; j++) { k = st_to_vec[axis][j]; if (k < 0) v[j] = -b[-k - 1]; else v[j] = b[k - 1]; } // avoid bilerp seam s = (s+1)*0.5; t = (t+1)*0.5; if (s < sky_min) s = sky_min; else if (s > sky_max) s = sky_max; if (t < sky_min) t = sky_min; else if (t > sky_max) t = sky_max; t = 1.0 - t; VA_SetElem2(texCoordArray[0][rb_vertex], s, t); VA_SetElem3(vertexArray[rb_vertex], v[0], v[1], v[2]); VA_SetElem4(colorArray[rb_vertex], 1.0f, 1.0f, 1.0f, 1.0f); rb_vertex++; }
/* ============= R_DrawTileImage This repeats a 64*64 tile graphic to fill the screen around a sized down refresh window. ============= */ void R_DrawTileImage (int32_t x, int32_t y, int32_t w, int32_t h, image_t *image) { int32_t i; vec2_t texCoord[4], verts[4]; GL_Bind (image->texnum); /* Vector2Set(texCoord[0], x/64.0, y/64.0); Vector2Set(texCoord[1], (x+w)/64.0, y/64.0); Vector2Set(texCoord[2], (x+w)/64.0, (y+h)/64.0); Vector2Set(texCoord[3], x/64.0, (y+h)/64.0); */ Vector2Set(texCoord[0], (float)x/(float)image->width, (float)y/(float)image->height); Vector2Set(texCoord[1], (float)(x+w)/(float)image->width, (float)y/(float)image->height); Vector2Set(texCoord[2], (float)(x+w)/(float)image->width, (float)(y+h)/(float)image->height); Vector2Set(texCoord[3], (float)x/(float)image->width, (float)(y+h)/(float)image->height); Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+w, y); Vector2Set(verts[2], x+w, y+h); Vector2Set(verts[3], x, y+h); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, 1.0); rb_vertex++; } RB_RenderMeshGeneric (false); }
/* ================= R_DrawSpriteModel ================= */ void R_DrawSpriteModel (entity_t *e) { float alpha = 1.0f; vec2_t texCoord[4]; vec3_t point[4]; dsprite_t *psprite; dsprframe_t *frame; float *up, *right; int i; // don't even bother culling, because it's just a single // polygon without a surface cache psprite = (dsprite_t *)currentmodel->extradata; e->frame %= psprite->numframes; frame = &psprite->frames[e->frame]; if (!frame) return; c_alias_polys += 2; // normal sprite up = vup; right = vright; if (e->flags & RF_TRANSLUCENT) alpha = e->alpha; R_SetVertexRGBScale (true); // Psychospaz's additive transparency if ((currententity->flags & RF_TRANS_ADDITIVE) && (alpha != 1.0f)) { GL_Enable (GL_BLEND); GL_TexEnv (GL_MODULATE); GL_Disable (GL_ALPHA_TEST); GL_DepthMask (false); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE); } else { GL_TexEnv (GL_MODULATE); if (alpha == 1.0f) { GL_Enable (GL_ALPHA_TEST); GL_DepthMask (true); } else { GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask (false); GL_Enable (GL_BLEND); GL_Disable (GL_ALPHA_TEST); } } GL_Bind(currentmodel->skins[0][e->frame]->texnum); Vector2Set(texCoord[0], 0, 1); Vector2Set(texCoord[1], 0, 0); Vector2Set(texCoord[2], 1, 0); Vector2Set(texCoord[3], 1, 1); VectorMA (e->origin, -frame->origin_y, up, point[0]); VectorMA (point[0], -frame->origin_x, right, point[0]); VectorMA (e->origin, frame->height - frame->origin_y, up, point[1]); VectorMA (point[1], -frame->origin_x, right, point[1]); VectorMA (e->origin, frame->height - frame->origin_y, up, point[2]); VectorMA (point[2], frame->width - frame->origin_x, right, point[2]); VectorMA (e->origin, -frame->origin_y, up, point[3]); VectorMA (point[3], frame->width - frame->origin_x, right, point[3]); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], point[i][0], point[i][1], point[i][2]); VA_SetElem4(colorArray[rb_vertex], 1.0f, 1.0f, 1.0f, alpha); rb_vertex++; } RB_DrawArrays (); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_TexEnv (GL_REPLACE); GL_DepthMask (true); GL_Disable (GL_ALPHA_TEST); GL_Disable (GL_BLEND); R_SetVertexRGBScale (false); RB_DrawMeshTris (); rb_vertex = rb_index = 0; }
/* ============= R_DrawWarpSurface Does a water warp on the pre-fragmented glpoly_t chain. added Psychospaz's lightmaps on alpha surfaces ============= */ void R_DrawWarpSurface (msurface_t *fa, float alpha, qboolean render) { glpoly_t *p, *bp; float *v, s, t, scroll, dstscroll, rdt = r_newrefdef.time; vec3_t point; int i; qboolean light = r_warp_lighting->value && !r_fullbright->value && !(fa->texinfo->flags & SURF_NOLIGHTENV); qboolean texShaderNV = glConfig.NV_texshaders && glConfig.multitexture && ( (!glConfig.arb_fragment_program && r_pixel_shader_warp->value) || (glConfig.arb_fragment_program && r_pixel_shader_warp->value > 1) ); c_brush_surfs++; dstscroll = -64 * ( (r_newrefdef.time*0.15) - (int)(r_newrefdef.time*0.15) ); if (fa->texinfo->flags & SURF_FLOWING) scroll = -64 * ( (r_newrefdef.time*0.5) - (int)(r_newrefdef.time*0.5) ); else scroll = 0.0f; // rb_vertex = rb_index = 0; for (bp = fa->polys; bp; bp = bp->next) { c_brush_polys += (bp->numverts-2); p = bp; if (RB_CheckArrayOverflow (p->numverts, (p->numverts-2)*3)) RB_RenderWarpSurface (fa); for (i = 0; i < p->numverts-2; i++) { indexArray[rb_index++] = rb_vertex; indexArray[rb_index++] = rb_vertex+i+1; indexArray[rb_index++] = rb_vertex+i+2; } for (i=0, v=p->verts[0]; i<p->numverts; i++, v+=VERTEXSIZE) { #if !id386 s = v[3] + r_turbsin[(int)((v[4]*0.125+rdt) * TURBSCALE) & 255]; t = v[4] + r_turbsin[(int)((v[3]*0.125+rdt) * TURBSCALE) & 255]; #else s = v[3] + r_turbsin[Q_ftol( ((v[4]*0.125+rdt) * TURBSCALE) ) & 255]; t = v[4] + r_turbsin[Q_ftol( ((v[3]*0.125+rdt) * TURBSCALE) ) & 255]; #endif s += scroll; s *= DIV64; t *= DIV64; //=============== Water waves ======================== VectorCopy(v, point); if ( r_waterwave->value > 0 && !(fa->texinfo->flags & SURF_FLOWING) && fa->plane->normal[2] > 0 && fa->plane->normal[2] > fa->plane->normal[0] && fa->plane->normal[2] > fa->plane->normal[1] ) point[2] = v[2] + r_waterwave->value * sin(v[0]*0.025+rdt) * sin(v[2]*0.05+rdt); //=============== End water waves ==================== // MrG - texture shader waterwarp if (texShaderNV) { VA_SetElem2(texCoordArray[0][rb_vertex], (v[3]+dstscroll)*DIV64, v[4]*DIV64); VA_SetElem2(texCoordArray[1][rb_vertex], s, t); } else { VA_SetElem2(texCoordArray[0][rb_vertex], s, t); VA_SetElem2(texCoordArray[1][rb_vertex], (v[3]+dstscroll)*DIV64, v[4]*DIV64); } if (light && p->vertexlight && p->vertexlightset) VA_SetElem4(colorArray[rb_vertex], (float)(p->vertexlight[i*3+0]*DIV255), (float)(p->vertexlight[i*3+1]*DIV255), (float)(p->vertexlight[i*3+2]*DIV255), alpha); else VA_SetElem4(colorArray[rb_vertex], glState.inverse_intensity, glState.inverse_intensity, glState.inverse_intensity, alpha); VA_SetElem3(vertexArray[rb_vertex], point[0], point[1], point[2]); rb_vertex++; } } if (render) RB_RenderWarpSurface (fa); }
void R_DrawCameraEffect (void) { image_t *image[2]; int32_t x, y, w, h, i, j; float texparms[2][4]; vec2_t texCoord[4]; vec3_t verts[4]; renderparms_t cameraParms; image[0] = R_DrawFindPic ("/gfx/2d/screenstatic.tga"); image[1] = R_DrawFindPic ("/gfx/2d/scanlines.tga"); if (!image[0] || !image[1]) return; x = y = 0; w = vid.width; h = vid.height; GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_BlendFunc (GL_DST_COLOR, GL_SRC_COLOR); GL_DepthMask (false); VectorSet(verts[0], x, y, 0); VectorSet(verts[1], x+w, y, 0); VectorSet(verts[2], x+w, y+h, 0); VectorSet(verts[3], x, y+h, 0); Vector4Set(texparms[0], 2, 2, -30, 10); Vector4Set(texparms[1], 1, 10, 0, 0); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; rb_vertex = 4; for (i=0; i<2; i++) { GL_Bind (image[i]->texnum); Vector2Set(texCoord[0], x/image[i]->width, y/image[i]->height); Vector2Set(texCoord[1], (x+w)/image[i]->width, y/image[i]->height); Vector2Set(texCoord[2], (x+w)/image[i]->width, (y+h)/image[i]->height); Vector2Set(texCoord[3], x/image[i]->width, (y+h)/image[i]->height); Mod_SetRenderParmsDefaults (&cameraParms); cameraParms.scale_x = texparms[i][0]; cameraParms.scale_y = texparms[i][1]; cameraParms.scroll_x = texparms[i][2]; cameraParms.scroll_y = texparms[i][3]; RB_ModifyTextureCoords (&texCoord[0][0], &verts[0][0], 4, cameraParms); for (j=0; j<4; j++) { VA_SetElem2(texCoordArray[0][j], texCoord[j][0], texCoord[j][1]); VA_SetElem3(vertexArray[j], verts[j][0], verts[j][1], verts[j][2]); VA_SetElem4(colorArray[j], 1, 1, 1, 1); } RB_DrawArrays (); } rb_vertex = rb_index = 0; GL_DepthMask (true); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Disable (GL_BLEND); GL_TexEnv (GL_REPLACE); GL_Enable (GL_ALPHA_TEST); }
/* ============= R_DrawScaledImage Psychospaz's code for drawing stretched crosshairs ============= */ void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl) { float xoff, yoff; float scale_x, scale_y; int32_t i; vec2_t texCoord[4], verts[4]; if (scrap_dirty) Scrap_Upload (); // add alpha support if (gl->has_alpha || alpha < 1.0) { GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_DepthMask (false); } GL_Bind (gl->texnum); scale_x = scale_y = scale; scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image Vector2Set(texCoord[0], gl->sl, gl->tl); Vector2Set(texCoord[1], gl->sh, gl->tl); Vector2Set(texCoord[2], gl->sh, gl->th); Vector2Set(texCoord[3], gl->sl, gl->th); xoff = gl->width*scale_x-gl->width; yoff = gl->height*scale_y-gl->height; Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+gl->width+xoff, y); Vector2Set(verts[2], x+gl->width+xoff, y+gl->height+yoff); Vector2Set(verts[3], x, y+gl->height+yoff); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, alpha); rb_vertex++; } RB_RenderMeshGeneric (false); if (gl->has_alpha || alpha < 1.0) { GL_DepthMask (true); GL_TexEnv (GL_REPLACE); GL_Disable (GL_BLEND); GL_Enable (GL_ALPHA_TEST); // add alpha support } }
/* ================ R_DrawChar Draws one variable sized graphics character with 0 being transparent. It can be clipped to the top of the screen to allow the console to be smoothly scrolled off. ================ */ void R_DrawChar (float x, float y, int32_t num, float scale, int32_t red, int32_t green, int32_t blue, int32_t alpha, qboolean italic, qboolean last) { int32_t row, col, i; float frow, fcol, size, cscale, italicAdd; vec2_t texCoord[4], verts[4]; qboolean addChar = true; num &= 255; if (alpha > 255) alpha = 255; else if (alpha < 1) alpha = 1; if ((num & 127) == 32) // space addChar = false; if (y <= -(scale * DEFAULT_FONT_SIZE)) // totally off screen addChar = false; row = num >> 4; col = num&15; frow = row*0.0625; fcol = col*0.0625; size = 0.0625; cscale = scale * DEFAULT_FONT_SIZE; italicAdd = (italic) ? (cscale*0.25) : 0; if (addChar) { Vector2Set(texCoord[0], fcol, frow); Vector2Set(texCoord[1], fcol + size, frow); Vector2Set(texCoord[2], fcol + size, frow + size); Vector2Set(texCoord[3], fcol, frow + size); Vector2Set(verts[0], x+italicAdd, y); Vector2Set(verts[1], x+cscale+italicAdd, y); Vector2Set(verts[2], x+cscale-italicAdd, y+cscale); Vector2Set(verts[3], x-italicAdd, y+cscale); if (char_count == 0) rb_vertex = rb_index = 0; if (rb_vertex + 4 >= MAX_VERTICES || rb_index + 6 >= MAX_INDICES) R_FlushChars (); indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], red*DIV255, green*DIV255, blue*DIV255, alpha*DIV255); rb_vertex++; } char_count++; } if (last) R_FlushChars (); }
/* ================= R_DrawAliasFrameLerp ================= */ void R_DrawAliasFrameLerp (maliasmodel_t *paliashdr, entity_t *e) { int i, j, k, meshnum; maliasframe_t *frame, *oldframe; maliasmesh_t mesh; maliasvertex_t *v, *ov; vec3_t move, delta, vectors[3]; vec3_t curScale, oldScale, curNormal, oldNormal; vec3_t tempNormalsArray[MD3_MAX_VERTS]; vec2_t tempSkinCoord; vec3_t meshlight, lightcolor; float alpha, meshalpha, thisalpha, shellscale, frontlerp, backlerp = e->backlerp; image_t *skin; renderparms_t skinParms; qboolean shellModel = e->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM); frontlerp = 1.0 - backlerp; if (e->flags & RF_TRANSLUCENT) alpha = e->alpha; else alpha = 1.0; frame = paliashdr->frames + e->frame; oldframe = paliashdr->frames + e->oldframe; VectorScale(frame->scale, frontlerp, curScale); VectorScale(oldframe->scale, backlerp, oldScale); // move should be the delta back to the previous frame * backlerp VectorSubtract (e->oldorigin, e->origin, delta); AngleVectors (e->angles, vectors[0], vectors[1], vectors[2]); move[0] = DotProduct (delta, vectors[0]); // forward move[1] = -DotProduct (delta, vectors[1]); // left move[2] = DotProduct (delta, vectors[2]); // up VectorAdd (move, oldframe->translate, move); for (i=0 ; i<3 ; i++) move[i] = backlerp*move[i] + frontlerp*frame->translate[i]; R_SetVertexOverbrights(true); R_SetShellBlend (true); // new outer loop for whole model for (k=0, meshnum=0; k < paliashdr->num_meshes; k++, meshnum++) { mesh = paliashdr->meshes[k]; skinParms = mesh.skins[e->skinnum].renderparms; // select skin if (e->skin) skin = e->skin; // custom player skin else skin = currentmodel->skins[k][e->skinnum]; if (!skin) skin = r_notexture; if ( !shellModel ) GL_Bind(skin->texnum); else if (FlowingShell()) alpha = 0.7; // md3 skin scripting if (skinParms.nodraw) continue; // skip this mesh for this skin if (skinParms.twosided) GL_Disable(GL_CULL_FACE); if (skinParms.alphatest && !shellModel) GL_Enable(GL_ALPHA_TEST); if (skinParms.fullbright) VectorSet(meshlight, 1.0f, 1.0f, 1.0f); else VectorCopy(shadelight, meshlight); meshalpha = alpha * skinParms.basealpha; if (meshalpha < 1.0f || skinParms.blend) GL_Enable (GL_BLEND); else GL_Disable (GL_BLEND); if (skinParms.blend && !shellModel) GL_BlendFunc (skinParms.blendfunc_src, skinParms.blendfunc_dst); else GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // md3 skin scripting v = mesh.vertexes + e->frame*mesh.num_verts; ov = mesh.vertexes + e->oldframe*mesh.num_verts; rb_vertex = 0; for (i=0; i<mesh.num_verts; i++, v++, ov++) { // lerp verts curNormal[0] = r_sinTable[v->normal[0]] * r_cosTable[v->normal[1]]; curNormal[1] = r_sinTable[v->normal[0]] * r_sinTable[v->normal[1]]; curNormal[2] = r_cosTable[v->normal[0]]; oldNormal[0] = r_sinTable[ov->normal[0]] * r_cosTable[ov->normal[1]]; oldNormal[1] = r_sinTable[ov->normal[0]] * r_sinTable[ov->normal[1]]; oldNormal[2] = r_cosTable[ov->normal[0]]; VectorSet ( tempNormalsArray[i], curNormal[0] + (oldNormal[0] - curNormal[0])*backlerp, curNormal[1] + (oldNormal[1] - curNormal[1])*backlerp, curNormal[2] + (oldNormal[2] - curNormal[2])*backlerp ); if (shellModel) shellscale = (e->flags & RF_WEAPONMODEL) ? WEAPON_SHELL_SCALE: POWERSUIT_SCALE; else shellscale = 0.0; VectorSet ( tempVertexArray[meshnum][i], move[0] + ov->point[0]*oldScale[0] + v->point[0]*curScale[0] + tempNormalsArray[i][0]*shellscale, move[1] + ov->point[1]*oldScale[1] + v->point[1]*curScale[1] + tempNormalsArray[i][1]*shellscale, move[2] + ov->point[2]*oldScale[2] + v->point[2]*curScale[2] + tempNormalsArray[i][2]*shellscale ); // calc lighting and alpha if (shellModel) VectorCopy(meshlight, lightcolor); else R_LightAliasModel(meshlight, tempNormalsArray[i], lightcolor, v->lightnormalindex, !skinParms.nodiffuse); //thisalpha = R_CalcEntAlpha(meshalpha, tempVertexArray[meshnum][i]); thisalpha = meshalpha; // get tex coords if (shellModel && FlowingShell()) { tempSkinCoord[0] = (tempVertexArray[meshnum][i][0] + tempVertexArray[meshnum][i][1]) / 40.0 + shellFlowH; tempSkinCoord[1] = tempVertexArray[meshnum][i][2] / 40.0 + shellFlowV; } else { tempSkinCoord[0] = mesh.stcoords[i].st[0]; tempSkinCoord[1] = mesh.stcoords[i].st[1]; } // add to arrays VA_SetElem2(texCoordArray[0][rb_vertex], tempSkinCoord[0], tempSkinCoord[1]); VA_SetElem3(vertexArray[rb_vertex], tempVertexArray[meshnum][i][0], tempVertexArray[meshnum][i][1], tempVertexArray[meshnum][i][2]); VA_SetElem4(colorArray[rb_vertex], lightcolor[0], lightcolor[1], lightcolor[2], thisalpha); rb_vertex++; } if (!shellModel) RB_ModifyTextureCoords (&texCoordArray[0][0][0], &vertexArray[0][0], rb_vertex, skinParms); // set indices for each triangle and draw rb_index = 0; for (j=0; j < mesh.num_tris; j++) { indexArray[rb_index++] = mesh.indexes[3*j+0]; indexArray[rb_index++] = mesh.indexes[3*j+1]; indexArray[rb_index++] = mesh.indexes[3*j+2]; } RB_DrawArrays (GL_TRIANGLES); // glow pass if (mesh.skins[e->skinnum].glowimage && !shellModel) { float glowcolor; if (skinParms.glow.type > -1) glowcolor = RB_CalcGlowColor (skinParms); else glowcolor = 1.0; qglDisableClientState (GL_COLOR_ARRAY); qglColor4f(glowcolor, glowcolor, glowcolor, 1.0); GL_Enable (GL_BLEND); GL_BlendFunc (GL_ONE, GL_ONE); GL_Bind(mesh.skins[e->skinnum].glowimage->texnum); RB_DrawArrays (GL_TRIANGLES); qglEnableClientState (GL_COLOR_ARRAY); qglColor4f(1.0, 1.0, 1.0, 1.0); } // envmap pass if (skinParms.envmap > 0.0f && !shellModel) { GL_Enable (GL_BLEND); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); // apply alpha to array for (i=0; i<mesh.num_verts; i++) //colorArray[i][3] = R_CalcEntAlpha(meshalpha*skinParms.envmap, tempVertexArray[meshnum][i]); colorArray[i][3] = meshalpha*skinParms.envmap; GL_Bind(r_envmappic->texnum); qglEnable(GL_TEXTURE_GEN_S); qglEnable(GL_TEXTURE_GEN_T); RB_DrawArrays (GL_TRIANGLES); qglDisable(GL_TEXTURE_GEN_S); qglDisable(GL_TEXTURE_GEN_T); } RB_DrawMeshTris (GL_TRIANGLES, 1); // md3 skin scripting if (skinParms.twosided) GL_Enable(GL_CULL_FACE); if (skinParms.alphatest && !shellModel) GL_Disable(GL_ALPHA_TEST); GL_Disable (GL_BLEND); // md3 skin scripting } // end new outer loop R_SetShellBlend (false); R_SetVertexOverbrights(false); }
/* ============= R_BuildShadowVolume based on code from BeefQuake R6 ============= */ void R_BuildShadowVolume (maliasmodel_t *hdr, int meshnum, vec3_t light, float projectdistance, qboolean nocap) { int i, j, baseindex; qboolean trianglefacinglight[MD3_MAX_TRIANGLES]; vec3_t v0, v1, v2, v3; float thisAlpha; maliasmesh_t mesh; maliasvertex_t *verts; mesh = hdr->meshes[meshnum]; if (mesh.skins[currententity->skinnum].renderparms.nodraw || mesh.skins[currententity->skinnum].renderparms.alphatest || mesh.skins[currententity->skinnum].renderparms.noshadow) return; verts = mesh.vertexes; thisAlpha = aliasShadowAlpha; // was r_shadowalpha->value for (i=0; i<mesh.num_tris; i++) { VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+0]], v0); VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+1]], v1); VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+2]], v2); trianglefacinglight[i] = (light[0] - v0[0]) * ((v0[1] - v1[1]) * (v2[2] - v1[2]) - (v0[2] - v1[2]) * (v2[1] - v1[1])) + (light[1] - v0[1]) * ((v0[2] - v1[2]) * (v2[0] - v1[0]) - (v0[0] - v1[0]) * (v2[2] - v1[2])) + (light[2] - v0[2]) * ((v0[0] - v1[0]) * (v2[1] - v1[1]) - (v0[1] - v1[1]) * (v2[0] - v1[0])) > 0; } shadow_va = shadow_index = 0; for (i=0; i<mesh.num_tris; i++) { if (!trianglefacinglight[i]) continue; if (mesh.trneighbors[i*3+0] < 0 || !trianglefacinglight[mesh.trneighbors[i*3+0]]) { baseindex = shadow_va; for (j=0; j<3; j++) { v0[j]=tempVertexArray[meshnum][mesh.indexes[3*i+1]][j]; v1[j]=tempVertexArray[meshnum][mesh.indexes[3*i+0]][j]; v2[j]=v1[j]+((v1[j]-light[j]) * projectdistance); v3[j]=v0[j]+((v0[j]-light[j]) * projectdistance); } VA_SetElem3(vertexArray[shadow_va], v0[0], v0[1], v0[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v1[0], v1[1], v1[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v2[0], v2[1], v2[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v3[0], v3[1], v3[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+1; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+3; } if (mesh.trneighbors[i*3+1] < 0 || !trianglefacinglight[mesh.trneighbors[i*3+1]]) { baseindex = shadow_va; for (j=0; j<3; j++) { v0[j]=tempVertexArray[meshnum][mesh.indexes[3*i+2]][j]; v1[j]=tempVertexArray[meshnum][mesh.indexes[3*i+1]][j]; v2[j]=v1[j]+((v1[j]-light[j]) * projectdistance); v3[j]=v0[j]+((v0[j]-light[j]) * projectdistance); } VA_SetElem3(vertexArray[shadow_va], v0[0], v0[1], v0[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v1[0], v1[1], v1[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v2[0], v2[1], v2[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v3[0], v3[1], v3[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+1; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+3; } if (mesh.trneighbors[i*3+2] < 0 || !trianglefacinglight[mesh.trneighbors[i*3+2]]) { baseindex = shadow_va; for (j=0; j<3; j++) { v0[j]=tempVertexArray[meshnum][mesh.indexes[3*i+0]][j]; v1[j]=tempVertexArray[meshnum][mesh.indexes[3*i+2]][j]; v2[j]=v1[j]+((v1[j]-light[j]) * projectdistance); v3[j]=v0[j]+((v0[j]-light[j]) * projectdistance); } VA_SetElem3(vertexArray[shadow_va], v0[0], v0[1], v0[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v1[0], v1[1], v1[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v2[0], v2[1], v2[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; VA_SetElem3(vertexArray[shadow_va], v3[0], v3[1], v3[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); shadow_va++; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+1; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+0; indexArray[shadow_index++] = baseindex+2; indexArray[shadow_index++] = baseindex+3; } } if (nocap) return; // cap the volume for (i=0; i<mesh.num_tris; i++) { if (trianglefacinglight[i]) { VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+0]], v0); VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+1]], v1); VectorCopy(tempVertexArray[meshnum][mesh.indexes[3*i+2]], v2); VA_SetElem3(vertexArray[shadow_va], v0[0], v0[1], v0[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; VA_SetElem3(vertexArray[shadow_va], v1[0], v1[1], v1[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; VA_SetElem3(vertexArray[shadow_va], v2[0], v2[1], v2[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; continue; } for (j=0; j<3; j++) { v0[j]=tempVertexArray[meshnum][mesh.indexes[3*i+0]][j]; v1[j]=tempVertexArray[meshnum][mesh.indexes[3*i+1]][j]; v2[j]=tempVertexArray[meshnum][mesh.indexes[3*i+2]][j]; v0[j]=v0[j]+((v0[j]-light[j]) * projectdistance); v1[j]=v1[j]+((v1[j]-light[j]) * projectdistance); v2[j]=v2[j]+((v2[j]-light[j]) * projectdistance); } VA_SetElem3(vertexArray[shadow_va], v0[0], v0[1], v0[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; VA_SetElem3(vertexArray[shadow_va], v1[0], v1[1], v1[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; VA_SetElem3(vertexArray[shadow_va], v2[0], v2[1], v2[2]); VA_SetElem4(colorArray[shadow_va], 0, 0, 0, thisAlpha); indexArray[shadow_index++] = shadow_va; shadow_va++; } }