Пример #1
0
/*
=================
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);
	}
}
Пример #2
0
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
}
Пример #3
0
/*
 * =================
 * 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);
}
Пример #4
0
/*
==============
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);
}
Пример #5
0
/*
=================
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);
	}
}
Пример #6
0
/*
=================
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);
}
Пример #7
0
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);
}
Пример #8
0
/*
=================
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);
}
Пример #9
0
/*
=================
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 );
    }
}
Пример #10
0
/*
 * =================
 * 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);
    }
Пример #11
0
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);
	}
}
Пример #12
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;
}
Пример #13
0
/*
=================
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 ();
}
Пример #14
0
/*
=================
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 ();
}
Пример #15
0
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);
}
Пример #16
0
/*
=================
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;
}
Пример #17
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);
}
Пример #18
0
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);
}
Пример #19
0
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
}
Пример #20
0
/*
=================
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);
}