/*
=================
RB_DrawArrays
=================
*/
void RB_DrawArrays (GLenum polyMode)
{
	if (rb_vertex == 0 || rb_index == 0) // nothing to render
		return;

	GL_LockArrays (rb_vertex);
	if (gl_config.drawRangeElements)
		qglDrawRangeElementsEXT(polyMode, 0, rb_vertex, rb_index, GL_UNSIGNED_INT, indexArray);
	else
		qglDrawElements(polyMode, rb_index, GL_UNSIGNED_INT, indexArray);
	GL_UnlockArrays ();
}
Exemple #2
0
/*
=================
RB_DrawArrays
=================
*/
void RB_DrawArrays (void)
{
	if (rb_vertex == 0 || rb_index == 0) // nothing to render
		return;

	GL_LockArrays (rb_vertex);
	if (glConfig.drawRangeElements)
		qglDrawRangeElementsEXT(GL_TRIANGLES, 0, rb_vertex, rb_index, GL_UNSIGNED_INT, indexArray);
	else
		qglDrawElements(GL_TRIANGLES, rb_index, GL_UNSIGNED_INT, indexArray);
	GL_UnlockArrays ();
}
/*
=============
R_DrawAliasVolumeShadow
based on code from BeefQuake R6
=============
*/
void R_DrawAliasVolumeShadow (maliasmodel_t *paliashdr, vec3_t bbox[8])
{
	vec3_t		light, temp, vecAdd;
	float		dist, highest, lowest, projected_distance;
	float		angle, cosp, sinp, cosy, siny, cosr, sinr, ix, iy, iz;
	int			i, lnum;
	dlight_t	*dl;

	dl = r_newrefdef.dlights;

	VectorSet(vecAdd, 680,0,1024); // set base vector, was 576,0,1024

	// compute average light vector from dlights
	for (i=0, lnum=0; i<r_newrefdef.num_dlights; i++, dl++)
	{
		if (VectorCompare(dl->origin, currententity->origin))
			continue;
		
		VectorSubtract(dl->origin, currententity->origin, temp);
		dist = dl->intensity - VectorLength(temp);
		if (dist <= 0)
			continue;
		
		lnum++;
		// Factor in the intensity of a dlight
		VectorScale (temp, dist*0.25, temp);
		VectorAdd (vecAdd, temp, vecAdd);
	}
	VectorNormalize(vecAdd);
	VectorScale(vecAdd, 1024, vecAdd);

	// get projection distance from lightspot height
	highest = lowest = bbox[0][2];
	for (i=0; i<8; i++) {
		if (bbox[i][2] > highest) highest = bbox[i][2];
		if (bbox[i][2] < lowest) lowest = bbox[i][2];
	}
	projected_distance = (fabs(highest - lightspot[2]) + (highest-lowest)) / vecAdd[2];

	VectorCopy(vecAdd, light);
	
	/*cosy = cos(-currententity->angles[YAW] / 180 * M_PI);
	siny = sin(-currententity->angles[YAW] / 180 * M_PI);

	ix = light[0], iy = light[1];
	light[0] = (cosy * (ix - 0) + siny * (0 - iy) + 0);
	light[1] = (cosy * (iy - 0) + siny * (ix - 0) + 0);
	light[2] += 8;*/

	// reverse-rotate light vector based on angles
	angle = -currententity->angles[PITCH] / 180 * M_PI;
	cosp = cos(angle), sinp = sin(angle);
	angle = -currententity->angles[YAW] / 180 * M_PI;
	cosy = cos(angle), siny = sin(angle);
	angle = currententity->angles[ROLL] / 180 * M_PI; // roll is backwards
	cosr = cos(angle), sinr = sin(angle);

	// rotate for yaw (z axis)
	ix = light[0], iy = light[1];
	light[0] = cosy * ix - siny * iy + 0;
	light[1] = siny * ix + cosy * iy + 0;

	// rotate for pitch (y axis)
	ix = light[0], iz = light[2];
	light[0] = cosp * ix + 0 + sinp * iz;
	light[2] = -sinp * ix + 0 + cosp * iz;

	// rotate for roll (x axis)
	iy = light[1], iz = light[2];
	light[1] = 0 + cosr * iy - sinr * iz;
	light[2] = 0 + sinr * iy + cosr * iz;


	// set up stenciling
	if (!r_shadowvolumes->value)
	{
		qglPushAttrib(GL_STENCIL_BUFFER_BIT); // save stencil buffer
		qglClear(GL_STENCIL_BUFFER_BIT);

		qglColorMask(0,0,0,0);
		GL_DepthMask(0);
		GL_DepthFunc(GL_LESS);

		GL_Enable(GL_STENCIL_TEST);
		qglStencilFunc(GL_ALWAYS, 0, 255);
	//	qglStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
	//	qglStencilMask (255);
	}

	// build shadow volumes and render each to stencil buffer
	for (i=0; i<paliashdr->num_meshes; i++)
	{
		if (paliashdr->meshes[i].skins[currententity->skinnum].renderparms.nodraw
			|| paliashdr->meshes[i].skins[currententity->skinnum].renderparms.alphatest
			|| paliashdr->meshes[i].skins[currententity->skinnum].renderparms.noshadow)
			continue;

		R_BuildShadowVolume (paliashdr, i, light, projected_distance, r_shadowvolumes->value);
		GL_LockArrays (shadow_va);

		if (!r_shadowvolumes->value)
		{
			if (gl_config.atiSeparateStencil && gl_config.extStencilWrap) // Barnes ATI stenciling
			{
				GL_Disable(GL_CULL_FACE);

				qglStencilOpSeparateATI (GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP); 
				qglStencilOpSeparateATI (GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);

				R_DrawShadowVolume ();

				GL_Enable(GL_CULL_FACE);
			}
			else if (gl_config.extStencilTwoSide && gl_config.extStencilWrap) // Echon's two-sided stenciling
			{
				GL_Disable(GL_CULL_FACE);
				qglEnable (GL_STENCIL_TEST_TWO_SIDE_EXT);

				qglActiveStencilFaceEXT (GL_BACK);
				qglStencilOp (GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
				qglActiveStencilFaceEXT (GL_FRONT);
				qglStencilOp (GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);

				R_DrawShadowVolume ();

				qglDisable (GL_STENCIL_TEST_TWO_SIDE_EXT);
				GL_Enable(GL_CULL_FACE);
			}
			else
			{	// increment stencil if backface is behind depthbuffer
				GL_CullFace(GL_BACK); // quake is backwards, this culls front faces
				qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
				R_DrawShadowVolume ();

				// decrement stencil if frontface is behind depthbuffer
				GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
				qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
				R_DrawShadowVolume ();
			}
		}
		else
			R_DrawShadowVolume ();

		GL_UnlockArrays ();
	}

	// end stenciling and draw stenciled volume
	if (!r_shadowvolumes->value)
	{
		GL_CullFace(GL_FRONT);
		GL_Disable(GL_STENCIL_TEST);
		
		GL_DepthFunc(GL_LEQUAL);
		GL_DepthMask(1);
		qglColorMask(1,1,1,1);
		
		// draw shadows for this model now
		R_ShadowBlend (aliasShadowAlpha * currententity->alpha); // was r_shadowalpha->value
		qglPopAttrib(); // restore stencil buffer
	}
}