示例#1
0
void GLWall::RenderTextured(int rflags)
{
	int tmode = gl_RenderState.GetTextureMode();
	int rel = rellight + getExtraLight();

	if (flags & GLWF_GLOW)
	{
		gl_RenderState.EnableGlow(true);
		gl_RenderState.SetGlowPlanes(topplane, bottomplane);
		gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor);
	}
	gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false);

	if (type == RENDERWALL_M2SNF)
	{
		if (flags & GLT_CLAMPY)
		{
			if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY);
		}
		gl_SetFog(255, 0, NULL, false);
	}

	float absalpha = fabsf(alpha);
	if (lightlist == NULL)
	{
		gl_SetColor(lightlevel, rel, Colormap, absalpha);
		if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add);
		RenderWall(rflags);
	}
	else
	{
		gl_RenderState.EnableSplit(true);

		for (unsigned i = 0; i < lightlist->Size(); i++)
		{
			secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane;
			// this must use the exact same calculation method as GLWall::Process etc.
			float low1 = lowplane.ZatPoint(vertexes[0]);
			float low2 = lowplane.ZatPoint(vertexes[1]);

			if (low1 < ztop[0] || low2 < ztop[1])
			{
				int thisll = (*lightlist)[i].caster != NULL ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
				FColormap thiscm;
				thiscm.FadeColor = Colormap.FadeColor;
				thiscm.CopyFrom3DLight(&(*lightlist)[i]);
				gl_SetColor(thisll, rel, thiscm, absalpha);
				if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
				gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, lowplane);
				RenderWall(rflags);
			}
			if (low1 <= zbottom[0] && low2 <= zbottom[1]) break;
		}

		gl_RenderState.EnableSplit(false);
	}
	gl_RenderState.SetTextureMode(tmode);
	gl_RenderState.EnableGlow(false);
}
void GLWall::RenderTranslucentWall()
{
	bool transparent = gltexture? gltexture->GetTransparent() : false;
	
	// currently the only modes possible are solid, additive or translucent
	// and until that changes I won't fix this code for the new blending modes!
	bool isadditive = RenderStyle == STYLE_Add;

	if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE))
	{
		SetupLights();
	}

	if (!transparent) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
	else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
	if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE);

	int extra;
	if (gltexture) 
	{
		gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW));
		gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false);
		extra = getExtraLight();
	}
	else 
	{
		gl_RenderState.EnableTexture(false);
		extra = 0;
	}
	int tmode = gl_RenderState.GetTextureMode();

	gl_SetColor(lightlevel, extra, Colormap, fabsf(alpha));
	if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, extra, &Colormap, isadditive);
	else
	{
		if (flags & GLT_CLAMPY)
		{
			if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY);
		}
		gl_SetFog(255, 0, NULL, false);
	}

	RenderWall(RWF_TEXTURED|RWF_NOSPLIT);

	// restore default settings
	if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	if (!gltexture)	
	{
		gl_RenderState.EnableTexture(true);
	}
	gl_RenderState.EnableGlow(false);
	gl_RenderState.SetTextureMode(tmode);
}
示例#3
0
//==========================================================================
//
//
//
//==========================================================================
void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIGHTSONLY
{
	int rel = getExtraLight();

#ifdef _DEBUG
	if (sector->sectornum == gl_breaksec)
	{
		int a = 0;
	}
#endif


	switch (pass)
	{
	case GLPASS_PLAIN:			// Single-pass rendering
	case GLPASS_ALL:
		gl_SetColor(lightlevel, rel, Colormap,1.0f);
		gl_SetFog(lightlevel, rel, &Colormap, false);
		gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
		gl_SetPlaneTextureRotation(&plane, gltexture);
		DrawSubsectors(pass, (pass == GLPASS_ALL || dynlightindex > -1), false);
		gl_RenderState.EnableTextureMatrix(false);
		break;

	case GLPASS_LIGHTSONLY:
		if (!trans || gltexture)
		{
			ProcessLights(trans);
		}
		break;

	case GLPASS_TRANSLUCENT:
		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
		gl_SetColor(lightlevel, rel, Colormap, alpha);
		gl_SetFog(lightlevel, rel, &Colormap, false);
		gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
		if (!gltexture)	
		{
			gl_RenderState.EnableTexture(false);
			DrawSubsectors(pass, false, true);
			gl_RenderState.EnableTexture(true);
		}
		else 
		{
			gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
			gl_SetPlaneTextureRotation(&plane, gltexture);
			DrawSubsectors(pass, true, true);
			gl_RenderState.EnableTextureMatrix(false);
		}
		if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		break;
	}
}
示例#4
0
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DoDrawDecals()
{
	if (seg->sidedef && seg->sidedef->AttachedDecals)
	{
		if (lightlist != NULL)
		{
			gl_RenderState.EnableSplit(true);
		}
		else
		{
			gl_SetFog(lightlevel, rellight + getExtraLight(), &Colormap, false);
		}

		DBaseDecal *decal = seg->sidedef->AttachedDecals;
		while (decal)
		{
			DrawDecal(decal);
			decal = decal->WallNext;
		}

		if (lightlist != NULL)
		{
			gl_RenderState.EnableSplit(false);
		}

	}
}
示例#5
0
void GLWall::RenderFogBoundary()
{
	if (gl_fogmode && gl_fixedcolormap == 0)
	{
		if (!gl.legacyMode)
		{
			int rel = rellight + getExtraLight();
			gl_SetFog(lightlevel, rel, &Colormap, false);
			gl_RenderState.EnableDrawBuffers(1);
			gl_RenderState.SetEffect(EFF_FOGBOUNDARY);
			gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
			glEnable(GL_POLYGON_OFFSET_FILL);
			glPolygonOffset(-1.0f, -128.0f);
			RenderWall(RWF_BLANK);
			glPolygonOffset(0.0f, 0.0f);
			glDisable(GL_POLYGON_OFFSET_FILL);
			gl_RenderState.SetEffect(EFF_NONE);
			gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
		}
		else
		{
			RenderFogBoundaryCompat();
		}
	}
}
示例#6
0
//==========================================================================
//
// 
//
//==========================================================================
void GLWall::RenderMirrorSurface()
{
	if (GLRenderer->mirrortexture == NULL) return;

	// For the sphere map effect we need a normal of the mirror surface,
	FVector3 v = glseg.Normal();

	if (!gl.legacyMode)
	{
		// we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is.
		tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X;
		tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z;

		gl_RenderState.EnableTextureMatrix(true);
		gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix);
	}
	else
	{
		glNormal3fv(&v[0]);
	}

	// Use sphere mapping for this
	gl_RenderState.SetEffect(EFF_SPHEREMAP);

	gl_SetColor(lightlevel, 0, Colormap ,0.1f);
	gl_SetFog(lightlevel, 0, &Colormap, true);
	gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE);
	gl_RenderState.AlphaFunc(GL_GREATER,0);
	glDepthFunc(GL_LEQUAL);

	FMaterial * pat=FMaterial::ValidateTexture(GLRenderer->mirrortexture, false);
	gl_RenderState.SetMaterial(pat, CLAMP_NONE, 0, -1, false);

	flags &= ~GLWF_GLOW;
	RenderWall(RWF_BLANK);

	gl_RenderState.EnableTextureMatrix(false);
	gl_RenderState.SetEffect(EFF_NONE);

	// Restore the defaults for the translucent pass
	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
	glDepthFunc(GL_LESS);

	// This is drawn in the translucent pass which is done after the decal pass
	// As a result the decals have to be drawn here.
	if (seg->sidedef->AttachedDecals)
	{
		glEnable(GL_POLYGON_OFFSET_FILL);
		glPolygonOffset(-1.0f, -128.0f);
		glDepthMask(false);
		DoDrawDecals();
		glDepthMask(true);
		glPolygonOffset(0.0f, 0.0f);
		glDisable(GL_POLYGON_OFFSET_FILL);
		gl_RenderState.SetTextureMode(TM_MODULATE);
		gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}
}
示例#7
0
void GLWall::RenderTranslucentWall()
{
	if (gltexture)
	{
		if (gl_fixedcolormap == CM_DEFAULT && gl_lights && gl.lightmethod == LM_DIRECT)
		{
			SetupLights();
		}
		if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
		else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
		if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE);
		RenderTextured(RWF_TEXTURED | RWF_NOSPLIT);
		if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}
	else
	{
		gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
		gl_SetColor(lightlevel, 0, Colormap, fabsf(alpha));
		gl_SetFog(lightlevel, 0, &Colormap, RenderStyle == STYLE_Add);
		gl_RenderState.EnableTexture(false);
		RenderWall(RWF_NOSPLIT);
		gl_RenderState.EnableTexture(true);
	}
}
示例#8
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Horizon Portal
//
// This simply draws the area in medium sized squares. Drawing it as a whole
// polygon creates visible inaccuracies.
//
// Originally I tried to minimize the amount of data to be drawn but there
// are 2 problems with it:
//
// 1. Setting this up completely negates any performance gains.
// 2. It doesn't work with a 360° field of view (as when you are looking up.)
//
//
// So the brute force mechanism is just as good.
//
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// GLHorizonPortal::DrawContents
//
//-----------------------------------------------------------------------------
void GLHorizonPortal::DrawContents()
{
	PortalAll.Clock();

	GLSectorPlane * sp=&origin->plane;
	FMaterial * gltexture;
	PalEntry color;
	float z;
	player_t * player=&players[consoleplayer];

	gltexture=FMaterial::ValidateTexture(sp->texture, true);
	if (!gltexture) 
	{
		ClearScreen();
		PortalAll.Unclock();
		return;
	}


	z=FIXED2FLOAT(sp->texheight);


	if (gltexture && gltexture->tex->isFullbright())
	{
		// glowing textures are always drawn full bright without color
		gl_SetColor(255, 0, NULL, 1.f);
		gl_SetFog(255, 0, &origin->colormap, false);
	}
	else 
	{
		int rel = getExtraLight();
		gl_SetColor(origin->lightlevel, rel, &origin->colormap, 1.0f);
		gl_SetFog(origin->lightlevel, rel, &origin->colormap, false);
	}


	gltexture->Bind(origin->colormap.colormap);

	gl_RenderState.EnableAlphaTest(false);
	gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
	gl_RenderState.Apply();


	bool pushed = gl_SetPlaneTextureRotation(sp, gltexture);

	float vx=FIXED2FLOAT(viewx);
	float vy=FIXED2FLOAT(viewy);

	// Draw to some far away boundary
	for(float x=-32768+vx; x<32768+vx; x+=4096)
	{
		for(float y=-32768+vy; y<32768+vy;y+=4096)
		{
			glBegin(GL_TRIANGLE_FAN);

			glTexCoord2f(x/64, -y/64);
			glVertex3f(x, z, y);

			glTexCoord2f(x/64 + 64, -y/64);
			glVertex3f(x + 4096, z, y);

			glTexCoord2f(x/64 + 64, -y/64 - 64);
			glVertex3f(x + 4096, z, y + 4096);

			glTexCoord2f(x/64, -y/64 - 64);
			glVertex3f(x, z, y + 4096);

			glEnd();

		}
	}

	float vz=FIXED2FLOAT(viewz);
	float tz=(z-vz);///64.0f;

	// fill the gap between the polygon and the true horizon
	// Since I can't draw into infinity there can always be a
	// small gap

	glBegin(GL_TRIANGLE_STRIP);

	glTexCoord2f(512.f, 0);
	glVertex3f(-32768+vx, z, -32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f(-32768+vx, vz, -32768+vy);

	glTexCoord2f(-512.f, 0);
	glVertex3f(-32768+vx, z,  32768+vy);
	glTexCoord2f(-512.f, tz);
	glVertex3f(-32768+vx, vz,  32768+vy);

	glTexCoord2f(512.f, 0);
	glVertex3f( 32768+vx, z,  32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f( 32768+vx, vz,  32768+vy);

	glTexCoord2f(-512.f, 0);
	glVertex3f( 32768+vx, z, -32768+vy);
	glTexCoord2f(-512.f, tz);
	glVertex3f( 32768+vx, vz, -32768+vy);

	glTexCoord2f(512.f, 0);
	glVertex3f(-32768+vx, z, -32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f(-32768+vx, vz, -32768+vy);

	glEnd();

	if (pushed)
	{
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
	}

	PortalAll.Unclock();

}
示例#9
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FMaterial * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FMaterial::ValidateTexture(plane.texture, true);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.Clear();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
	}

	int rel = getExtraLight();
	gl_SetColor(lightlevel, rel, Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind();

	float fviewx = FIXED2FLOAT(viewx);
	float fviewy = FIXED2FLOAT(viewy);
	float fviewz = FIXED2FLOAT(viewz);

	gl_SetPlaneTextureRotation(&plane, gltexture);
	gl_RenderState.Apply();

	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
	ptr->Set(px1, planez, py1, px1 / 64, -py1 / 64);
	ptr++;
	ptr->Set(px2, planez, py2, px2 / 64, -py2 / 64);
	ptr++;
	ptr->Set(px3, planez, py3, px3 / 64, -py3 / 64);
	ptr++;
	ptr->Set(px4, planez, py4, px4 / 64, -py4 / 64);
	ptr++;
	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);

	gl_RenderState.EnableTextureMatrix(false);
}
示例#10
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FMaterial * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FMaterial::ValidateTexture(plane.texture, true);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.GetFixedColormap();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
	}

	int rel = getExtraLight();
	gl_SetColor(lightlevel, rel, &Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind(Colormap.colormap);

	float fviewx = FIXED2FLOAT(viewx);
	float fviewy = FIXED2FLOAT(viewy);
	float fviewz = FIXED2FLOAT(viewz);

	gl_RenderState.Apply();

	bool pushed = gl_SetPlaneTextureRotation(&plane, gltexture);

	glBegin(GL_TRIANGLE_FAN);
	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	glTexCoord2f(px1 / 64, -py1 / 64);
	glVertex3f(px1, planez, py1);

	glTexCoord2f(px2 / 64, -py2 / 64);
	glVertex3f(px2, planez, py2);

	glTexCoord2f(px3 / 64, -py3 / 64);
	glVertex3f(px3, planez, py3);

	glTexCoord2f(px4 / 64, -py4 / 64);
	glVertex3f(px4, planez, py4);

	glEnd();

	if (pushed)
	{
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
	}
}
示例#11
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FMaterial * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FMaterial::ValidateTexture(plane.texture, false, true);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.Clear();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
	}

	int rel = getExtraLight();
	gl_SetColor(lightlevel, rel, Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);

	float fviewx = ViewPos.X;
	float fviewy = ViewPos.Y;
	float fviewz = ViewPos.Z;

	gl_SetPlaneTextureRotation(&plane, gltexture);
	gl_RenderState.Apply();

	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	FQuadDrawer qd;
	qd.Set(0, px1, planez, py1, px1 / 64, -py1 / 64);
	qd.Set(1, px2, planez, py2, px2 / 64, -py2 / 64);
	qd.Set(2, px3, planez, py3, px3 / 64, -py3 / 64);
	qd.Set(3, px4, planez, py4, px4 / 64, -py4 / 64);
	qd.Render(GL_TRIANGLE_FAN);

	gl_RenderState.EnableTextureMatrix(false);
}
示例#12
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void GLDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FGLTexture * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FGLTexture::ValidateTexture(plane.texture);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.GetFixedColormap();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? GetCeilingLight(sec) : GetFloorLight(sec));
	}

	int rel = extralight * gl_weaponlight;
	gl_SetColor(lightlevel, rel, &Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind(Colormap.LightColor.a);
	gl_SetPlaneTextureRotation(&plane, gltexture);

	float fviewx = TO_GL(viewx);
	float fviewy = TO_GL(viewy);
	float fviewz = TO_GL(viewz);

	gl_ApplyShader();
	gl.Begin(GL_TRIANGLE_FAN);
	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	gl.TexCoord2f(px1 / 64, -py1 / 64);
	gl.Vertex3f(px1, planez, py1);

	gl.TexCoord2f(px2 / 64, -py2 / 64);
	gl.Vertex3f(px2, planez, py2);

	gl.TexCoord2f(px3 / 64, -py3 / 64);
	gl.Vertex3f(px3, planez, py3);

	gl.TexCoord2f(px4 / 64, -py4 / 64);
	gl.Vertex3f(px4, planez, py4);

	gl.End();

	gl.MatrixMode(GL_TEXTURE);
	gl.PopMatrix();
	gl.MatrixMode(GL_MODELVIEW);
}
示例#13
0
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DrawDecal(DBaseDecal *decal)
{
	line_t * line=seg->linedef;
	side_t * side=seg->sidedef;
	int i;
	float zpos;
	int light;
	int rel;
	float a;
	bool flipx, flipy;
	DecalVertex dv[4];
	FTextureID decalTile;
	

	if (decal->RenderFlags & RF_INVISIBLE) return;
	if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return;	// No decals on 3D floors with transparent textures.

	//if (decal->sprite != 0xffff)
	{
		decalTile = decal->PicNum;
		flipx = !!(decal->RenderFlags & RF_XFLIP);
		flipy = !!(decal->RenderFlags & RF_YFLIP);
	}
	/*
	else
	{
	decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0];
	flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1;
	}
	*/

	FTexture *texture = TexMan[decalTile];
	if (texture == NULL) return;

	FMaterial *tex;


	tex = FMaterial::ValidateTexture(texture, true);


	// the sectors are only used for their texture origin coordinates
	// so we don't need the fake sectors for deep water etc.
	// As this is a completely split wall fragment no further splits are
	// necessary for the decal.
	sector_t *frontsector;

	// for 3d-floor segments use the model sector as reference
	if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector;
	else frontsector=seg->frontsector;

	switch (decal->RenderFlags & RF_RELMASK)
	{
	default:
		// No valid decal can have this type. If one is encountered anyway
		// it is in some way invalid so skip it.
		return;
		//zpos = decal->z;
		//break;

	case RF_RELUPPER:
		if (type!=RENDERWALL_TOP) return;
		if (line->flags & ML_DONTPEGTOP)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
		else
		{
			zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
		}
		break;
	case RF_RELLOWER:
		if (type!=RENDERWALL_BOTTOM) return;
		if (line->flags & ML_DONTPEGBOTTOM)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
		else
		{
			zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
		}
		break;
	case RF_RELMID:
		if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return;
		if (line->flags & ML_DONTPEGBOTTOM)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
		}
		else
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
	}
	
	if (decal->RenderFlags & RF_FULLBRIGHT)
	{
		light = 255;
		rel = 0;
	}
	else
	{
		light = lightlevel;
		rel = rellight + getExtraLight();
	}
	
	FColormap p = Colormap;
	
	if (glset.nocoloredspritelighting)
	{
		p.Decolorize();
	}
	
	
	
	a = decal->Alpha;
	
	// now clip the decal to the actual polygon
	float decalwidth = tex->TextureWidth()  * decal->ScaleX;
	float decalheight= tex->TextureHeight() * decal->ScaleY;
	float decallefto = tex->GetLeftOffset() * decal->ScaleX;
	float decaltopo  = tex->GetTopOffset()  * decal->ScaleY;

	
	float leftedge = glseg.fracleft * side->TexelLength;
	float linelength = glseg.fracright * side->TexelLength - leftedge;

	// texel index of the decal's left edge
	float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx? decalwidth-decallefto : decallefto) - leftedge;

	float left,right;
	float lefttex,righttex;

	// decal is off the left edge
	if (decalpixpos < 0)
	{
		left = 0;
		lefttex = -decalpixpos;
	}
	else
	{
		left = decalpixpos;
		lefttex = 0;
	}
	
	// decal is off the right edge
	if (decalpixpos + decalwidth > linelength)
	{
		right = linelength;
		righttex = right - decalpixpos;
	}
	else
	{
		right = decalpixpos + decalwidth;
		righttex = decalwidth;
	}
	if (right<=left) return;	// nothing to draw

	// one texture unit on the wall as vector
	float vx=(glseg.x2-glseg.x1)/linelength;
	float vy=(glseg.y2-glseg.y1)/linelength;
		
	dv[1].x=dv[0].x=glseg.x1+vx*left;
	dv[1].y=dv[0].y=glseg.y1+vy*left;

	dv[3].x=dv[2].x=glseg.x1+vx*right;
	dv[3].y=dv[2].y=glseg.y1+vy*right;
		
	zpos+= (flipy? decalheight-decaltopo : decaltopo);

	dv[1].z=dv[2].z = zpos;
	dv[0].z=dv[3].z = dv[1].z - decalheight;
	dv[1].v=dv[2].v = tex->GetVT();

	dv[1].u=dv[0].u = tex->GetU(lefttex / decal->ScaleX);
	dv[3].u=dv[2].u = tex->GetU(righttex / decal->ScaleX);
	dv[0].v=dv[3].v = tex->GetVB();


	// now clip to the top plane
	float vzt=(ztop[1]-ztop[0])/linelength;
	float topleft=this->ztop[0]+vzt*left;
	float topright=this->ztop[0]+vzt*right;

	// completely below the wall
	if (topleft<dv[0].z && topright<dv[3].z) 
		return;

	if (topleft<dv[1].z || topright<dv[2].z)
	{
		// decal has to be clipped at the top
		// let texture clamping handle all extreme cases
		dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v;
		dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v;
		dv[1].z=topleft;
		dv[2].z=topright;
	}

	// now clip to the bottom plane
	float vzb=(zbottom[1]-zbottom[0])/linelength;
	float bottomleft=this->zbottom[0]+vzb*left;
	float bottomright=this->zbottom[0]+vzb*right;

	// completely above the wall
	if (bottomleft>dv[1].z && bottomright>dv[2].z) 
		return;

	if (bottomleft>dv[0].z || bottomright>dv[3].z)
	{
		// decal has to be clipped at the bottom
		// let texture clamping handle all extreme cases
		dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v;
		dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v;
		dv[0].z=bottomleft;
		dv[3].z=bottomright;
	}


	if (flipx)
	{
		float ur = tex->GetUR();
		for(i=0;i<4;i++) dv[i].u=ur-dv[i].u;
	}
	if (flipy)
	{
		float vb = tex->GetVB();
		for(i=0;i<4;i++) dv[i].v=vb-dv[i].v;
	}

	// calculate dynamic light effect.
	if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites)
	{
		// Note: This should be replaced with proper shader based lighting.
		double x, y;
		decal->GetXY(seg->sidedef, x, y);
		gl_SetDynSpriteLight(NULL, x, y, zpos, sub);
	}

	// alpha color only has an effect when using an alpha texture.
	if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
	{
		gl_RenderState.SetObjectColor(decal->AlphaColor|0xff000000);
	}




	gl_SetRenderStyle(decal->RenderStyle, false, false);
	gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha));


	// If srcalpha is one it looks better with a higher alpha threshold
	if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
	else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);


	gl_SetColor(light, rel, p, a);
	// for additively drawn decals we must temporarily set the fog color to black.
	PalEntry fc = gl_RenderState.GetFogColor();
	if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
	{
		gl_RenderState.SetFog(0,-1);
	}

	FQuadDrawer qd;
	for (i = 0; i < 4; i++)
	{
		qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
	}

	if (lightlist == NULL)
	{
		gl_RenderState.Apply();
		qd.Render(GL_TRIANGLE_FAN);
	}
	else
	{
		for (unsigned k = 0; k < lightlist->Size(); k++)
		{
			secplane_t &lowplane = k == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[k + 1].plane;

			float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
			float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);

			if (low1 < dv[1].z || low2 < dv[2].z)
			{
				int thisll = (*lightlist)[k].caster != NULL ? gl_ClampLight(*(*lightlist)[k].p_lightlevel) : lightlevel;
				FColormap thiscm;
				thiscm.FadeColor = Colormap.FadeColor;
				thiscm.CopyFrom3DLight(&(*lightlist)[k]);
				gl_SetColor(thisll, rel, thiscm, a);
				if (glset.nocoloredspritelighting) thiscm.Decolorize();
				gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
				gl_RenderState.SetSplitPlanes((*lightlist)[k].plane, lowplane);

				gl_RenderState.Apply();
				qd.Render(GL_TRIANGLE_FAN);
			}
			if (low1 <= dv[0].z && low2 <= dv[3].z) break;
		}
	}

	rendered_decals++;
	gl_RenderState.SetTextureMode(TM_MODULATE);
	gl_RenderState.SetObjectColor(0xffffffff);
	gl_RenderState.SetFog(fc,-1);
	gl_RenderState.SetDynLight(0,0,0);
}
示例#14
0
//==========================================================================
//
// 
//
//==========================================================================
void GLWall::Draw(int pass)
{
	int rel;
	int tmode;

#ifdef _DEBUG
	if (seg->linedef-lines==879)
	{
		int a = 0;
	}
#endif


	switch (pass)
	{
	case GLPASS_LIGHTSONLY:
		SetupLights();
		break;

	case GLPASS_ALL:
		SetupLights();
		// fall through
	case GLPASS_PLAIN:
		rel = rellight + getExtraLight();
		gl_SetColor(lightlevel, rel, Colormap,1.0f);
		tmode = gl_RenderState.GetTextureMode();
		if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false);
		else
		{
			if (flags & GLT_CLAMPY)
			{
				if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY);
			}
			gl_SetFog(255, 0, NULL, false);
		}
		gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW));
		gl_RenderState.SetMaterial(gltexture, flags & 3, false, -1, false);
		RenderWall(RWF_TEXTURED|RWF_GLOW);
		gl_RenderState.EnableGlow(false);
		gl_RenderState.SetTextureMode(tmode);
		break;

	case GLPASS_TRANSLUCENT:


		switch (type)
		{
		case RENDERWALL_MIRRORSURFACE:
			RenderMirrorSurface();
			break;

		case RENDERWALL_FOGBOUNDARY:
			RenderFogBoundary();
			break;

		case RENDERWALL_COLORLAYER:
			glEnable(GL_POLYGON_OFFSET_FILL);
			glPolygonOffset(-1.0f, -128.0f);
			RenderTranslucentWall();
			glDisable(GL_POLYGON_OFFSET_FILL);
			glPolygonOffset(0, 0);

		default:
			RenderTranslucentWall();
			break;
		}
	}
}
示例#15
0
//==========================================================================
//
//
//
//==========================================================================
void GLSprite::Draw(int pass)
{
    if (pass!=GLPASS_PLAIN && pass != GLPASS_ALL && pass!=GLPASS_TRANSLUCENT) return;


    bool additivefog = false;
    int rel = extralight*gl_weaponlight;

    if (pass==GLPASS_TRANSLUCENT)
    {
        // The translucent pass requires special setup for the various modes.

        // Brightmaps will only be used when doing regular drawing ops and having no fog
        if (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE ||
                RenderStyle.BlendOp != STYLEOP_Add)
        {
            gl_RenderState.EnableBrightmap(false);
        }

        gl_SetRenderStyle(RenderStyle, false,
                          // The rest of the needed checks are done inside gl_SetRenderStyle
                          trans > 1.f - FLT_EPSILON && gl_usecolorblending && gl_fixedcolormap < CM_FIRSTSPECIALCOLORMAP && actor &&
                          fullbright && gltexture && !gltexture->GetTransparent());

        if (hw_styleflags == STYLEHW_NoAlphaTest)
        {
            gl_RenderState.EnableAlphaTest(false);
        }
        else
        {
            gl_RenderState.AlphaFunc(GL_GEQUAL,trans*gl_mask_sprite_threshold);
        }

        if (RenderStyle.BlendOp == STYLEOP_Fuzz)
        {
            float fuzzalpha=0.44f;
            float minalpha=0.1f;

            // fog + fuzz don't work well without some fiddling with the alpha value!
            if (!gl_isBlack(Colormap.FadeColor))
            {
                float xcamera=FIXED2FLOAT(viewx);
                float ycamera=FIXED2FLOAT(viewy);

                float dist=Dist2(xcamera,ycamera, x,y);

                if (!Colormap.FadeColor.a) Colormap.FadeColor.a=clamp<int>(255-lightlevel,60,255);

                // this value was determined by trial and error and is scale dependent!
                float factor=0.05f+exp(-Colormap.FadeColor.a*dist/62500.f);
                fuzzalpha*=factor;
                minalpha*=factor;
            }

            gl_RenderState.AlphaFunc(GL_GEQUAL,minalpha*gl_mask_sprite_threshold);
            gl.Color4f(0.2f,0.2f,0.2f,fuzzalpha);
            additivefog = true;
        }
        else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One)
        {
            additivefog = true;
        }
    }
    if (RenderStyle.BlendOp!=STYLEOP_Fuzz)
    {
        if (actor)
        {
            lightlevel = gl_SetSpriteLighting(RenderStyle, actor, lightlevel, rel, &Colormap, ThingColor, trans,
                                              fullbright || gl_fixedcolormap >= CM_FIRSTSPECIALCOLORMAP, false);
        }
        else if (particle)
        {
            if (gl_light_particles)
            {
                lightlevel = gl_SetSpriteLight(particle, lightlevel, rel, &Colormap, trans, ThingColor);
            }
            else
            {
                gl_SetColor(lightlevel, rel, &Colormap, trans, ThingColor);
            }
        }
        else return;
    }

    if (gl_isBlack(Colormap.FadeColor)) foglevel=lightlevel;

    if (RenderStyle.Flags & STYLEF_FadeToBlack)
    {
        Colormap.FadeColor=0;
        additivefog = true;
    }

    if (RenderStyle.Flags & STYLEF_InvertOverlay)
    {
        Colormap.FadeColor = Colormap.FadeColor.InverseColor();
        additivefog=false;
    }

    gl_SetFog(foglevel, rel, &Colormap, additivefog);

    if (gltexture) gltexture->BindPatch(Colormap.colormap,translation);
    else if (!modelframe) gl_RenderState.EnableTexture(false);

    if (!modelframe)
    {
        // [BB] Billboard stuff
        const bool drawWithXYBillboard = ( !(actor && actor->renderflags & RF_FORCEYBILLBOARD)
                                           //&& GLRenderer->mViewActor != NULL
                                           && (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD )) );
        gl_RenderState.Apply();
        gl.Begin(GL_TRIANGLE_STRIP);
        if ( drawWithXYBillboard )
        {
            // Rotate the sprite about the vector starting at the center of the sprite
            // triangle strip and with direction orthogonal to where the player is looking
            // in the x/y plane.
            float xcenter = (x1+x2)*0.5;
            float ycenter = (y1+y2)*0.5;
            float zcenter = (z1+z2)*0.5;
            float angleRad = DEG2RAD(270. - float(GLRenderer->mAngles.Yaw));

            Matrix3x4 mat;
            mat.MakeIdentity();
            mat.Translate( xcenter, zcenter, ycenter);
            mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch);
            mat.Translate( -xcenter, -zcenter, -ycenter);
            Vector v1 = mat * Vector(x1,z1,y1);
            Vector v2 = mat * Vector(x2,z1,y2);
            Vector v3 = mat * Vector(x1,z2,y1);
            Vector v4 = mat * Vector(x2,z2,y2);

            if (gltexture)
            {
                gl.TexCoord2f(ul, vt);
                gl.Vertex3fv(&v1[0]);
                gl.TexCoord2f(ur, vt);
                gl.Vertex3fv(&v2[0]);
                gl.TexCoord2f(ul, vb);
                gl.Vertex3fv(&v3[0]);
                gl.TexCoord2f(ur, vb);
                gl.Vertex3fv(&v4[0]);
            }
            else	// Particle
            {
                gl.Vertex3fv(&v1[0]);
                gl.Vertex3fv(&v2[0]);
                gl.Vertex3fv(&v3[0]);
                gl.Vertex3fv(&v4[0]);
            }

        }
        else
        {
            if (gltexture)
            {
                gl.TexCoord2f(ul, vt);
                gl.Vertex3f(x1, z1, y1);
                gl.TexCoord2f(ur, vt);
                gl.Vertex3f(x2, z1, y2);
                gl.TexCoord2f(ul, vb);
                gl.Vertex3f(x1, z2, y1);
                gl.TexCoord2f(ur, vb);
                gl.Vertex3f(x2, z2, y2);
            }
            else	// Particle
            {
                gl.Vertex3f(x1, z1, y1);
                gl.Vertex3f(x2, z1, y2);
                gl.Vertex3f(x1, z2, y1);
                gl.Vertex3f(x2, z2, y2);
            }
        }
        gl.End();
    }
    else
    {
        gl_RenderModel(this, Colormap.colormap);
    }

    if (pass==GLPASS_TRANSLUCENT)
    {
        gl_RenderState.EnableBrightmap(true);
        gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        gl_RenderState.BlendEquation(GL_FUNC_ADD);
        gl_RenderState.SetTextureMode(TM_MODULATE);

        // [BB] Restore the alpha test after drawing a smooth particle.
        if (hw_styleflags == STYLEHW_NoAlphaTest)
        {
            gl_RenderState.EnableAlphaTest(true);
        }
        else
        {
            gl_RenderState.AlphaFunc(GL_GEQUAL,gl_mask_sprite_threshold);
        }
    }

    gl_RenderState.EnableTexture(true);
}
示例#16
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Horizon Portal
//
// This simply draws the area in medium sized squares. Drawing it as a whole
// polygon creates visible inaccuracies.
//
// Originally I tried to minimize the amount of data to be drawn but there
// are 2 problems with it:
//
// 1. Setting this up completely negates any performance gains.
// 2. It doesn't work with a 360° field of view (as when you are looking up.)
//
//
// So the brute force mechanism is just as good.
//
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// GLHorizonPortal::DrawContents
//
//-----------------------------------------------------------------------------
void GLHorizonPortal::DrawContents()
{
	PortalAll.Clock();

	GLSectorPlane * sp=&origin->plane;
	FMaterial * gltexture;
	PalEntry color;
	float z;
	player_t * player=&players[consoleplayer];

	gltexture=FMaterial::ValidateTexture(sp->texture, false, true);
	if (!gltexture) 
	{
		ClearScreen();
		PortalAll.Unclock();
		return;
	}
	gl_RenderState.SetCameraPos(ViewPos.X, ViewPos.Y, ViewPos.Z);


	z=sp->Texheight;


	if (gltexture && gltexture->tex->isFullbright())
	{
		// glowing textures are always drawn full bright without color
		gl_SetColor(255, 0, origin->colormap, 1.f);
		gl_SetFog(255, 0, &origin->colormap, false);
	}
	else 
	{
		int rel = getExtraLight();
		gl_SetColor(origin->lightlevel, rel, origin->colormap, 1.0f);
		gl_SetFog(origin->lightlevel, rel, &origin->colormap, false);
	}


	gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);

	gl_SetPlaneTextureRotation(sp, gltexture);
	gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
	gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
	gl_RenderState.Apply();



	float vx= ViewPos.X;
	float vy= ViewPos.Y;

	// Draw to some far away boundary
	// This is not drawn as larher strips because it causes visual glitches.
	for(float x=-32768+vx; x<32768+vx; x+=4096)
	{
		for(float y=-32768+vy; y<32768+vy;y+=4096)
		{
			FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
			ptr->Set(x, z, y, x / 64, -y / 64);
			ptr++;
			ptr->Set(x + 4096, z, y, x / 64 + 64, -y / 64);
			ptr++;
			ptr->Set(x, z, y + 4096, x / 64, -y / 64 - 64);
			ptr++;
			ptr->Set(x + 4096, z, y + 4096, x / 64 + 64, -y / 64 - 64);
			ptr++;
			GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
		}
	}

	float vz= ViewPos.Z;
	float tz=(z-vz);///64.0f;

	// fill the gap between the polygon and the true horizon
	// Since I can't draw into infinity there can always be a
	// small gap

	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
	ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0);
	ptr++;
	ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz);
	ptr++;
	ptr->Set(-32768 + vx, z, 32768 + vy, -512.f, 0);
	ptr++;
	ptr->Set(-32768 + vx, vz, 32768 + vy, -512.f, tz);
	ptr++;
	ptr->Set(32768 + vx, z, 32768 + vy, 512.f, 0);
	ptr++;
	ptr->Set(32768 + vx, vz, 32768 + vy, 512.f, tz);
	ptr++;
	ptr->Set(32768 + vx, z, -32768 + vy, -512.f, 0);
	ptr++;
	ptr->Set(32768 + vx, vz, -32768 + vy, -512.f, tz);
	ptr++;
	ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0);
	ptr++;
	ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz);
	ptr++;
	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);

	gl_RenderState.EnableTextureMatrix(false);
	PortalAll.Unclock();

}