/* ================= R_SetBlendModeOn ================= */ void R_SetBlendModeOn (image_t *skin) { GL_TexEnv( GL_MODULATE ); if (skin) GL_Bind(skin->texnum); GL_ShadeModel (GL_SMOOTH); if (currententity->flags & RF_TRANSLUCENT) { GL_DepthMask (false); if (currententity->flags & RF_TRANS_ADDITIVE) { GL_BlendFunc (GL_SRC_ALPHA, GL_ONE); glColor4ub(255, 255, 255, 255); GL_ShadeModel (GL_FLAT); } else GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Enable (GL_BLEND); } }
void Pass2D::setup(GLRenderer *r) { Pass::setup(r); GL_Enable(GL_SCISSOR_TEST); GL_Disable(GL_LIGHTING); GL_Disable(GL_DEPTH_TEST); GL_Disable(GL_CULL_FACE); GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc(GL_GREATER, 0.01f); Cvar_SetVarValue(&gfx_GLSLPass, 0); GL_TexModulate(1.0); GL_UseProgram(0); GL_MatrixMode(GL_PROJECTION); GL_PushMatrix(); glLoadIdentity(); glOrtho(0, Vid_GetScreenW(), Vid_GetScreenH(), 0, -1.0, 1.0); GL_MatrixMode(GL_MODELVIEW); GL_PushMatrix(); glLoadIdentity(); #ifdef DEBUG GLSL_catchLastError("Pass2D::setup(): "); #endif }
/* * ================= * 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_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_SetBlendModeOff ================= */ void R_SetBlendModeOff (void) { if ( currententity->flags & RF_TRANSLUCENT ) { GL_DepthMask (true); GL_Disable(GL_BLEND); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } }
/* ================= 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); }
void LightPass::setup(GLRenderer *r) { Pass::setup(r); //basically, light pass is like a normal pass but we don't have any ambient light vec4_t ambient = { 0, 0, 0, 1 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); //but we do have additive blending GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); }
/* ================= R_Bloom_DrawEffect ================= */ void R_Bloom_DrawEffect( refdef_t *fd ) { GL_Bind(r_bloomeffecttexture->texnum); GL_Enable(GL_BLEND); GL_BlendFunc(GL_ONE, GL_ONE); qglColor4f(r_bloom_alpha->value + fd->bloomalpha /*bc mod*/, r_bloom_alpha->value + fd->bloomalpha /*bc mod*/, r_bloom_alpha->value + fd->bloomalpha /*bc mod*/, 1.0f); GL_TexEnv(GL_MODULATE); qglBegin(GL_QUADS); qglTexCoord2f( 0, sampleText_tch ); qglVertex2f( curView_x, curView_y ); qglTexCoord2f( 0, 0 ); qglVertex2f( curView_x, curView_y + curView_height ); qglTexCoord2f( sampleText_tcw, 0 ); qglVertex2f( curView_x + curView_width, curView_y + curView_height ); qglTexCoord2f( sampleText_tcw, sampleText_tch ); qglVertex2f( curView_x + curView_width, curView_y ); qglEnd(); GL_Disable(GL_BLEND); }
/* ================= R_Bloom_DownsampleView ================= */ void R_Bloom_DownsampleView( void ) { GL_Disable( GL_BLEND ); qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); //stepped downsample if( r_screendownsamplingtexture_size ) { int midsample_width = r_screendownsamplingtexture_size * sampleText_tcw; int midsample_height = r_screendownsamplingtexture_size * sampleText_tch; //copy the screen and draw resized GL_Bind(r_bloomscreentexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, curView_x, vid.height - (curView_y + curView_height), curView_width, curView_height); R_Bloom_Quad( 0, vid.height-midsample_height, midsample_width, midsample_height, screenText_tcw, screenText_tch ); //now copy into Downsampling (mid-sized) texture GL_Bind(r_bloomdownsamplingtexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height); //now draw again in bloom size qglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); R_Bloom_Quad( 0, vid.height-sample_height, sample_width, sample_height, sampleText_tcw, sampleText_tch ); //now blend the big screen texture into the bloom generation space (hoping it adds some blur) GL_Enable( GL_BLEND ); GL_BlendFunc(GL_ONE, GL_ONE); qglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); GL_Bind(r_bloomscreentexture->texnum); R_Bloom_Quad( 0, vid.height-sample_height, sample_width, sample_height, screenText_tcw, screenText_tch ); qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Disable( GL_BLEND ); } else { //downsample simple GL_Bind(r_bloomscreentexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, curView_x, vid.height - (curView_y + curView_height), curView_width, curView_height); R_Bloom_Quad( 0, vid.height-sample_height, sample_width, sample_height, screenText_tcw, screenText_tch ); } }
/* * ================= * R_Bloom_GeneratexCross - alternative bluring method * ================= */ void R_Bloom_GeneratexCross(void) { int i; static int BLOOM_BLUR_RADIUS = 8; //static float BLOOM_BLUR_INTENSITY = 2.5f; float BLOOM_BLUR_INTENSITY; static float intensity; static float range; // set up sample size workspace glViewport(0, 0, sample_width, sample_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, sample_width, sample_height, 0, -10, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // copy small scene into r_bloomeffecttexture GL_Bind(0, r_bloomeffecttexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); // start modifying the small scene corner GL_Enable(GL_BLEND); // darkening passes if (r_bloom_darken->value) { GL_BlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); R_Bloom_DrawStart for (i = 0; i < r_bloom_darken->value; i++) { R_Bloom_SamplePass(0, 0, 1.0f, 1.0f, 1.0f, 1.0f); } R_Bloom_DrawFinish glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); }
static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { int surfacelistindex = 0; const int numtriangles = EXPLOSIONTRIS, numverts = EXPLOSIONVERTS; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); GL_DepthRange(0, 1); GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); GL_DepthTest(true); GL_CullFace(r_refdef.view.cullface_back); R_EntityMatrix(&identitymatrix); // R_Mesh_ResetTextureState(); R_SetupShader_Generic(explosiontexture, NULL, GL_MODULATE, 1, false, false, false); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { const explosion_t *e = explosion + surfacelist[surfacelistindex]; // FIXME: this can't properly handle r_refdef.view.colorscale > 1 GL_Color(e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, e->alpha * r_refdef.view.colorscale, 1); R_Mesh_PrepareVertices_Generic_Arrays(numverts, e->vert[0], NULL, explosiontexcoord2f[0]); R_Mesh_Draw(0, numverts, 0, numtriangles, NULL, NULL, 0, explosiontris[0], NULL, 0); } }
/** * @brief This routine is responsible for setting the most commonly changed state in Q3. */ void GL_State(uint32_t stateBits) { uint32_t diff = stateBits ^ glState.glStateBits; if (!diff) { return; } // check depthFunc bits if (diff & GLS_DEPTHFUNC_BITS) { switch (stateBits & GLS_DEPTHFUNC_BITS) { default: GL_DepthFunc(GL_LEQUAL); break; case GLS_DEPTHFUNC_LESS: GL_DepthFunc(GL_LESS); break; case GLS_DEPTHFUNC_EQUAL: GL_DepthFunc(GL_EQUAL); break; } } // check blend bits if (diff & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) { GLenum srcFactor, dstFactor; if (stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) { switch (stateBits & GLS_SRCBLEND_BITS) { case GLS_SRCBLEND_ZERO: srcFactor = GL_ZERO; break; case GLS_SRCBLEND_ONE: srcFactor = GL_ONE; break; case GLS_SRCBLEND_DST_COLOR: srcFactor = GL_DST_COLOR; break; case GLS_SRCBLEND_ONE_MINUS_DST_COLOR: srcFactor = GL_ONE_MINUS_DST_COLOR; break; case GLS_SRCBLEND_SRC_ALPHA: srcFactor = GL_SRC_ALPHA; break; case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA: srcFactor = GL_ONE_MINUS_SRC_ALPHA; break; case GLS_SRCBLEND_DST_ALPHA: srcFactor = GL_DST_ALPHA; break; case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA: srcFactor = GL_ONE_MINUS_DST_ALPHA; break; case GLS_SRCBLEND_ALPHA_SATURATE: srcFactor = GL_SRC_ALPHA_SATURATE; break; default: srcFactor = GL_ONE; // to get warning to shut up Ren_Drop("GL_State: invalid src blend state bits\n"); break; } switch (stateBits & GLS_DSTBLEND_BITS) { case GLS_DSTBLEND_ZERO: dstFactor = GL_ZERO; break; case GLS_DSTBLEND_ONE: dstFactor = GL_ONE; break; case GLS_DSTBLEND_SRC_COLOR: dstFactor = GL_SRC_COLOR; break; case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR: dstFactor = GL_ONE_MINUS_SRC_COLOR; break; case GLS_DSTBLEND_SRC_ALPHA: dstFactor = GL_SRC_ALPHA; break; case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA: dstFactor = GL_ONE_MINUS_SRC_ALPHA; break; case GLS_DSTBLEND_DST_ALPHA: dstFactor = GL_DST_ALPHA; break; case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA: dstFactor = GL_ONE_MINUS_DST_ALPHA; break; default: dstFactor = GL_ONE; // to get warning to shut up Ren_Drop("GL_State: invalid dst blend state bits\n"); break; } glEnable(GL_BLEND); GL_BlendFunc(srcFactor, dstFactor); } else { glDisable(GL_BLEND); } } // check colormask if (diff & GLS_COLORMASK_BITS) { if (stateBits & GLS_COLORMASK_BITS) { GL_ColorMask((stateBits & GLS_REDMASK_FALSE) ? GL_FALSE : GL_TRUE, (stateBits & GLS_GREENMASK_FALSE) ? GL_FALSE : GL_TRUE, (stateBits & GLS_BLUEMASK_FALSE) ? GL_FALSE : GL_TRUE, (stateBits & GLS_ALPHAMASK_FALSE) ? GL_FALSE : GL_TRUE); } else { GL_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } // check depthmask if (diff & GLS_DEPTHMASK_TRUE) { if (stateBits & GLS_DEPTHMASK_TRUE) { GL_DepthMask(GL_TRUE); } else { GL_DepthMask(GL_FALSE); } } // fill/line mode if (diff & GLS_POLYMODE_LINE) { if (stateBits & GLS_POLYMODE_LINE) { GL_PolygonMode(GL_FRONT_AND_BACK, GL_LINE); } else { GL_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } // depthtest if (diff & GLS_DEPTHTEST_DISABLE) { if (stateBits & GLS_DEPTHTEST_DISABLE) { glDisable(GL_DEPTH_TEST); } else { glEnable(GL_DEPTH_TEST); } } // alpha test - deprecated in OpenGL 3.0 #if 0 if (diff & GLS_ATEST_BITS) { switch (stateBits & GLS_ATEST_BITS) { case GLS_ATEST_GT_0: case GLS_ATEST_LT_128: case GLS_ATEST_GE_128: //case GLS_ATEST_GT_CUSTOM: glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); break; default: case 0: glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); break; } } #endif /* if(diff & GLS_ATEST_BITS) { switch (stateBits & GLS_ATEST_BITS) { case 0: glDisable(GL_ALPHA_TEST); break; case GLS_ATEST_GT_0: glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); break; case GLS_ATEST_LT_80: glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_LESS, 0.5f); break; case GLS_ATEST_GE_80: glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL, 0.5f); break; case GLS_ATEST_GT_CUSTOM: // FIXME glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); break; default: assert(0); break; } } */ // stenciltest if (diff & GLS_STENCILTEST_ENABLE) { if (stateBits & GLS_STENCILTEST_ENABLE) { glEnable(GL_STENCIL_TEST); } else { glDisable(GL_STENCIL_TEST); } } glState.glStateBits = stateBits; }
/* ================= R_Bloom_GeneratexCross - alternative bluring method ================= */ void R_Bloom_GeneratexCross( void ) { int i; static int BLOOM_BLUR_RADIUS = 8; //static float BLOOM_BLUR_INTENSITY = 2.5f; float BLOOM_BLUR_INTENSITY; static float intensity; static float range; //set up sample size workspace qglViewport( 0, 0, sample_width, sample_height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, sample_width, sample_height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); //copy small scene into r_bloomeffecttexture GL_Bind(0, r_bloomeffecttexture); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //start modifying the small scene corner qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Enable(GL_BLEND); //darkening passes if( r_bloom_darken->value ) { GL_BlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); for(i=0; i<r_bloom_darken->value ; i++) { R_Bloom_SamplePass( 0, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //bluring passes if( BLOOM_BLUR_RADIUS ) { GL_BlendFunc(GL_ONE, GL_ONE); range = (float)BLOOM_BLUR_RADIUS; BLOOM_BLUR_INTENSITY = r_bloom_intensity->value; //diagonal-cross draw 4 passes to add initial smooth qglColor4f( 0.5f, 0.5f, 0.5f, 1.0); R_Bloom_SamplePass( 1, 1 ); R_Bloom_SamplePass( -1, 1 ); R_Bloom_SamplePass( -1, -1 ); R_Bloom_SamplePass( 1, -1 ); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) { intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range)); if( intensity < 0.05f ) continue; qglColor4f( intensity, intensity, intensity, 1.0f); R_Bloom_SamplePass( i, 0 ); //R_Bloom_SamplePass( -i, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //for(i=0;i<BLOOM_BLUR_RADIUS;i++) { for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) { intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range)); if( intensity < 0.05f ) continue; qglColor4f( intensity, intensity, intensity, 1.0f); R_Bloom_SamplePass( 0, i ); //R_Bloom_SamplePass( 0, -i ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //restore full screen workspace qglViewport( 0, 0, glState.width, glState.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, glState.width, glState.height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); }
/* ================= R_Bloom_GeneratexDiamonds ================= */ void R_Bloom_GeneratexDiamonds( refdef_t *fd ) { int i, j; static float intensity; //set up sample size workspace qglViewport( 0, 0, sample_width, sample_height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, sample_width, sample_height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); //copy small scene into r_bloomeffecttexture GL_Bind(r_bloomeffecttexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //start modifying the small scene corner qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Enable(GL_BLEND); //Com_Printf("%d %d\n", r_bloom_darken->value, fd->bloomdarken); //darkening passes if( r_bloom_darken->value ) { GL_BlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); for(i=0; i< r_bloom_darken->value ; i++) { R_Bloom_SamplePass( 0, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //bluring passes //GL_BlendFunc(GL_ONE, GL_ONE); GL_BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); if( r_bloom_diamond_size->value > 7 || r_bloom_diamond_size->value <= 3) { if( (int)r_bloom_diamond_size->value != 8 ) Cvar_SetValue( "r_bloom_diamond_size", 8 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.3 * Diamond8x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-4, j-4 ); } } } else if( r_bloom_diamond_size->value > 5 ) { if( r_bloom_diamond_size->value != 6 ) Cvar_SetValue( "r_bloom_diamond_size", 6 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.5 * Diamond6x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-3, j-3 ); } } } else if( r_bloom_diamond_size->value > 3 ) { if( (int)r_bloom_diamond_size->value != 4 ) Cvar_SetValue( "r_bloom_diamond_size", 4 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.8f * Diamond4x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-2, j-2 ); } } } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //restore full screen workspace qglViewport( 0, 0, vid.width, vid.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, vid.width, vid.height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); }
void R_BloomBlend ( refdef_t *fd ) { if( !(fd->rdflags & RDF_BLOOM) || !r_bloom->value || r_showtris->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 qglViewport ( 0, 0, vid.width, vid.height ); GL_TexEnv (GL_REPLACE); // Knightmare added GL_Disable (GL_DEPTH_TEST); qglMatrixMode (GL_PROJECTION); qglLoadIdentity (); qglOrtho(0, vid.width, vid.height, 0, -10, 100); qglMatrixMode (GL_MODELVIEW); qglLoadIdentity (); GL_Disable (GL_CULL_FACE); GL_Disable (GL_BLEND); qglEnable (GL_TEXTURE_2D); qglColor4f (1, 1, 1, 1); //set up current sizes curView_x = fd->x; curView_y = fd->y; curView_width = fd->width; curView_height = fd->height; screenText_tcw = ((float)fd->width / (float)screen_texture_width); screenText_tch = ((float)fd->height / (float)screen_texture_height); if( fd->height > fd->width ) { sampleText_tcw = ((float)fd->width / (float)fd->height); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ((float)fd->height / (float)fd->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(r_bloombackuptexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch); //create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds( fd ); //R_Bloom_GeneratexCross(); //restore the screen-backup to the screen GL_Disable(GL_BLEND); GL_Bind(r_bloombackuptexture->texnum); qglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, vid.height - (r_screenbackuptexture_size * sampleText_tch), r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch, sampleText_tcw, sampleText_tch ); R_Bloom_DrawEffect( fd ); // Knightmare added R_SetupGL (); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglEnable (GL_TEXTURE_2D); qglColor4f(1,1,1,1); }
/* ================= 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; }
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_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); }
void Pass::setup(GLRenderer *) { vec4_t ambient = { sunLight.ambient[0] * 0.8, sunLight.ambient[1] * 0.8, sunLight.ambient[2] * 0.95, 1 }; GLSL_reset(); shader = NULL; lightCount = 0; glPushAttrib(attrib_bits); //GL_Enable(GL_SCISSOR_TEST); GL_SwitchTexUnit(GL_TEXTURE0_ARB); //defaults for pass GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_Enable(GL_CULL_FACE); GL_Enable(GL_ALPHA_TEST); //glAlphaFunc(GL_GREATER, 0.0); GL_ResetColor(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //enable the lights for this pass by default if(allowLighting()) { if(gfx_GLSLQuality.integer <= 1) M_MultVec3(ambient, 1.5, ambient); GL_Enable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, true); glShadeModel(GL_SMOOTH); } //GL_Enable(GL_NORMALIZE); //framebuffer if(gfx_postProcessing.integer) { if(!target) target = glScreen; target->makeTarget(); } else { glScreen->makeTarget(); } //depth GL_Enable(GL_DEPTH_TEST); GL_DepthMask(depthMask); GL_DepthFunc(depthFunc); if(preclearDepth) { glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); } if(viewer) { vec4_t rect; //FIXME: probably should be a data member for configurable pass "windows" SET_VEC4(rect, 0, 0, viewer->width, viewer->height); Scene_SetFrustum(viewer, rect); Scene_BuildOccluderList(viewer); if(gfx_debugCamera.integer>0) { camera_t debugcam; vec3_t back; M_MultVec3(viewer->viewaxis[AXIS_FORWARD], -gfx_debugCamera.integer, back); memcpy(&debugcam, viewer, sizeof(camera_t)); M_AddVec3(debugcam.origin, back, debugcam.origin); GL_PushCamera(&debugcam); } else { GL_PushCamera(viewer); //scene_cam = viewer; } //fog if (viewer->fog_far > 0 && gfx_fog.integer) { vec4_t fog_color = { gfx_fogr.value, gfx_fogg.value, gfx_fogb.value, 0 }; GL_Enable(GL_FOG); if(gfx_nicerFog.integer) { glFogf(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, 1.5 / viewer->fog_far); // Notaus: old value was fixed at 0.00072 and not appropriate for very foggy maps } else { glFogf(GL_FOG_MODE, GL_LINEAR); } glHint(GL_FOG_HINT, GL_NICEST); if (viewer->fog_near > 0 && viewer->fog_far >= viewer->fog_near) { glFogf(GL_FOG_START, viewer->fog_near); glFogf(GL_FOG_END, viewer->fog_far); fog_near = viewer->fog_near; fog_far = viewer->fog_far; } else { glFogf(GL_FOG_START, gfx_fog_near.value); glFogf(GL_FOG_END, gfx_fog_far.value); fog_near = gfx_fog_near.value; fog_far = gfx_fog_far.value; } glFogfv(GL_FOG_COLOR, fog_color); } else if (gfx_fog.integer==0) { GL_Enable(GL_FOG); glFogf(GL_FOG_START, 90000); glFogf(GL_FOG_END, 100000); //shaders make it better just to set this ridiculously far out } else { GL_Disable(GL_FOG); } } else { GL_Disable(GL_FOG); } if(gfx_GLSL.integer) Cvar_SetVarValue(&gfx_GLSLPass, 1); else GL_TexModulate(2.0); #ifdef DEBUG GLSL_catchLastError("Pass::setup()"); #endif }
/* ================= 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); }