示例#1
0
void FGLRenderer::DrawTexture(FTexture *img, DCanvas::DrawParms &parms)
{
	double xscale = parms.destwidth / parms.texwidth;
	double yscale = parms.destheight / parms.texheight;
	double x = parms.x - parms.left * xscale;
	double y = parms.y - parms.top * yscale;
	double w = parms.destwidth;
	double h = parms.destheight;
	float u1, v1, u2, v2, r, g, b;
	float light = 1.f;

	FMaterial * gltex = FMaterial::ValidateTexture(img);

	const PatchTextureInfo * pti;

	if (parms.colorOverlay)
	{
		// Right now there's only black. Should be implemented properly later
		light = 1.f - APART(parms.colorOverlay)/255.f;
	}

	if (!img->bHasCanvas)
	{
		if (!parms.alphaChannel) 
		{
			int translation = 0;
			if (parms.remap != NULL && !parms.remap->Inactive)
			{
				GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative());
				if (pal) translation = -pal->GetIndex();
			}
			pti = gltex->BindPatch(CM_DEFAULT, translation);
		}
		else 
		{
			// This is an alpha texture
			pti = gltex->BindPatch(CM_SHADE, 0);
		}

		if (!pti) return;

		u1 = pti->GetUL();
		v1 = pti->GetVT();
		u2 = pti->GetUR();
		v2 = pti->GetVB();
	}
	else
	{
		gltex->Bind(CM_DEFAULT, 0, 0);
		u2=1.f;
		v2=-1.f;
		u1 = v1 = 0.f;
		gl_RenderState.SetTextureMode(TM_OPAQUE);
	}
	
	if (parms.flipX)
	{
		float temp = u1;
		u1 = u2;
		u2 = temp;
	}
	

	if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
	{
		x += parms.windowleft * xscale;
		w -= (parms.texwidth - parms.windowright + parms.windowleft) * xscale;

		u1 = float(u1 + parms.windowleft / parms.texwidth);
		u2 = float(u2 - (parms.texwidth - parms.windowright) / parms.texwidth);
	}

	if (parms.style.Flags & STYLEF_ColorIsFixed)
	{
		r = RPART(parms.fillcolor)/255.0f;
		g = GPART(parms.fillcolor)/255.0f;
		b = BPART(parms.fillcolor)/255.0f;
	}
	else
	{
		r = g = b = light;
	}
	
	// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
	int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
	btm = SCREENHEIGHT - btm;

	gl.Enable(GL_SCISSOR_TEST);
	int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2;
	gl.Scissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
	
	gl_SetRenderStyle(parms.style, !parms.masked, false);
	if (img->bHasCanvas)
	{
		gl_RenderState.SetTextureMode(TM_OPAQUE);
	}

	gl.Color4f(r, g, b, FIXED2FLOAT(parms.alpha));
	
	gl_RenderState.EnableAlphaTest(false);
	gl_RenderState.Apply();
	gl.Begin(GL_TRIANGLE_STRIP);
	gl.TexCoord2f(u1, v1);
	glVertex2d(x, y);
	gl.TexCoord2f(u1, v2);
	glVertex2d(x, y + h);
	gl.TexCoord2f(u2, v1);
	glVertex2d(x + w, y);
	gl.TexCoord2f(u2, v2);
	glVertex2d(x + w, y + h);
	gl.End();
	gl_RenderState.EnableAlphaTest(true);
	
	gl.Scissor(0, 0, screen->GetWidth(), screen->GetHeight());
	gl.Disable(GL_SCISSOR_TEST);
	gl_RenderState.SetTextureMode(TM_MODULATE);
	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
