Example #1
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
}
Example #2
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;
}
Example #3
0
/*
=============
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
	}
}