示例#2
0
void FGLRenderer::DrawTexture(FTexture *img, DrawParms &parms)
{
	double xscale = parms.destwidth / parms.texwidth;
	double yscale = parms.destheight / parms.texheight;
	double x = parms.x - parms.left * xscale;
	double y = parms.y - parms.top * yscale;
	double w = parms.destwidth;
	double h = parms.destheight;
	float u1, v1, u2, v2;
	int light = 255;

	FMaterial * gltex = FMaterial::ValidateTexture(img, false);

	if (parms.colorOverlay && (parms.colorOverlay & 0xffffff) == 0)
	{
		// Right now there's only black. Should be implemented properly later
		light = 255 - APART(parms.colorOverlay);
		parms.colorOverlay = 0;
	}

	gl_SetRenderStyle(parms.style, !parms.masked, false);
	if (!img->bHasCanvas)
	{
		int translation = 0;
		if (!parms.alphaChannel)
		{
			if (parms.remap != NULL && !parms.remap->Inactive)
			{
				GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative());
				if (pal) translation = -pal->GetIndex();
			}
		}
		gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, -1, !!(parms.style.Flags & STYLEF_RedIsAlpha));

		u1 = gltex->GetUL();
		v1 = gltex->GetVT();
		u2 = gltex->GetUR();
		v2 = gltex->GetVB();

	}
	else
	{
		gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, 0, -1, false);
		u1 = 0.f;
		v1 = 1.f;
		u2 = 1.f;
		v2 = 0.f;
		gl_RenderState.SetTextureMode(TM_OPAQUE);
	}
	
	if (parms.flipX)
	{
		float temp = u1;
		u1 = u2;
		u2 = temp;
	}
	

	if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
	{
		double wi = MIN(parms.windowright, parms.texwidth);
		x += parms.windowleft * xscale;
		w -= (parms.texwidth - wi + parms.windowleft) * xscale;

		u1 = float(u1 + parms.windowleft / parms.texwidth);
		u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
	}

	PalEntry color;
	if (parms.style.Flags & STYLEF_ColorIsFixed)
	{
		color = parms.fillcolor;
	}
	else
	{
		color = PalEntry(light, light, light);
	}
	color.a = (BYTE)(parms.Alpha * 255);

	// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
	int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
	btm = SCREENHEIGHT - btm;

	glEnable(GL_SCISSOR_TEST);
	int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2;
	glScissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
	
	gl_RenderState.SetColor(color);
	gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
	gl_RenderState.Apply();

	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
	ptr->Set(x, y, 0, u1, v1); ptr++;
	ptr->Set(x, y + h, 0, u1, v2); ptr++;
	ptr->Set(x + w, y, 0, u2, v1); ptr++;
	ptr->Set(x + w, y + h, 0, u2, v2); ptr++;
	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);

	if (parms.colorOverlay)
	{
		gl_RenderState.SetTextureMode(TM_MASK);
		gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		gl_RenderState.BlendEquation(GL_FUNC_ADD);
		gl_RenderState.SetColor(PalEntry(parms.colorOverlay));
		gl_RenderState.Apply();

		FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
		ptr->Set(x, y, 0, u1, v1); ptr++;
		ptr->Set(x, y + h, 0, u1, v2); ptr++;
		ptr->Set(x + w, y, 0, u2, v1); ptr++;
		ptr->Set(x + w, y + h, 0, u2, v2); ptr++;
		GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
	}

	glScissor(0, 0, screen->GetWidth(), screen->GetHeight());
	glDisable(GL_SCISSOR_TEST);
	gl_RenderState.SetTextureMode(TM_MODULATE);
	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
示例#3
0
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DrawDecal(DBaseDecal *decal)
{
	line_t * line=seg->linedef;
	side_t * side=seg->sidedef;
	int i;
	fixed_t zpos;
	int light;
	int rel;
	float a;
	bool flipx, flipy, loadAlpha;
	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;


	if (texture->UseType == FTexture::TEX_MiscPatch)
	{
		// We need to create a clone of this texture where we can force the
		// texture filtering offset in.
		if (texture->gl_info.DecalTexture == NULL)
		{
			texture->gl_info.DecalTexture = new FCloneTexture(texture, FTexture::TEX_Decal);
		}
		tex = FMaterial::ValidateTexture(texture->gl_info.DecalTexture);
	}
	else tex = FMaterial::ValidateTexture(texture);


	// 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();
	}
	
	int r = RPART(decal->AlphaColor);
	int g = GPART(decal->AlphaColor);
	int b = BPART(decal->AlphaColor);
	FColormap p = Colormap;
	
	if (glset.nocoloredspritelighting)
	{
		int v = (Colormap.LightColor.r * 77 + Colormap.LightColor.g*143 + Colormap.LightColor.b*35)/255;
		p.LightColor = PalEntry(p.colormap, v, v, v);
	}
	
	float red, green, blue;
	
	if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
	{
		loadAlpha = true;
		p.colormap=CM_SHADE;

		if (glset.lightmode != 8)
		{
			gl_GetLightColor(light, rel, &p, &red, &green, &blue);
		}
		else
		{
			gl_GetLightColor(lightlevel, rellight, &p, &red, &green, &blue);
		}
		
		if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites)
		{
			float result[3];
			fixed_t x, y;
			decal->GetXY(seg->sidedef, x, y);
			gl_GetSpriteLight(NULL, x, y, zpos, sub, Colormap.colormap-CM_DESAT0, result, line, side == line->sidedef[0]? 0:1);
			if (glset.lightmode != 8)
			{
				red = clamp<float>(result[0]+red, 0, 1.0f);
				green = clamp<float>(result[1]+green, 0, 1.0f);
				blue = clamp<float>(result[2]+blue, 0, 1.0f);
			}
			else
			{
				gl_RenderState.SetDynLight(result[0], result[1], result[2]);
			}
		}

		BYTE R = xs_RoundToInt(r * red);
		BYTE G = xs_RoundToInt(g * green);
		BYTE B = xs_RoundToInt(b * blue);

		gl_ModifyColor(R,G,B, Colormap.colormap);

		red = R/255.f;
		green = G/255.f;
		blue = B/255.f;
	}	
	else
	{
		loadAlpha = false;
		
		red = 1.f;
		green = 1.f;
		blue = 1.f;
	}
	
	
	a = FIXED2FLOAT(decal->Alpha);
	
	// now clip the decal to the actual polygon
	float decalwidth = tex->TextureWidth(GLUSE_PATCH)  * FIXED2FLOAT(decal->ScaleX);
	float decalheight= tex->TextureHeight(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY);
	float decallefto = tex->GetLeftOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX);
	float decaltopo  = tex->GetTopOffset(GLUSE_PATCH)  * FIXED2FLOAT(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 / (1<<30) - (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+= FRACUNIT*(flipy? decalheight-decaltopo : decaltopo);

	tex->BindPatch(p.colormap, decal->Translation);

	dv[1].z=dv[2].z = FIXED2FLOAT(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 / FIXED2FLOAT(decal->ScaleX));
	dv[3].u=dv[2].u = tex->GetU(righttex / FIXED2FLOAT(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;
	}
	// fog is set once per wall in the calling function and not per decal!

	if (loadAlpha)
	{
		glColor4f(red, green, blue, a);

		if (glset.lightmode == 8)
		{
			if (gl_fixedcolormap)
				glVertexAttrib1f(VATTR_LIGHTLEVEL, 1.0);
			else
				glVertexAttrib1f(VATTR_LIGHTLEVEL, gl_CalcLightLevel(light, rel, false) / 255.0);
		}
	}
	else
	{
		if (glset.lightmode == 8)
		{
			gl_SetColor(light, rel, &p, a, extralight); // Korshun.
		}
		else
		{
			gl_SetColor(light, rel, &p, a);
		}
	}

	PalEntry fc = gl_RenderState.GetFogColor();
	if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
	{
		gl_RenderState.SetFog(0,-1);
	}


	gl_SetRenderStyle(decal->RenderStyle, false, false);

	// 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_threshold);
	else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);

	gl_RenderState.Apply();
	glBegin(GL_TRIANGLE_FAN);
	for(i=0;i<4;i++)
	{
		glTexCoord2f(dv[i].u,dv[i].v);
		glVertex3f(dv[i].x,dv[i].z,dv[i].y);
	}
	glEnd();
	rendered_decals++;
	gl_RenderState.SetFog(fc,-1);
	gl_RenderState.SetDynLight(0,0,0);
}
示例#4
0
void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
{
	bool brightflash = false;
	unsigned int i;
	int lightlevel=0;
	FColormap cm;
	sector_t * fakesec, fs;
	AActor * playermo=players[consoleplayer].camera;
	player_t * player=playermo->player;
	
	// this is the same as the software renderer
	if (!player ||
		!r_drawplayersprites ||
		!camera->player ||
		(player->cheats & CF_CHASECAM) || 
		(r_deathcamera && camera->health <= 0))
		return;

	float bobx, boby, wx, wy;
	DPSprite *weapon;

	P_BobWeapon(camera->player, &bobx, &boby, r_TicFracF);

	// Interpolate the main weapon layer once so as to be able to add it to other layers.
	if ((weapon = camera->player->FindPSprite(PSP_WEAPON)) != nullptr)
	{
		if (weapon->firstTic)
		{
			wx = weapon->x;
			wy = weapon->y;
		}
		else
		{
			wx = weapon->oldx + (weapon->x - weapon->oldx) * r_TicFracF;
			wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF;
		}
	}
	else
	{
		wx = 0;
		wy = 0;
	}

	if (gl_fixedcolormap) 
	{
		lightlevel=255;
		cm.Clear();
		fakesec = viewsector;
	}
	else
	{
		fakesec    = gl_FakeFlat(viewsector, &fs, false);

		// calculate light level for weapon sprites
		lightlevel = gl_ClampLight(fakesec->lightlevel);

		// calculate colormap for weapon sprites
		if (viewsector->e->XFloor.ffloors.Size() && !glset.nocoloredspritelighting)
		{
			TArray<lightlist_t> & lightlist = viewsector->e->XFloor.lightlist;
			for(i=0;i<lightlist.Size();i++)
			{
				double lightbottom;

				if (i<lightlist.Size()-1) 
				{
					lightbottom=lightlist[i+1].plane.ZatPoint(ViewPos);
				}
				else 
				{
					lightbottom=viewsector->floorplane.ZatPoint(ViewPos);
				}

				if (lightbottom<player->viewz) 
				{
					cm = lightlist[i].extra_colormap;
					lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel);
					break;
				}
			}
		}
		else 
		{
			cm=fakesec->ColorMap;
			if (glset.nocoloredspritelighting) cm.ClearColor();
		}

		lightlevel = gl_CalcLightLevel(lightlevel, getExtraLight(), true);

		if (glset.lightmode == 8)
		{
			// Korshun: the way based on max possible light level for sector like in software renderer.
			float min_L = 36.0 / 31.0 - ((lightlevel / 255.0) * (63.0 / 31.0)); // Lightlevel in range 0-63
			if (min_L < 0)
				min_L = 0;
			else if (min_L > 1.0)
				min_L = 1.0;

			lightlevel = (1.0 - min_L) * 255;
		}
		else
		{
			lightlevel = (2 * lightlevel + 255) / 3;
		}
		lightlevel = gl_CheckSpriteGlow(viewsector, lightlevel, playermo->Pos());

	}
	
	// Korshun: fullbright fog in opengl, render weapon sprites fullbright (but don't cancel out the light color!)
	if (glset.brightfog && ((level.flags&LEVEL_HASFADETABLE) || cm.FadeColor != 0))
	{
		lightlevel = 255;
	}

	PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff;
	ThingColor.a = 255;

	visstyle_t vis;

	vis.RenderStyle=playermo->RenderStyle;
	vis.Alpha=playermo->Alpha;
	vis.colormap = NULL;
	if (playermo->Inventory) 
	{
		playermo->Inventory->AlterWeaponSprite(&vis);
		if (vis.colormap >= SpecialColormaps[0].Colormap && 
			vis.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap && 
			gl_fixedcolormap == CM_DEFAULT)
		{
			// this only happens for Strife's inverted weapon sprite
			vis.RenderStyle.Flags |= STYLEF_InvertSource;
		}
	}

	// Set the render parameters

	int OverrideShader = -1;
	float trans = 0.f;
	if (vis.RenderStyle.BlendOp >= STYLEOP_Fuzz && vis.RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)
	{
		vis.RenderStyle.CheckFuzz();
		if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz)
		{
			if (gl_fuzztype != 0)
			{
				// Todo: implement shader selection here
				vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent];
				OverrideShader = gl_fuzztype + 4;
				trans = 0.99f;	// trans may not be 1 here
			}
			else
			{
				vis.RenderStyle.BlendOp = STYLEOP_Shadow;
			}
		}
	}

	gl_SetRenderStyle(vis.RenderStyle, false, false);

	if (vis.RenderStyle.Flags & STYLEF_TransSoulsAlpha)
	{
		trans = transsouls;
	}
	else if (vis.RenderStyle.Flags & STYLEF_Alpha1)
	{
		trans = 1.f;
	}
	else if (trans == 0.f)
	{
		trans = vis.Alpha;
	}

	// now draw the different layers of the weapon
	gl_RenderState.EnableBrightmap(true);
	gl_RenderState.SetObjectColor(ThingColor);
	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
	gl_RenderState.BlendEquation(GL_FUNC_ADD);

	// hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change
	// light mode here to draw the weapon sprite.
	int oldlightmode = glset.lightmode;
	if (glset.lightmode == 8) glset.lightmode = 2;

	for(DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
	{
		if (psp->GetState() != nullptr) 
		{
			FColormap cmc = cm;
			int ll = lightlevel;
			if (isBright(psp)) 
			{
				if (fakesec == viewsector || in_area != area_below)	
				{
					cmc.LightColor.r=
					cmc.LightColor.g=
					cmc.LightColor.b=0xff;
				}
				else
				{
					// under water areas keep most of their color for fullbright objects
					cmc.LightColor.r = (3 * cmc.LightColor.r + 0xff) / 4;
					cmc.LightColor.g = (3*cmc.LightColor.g + 0xff)/4;
					cmc.LightColor.b = (3*cmc.LightColor.b + 0xff)/4;
				}
				ll = 255;
			}
			// set the lighting parameters
			if (vis.RenderStyle.BlendOp == STYLEOP_Shadow)
			{
				gl_RenderState.SetColor(0.2f, 0.2f, 0.2f, 0.33f, cmc.desaturation);
			}
			else
			{
				if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites)
				{
					gl_SetDynSpriteLight(playermo, NULL);
				}
				gl_SetColor(ll, 0, cmc, trans, true);
			}

			if (psp->firstTic)
			{ // Can't interpolate the first tic.
				psp->firstTic = false;
				psp->oldx = psp->x;
				psp->oldy = psp->y;
			}

			float sx = psp->oldx + (psp->x - psp->oldx) * r_TicFracF;
			float sy = psp->oldy + (psp->y - psp->oldy) * r_TicFracF;

			if (psp->Flags & PSPF_ADDBOB)
			{
				sx += bobx;
				sy += boby;
			}

			if (psp->Flags & PSPF_ADDWEAPON && psp->GetID() != PSP_WEAPON)
			{
				sx += wx;
				sy += wy;
			}


			DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(vis.RenderStyle.Flags & STYLEF_RedIsAlpha));
		}
	}
	gl_RenderState.SetObjectColor(0xffffffff);
	gl_RenderState.SetDynLight(0, 0, 0);
	gl_RenderState.EnableBrightmap(false);
	glset.lightmode = oldlightmode;
}
示例#5
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);
}
//==========================================================================
//
//
//
//==========================================================================
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);
}