Esempio n. 1
0
void GL_RecalcLowerWall(seg_t *seg, sector_t *frontSector, gl_poly_t *poly)
{
   FTexture *tex = TexMan(seg->sidedef->bottomtexture);
   float txScale, tyScale, yOffset, xOffset, dist, texHeight;
   float v1[5], v2[5], v3[5], v4[5];
   float upperHeight, lowerHeight;
   texcoord_t ll, ul, lr, ur;
   sector_t *backSector, ts2;
   vertex_t *vert1, *vert2;
   fixed_t h1, h2;

   if (!poly->initialized) GL_InitPolygon(poly);
   poly->lastUpdate = frameStartMS;
   poly->initialized = true;

   vert1 = seg->v1;
   vert2 = seg->v2;
   dist = seg->length;

   backSector = R_FakeFlat(seg->backsector, &ts2, NULL, NULL, false);

   h1 = (backSector->floorplane.ZatPoint(vert1) - frontSector->floorplane.ZatPoint(vert1));
   h2 = (backSector->floorplane.ZatPoint(vert2) - frontSector->floorplane.ZatPoint(vert2));

   v1[0] = v3[0] = -vert1->x * MAP_SCALE;
   v1[2] = v3[2] = vert1->y * MAP_SCALE;
   v2[0] = v4[0] = -vert2->x * MAP_SCALE;
   v2[2] = v4[2] = vert2->y * MAP_SCALE;

   v1[1] = (float)frontSector->floorplane.ZatPoint(vert1);
   v2[1] = (float)frontSector->floorplane.ZatPoint(vert2);
   v3[1] = v1[1] + h1;
   v4[1] = v2[1] + h2;

   // texscale: 8 = 1.0, 16 = 2.0, 4 = 0.5
   txScale = tex->ScaleX ? tex->ScaleX / 8.f : 1.f;
   tyScale = tex->ScaleY ? tex->ScaleY / 8.f : 1.f;

   xOffset = (seg->offset * txScale) * INV_FRACUNIT;

   ll.x = xOffset / tex->GetWidth();
   ul.x = ll.x;
   lr.x = ll.x + (dist / tex->GetWidth() * txScale);
   ur.x = lr.x;

   ul.y = ur.y = 1.f;
   ll.y = lr.y = 0.f;

   if (tex)
   {
      texHeight = tex->GetHeight() / tyScale;

      lowerHeight = frontSector->floortexz * INV_FRACUNIT;
      upperHeight = backSector->floortexz * INV_FRACUNIT;

      if (seg->linedef->flags & ML_DONTPEGBOTTOM)
      {
         yOffset = (frontSector->ceilingtexz - backSector->floortexz) * INV_FRACUNIT;
      }
      else
      {
         yOffset = 0.f;
      }

      ul.y = ur.y = (yOffset + upperHeight - lowerHeight) / texHeight;
      ll.y = lr.y = yOffset / texHeight;

      // scale the coordinates
      //ul.y *= tyScale;
      //ur.y *= tyScale;
      //ll.y *= tyScale;
      //lr.y *= tyScale;

      // adjust for slopes
      ul.y -= ((v1[1] * INV_FRACUNIT) - lowerHeight) / texHeight;
      ur.y -= ((v2[1] * INV_FRACUNIT) - lowerHeight) / texHeight;
      ll.y += (upperHeight - (v3[1] * INV_FRACUNIT)) / texHeight;
      lr.y += (upperHeight - (v4[1] * INV_FRACUNIT)) / texHeight;
   }

   v1[1] *= MAP_SCALE;
   v2[1] *= MAP_SCALE;
   v3[1] *= MAP_SCALE;
   v4[1] *= MAP_SCALE;

   v1[3] = ul.x; v1[4] = ul.y;
   v2[3] = ur.x; v2[4] = ur.y;
   v3[3] = ll.x; v3[4] = ll.y;
   v4[3] = lr.x; v4[4] = lr.y;

   memcpy(poly->vertices + (0 * 3), v3, sizeof(float) * 3);
   memcpy(poly->vertices + (1 * 3), v1, sizeof(float) * 3);
   memcpy(poly->vertices + (2 * 3), v2, sizeof(float) * 3);
   memcpy(poly->vertices + (3 * 3), v4, sizeof(float) * 3);

   memcpy(poly->texCoords + (0 * 2), v3 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (1 * 2), v1 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (2 * 2), v2 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (3 * 2), v4 + 3, sizeof(float) * 2);
}
Esempio n. 2
0
void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
{
	if (RenderPolySprite::IsThingCulled(thing))
		return;

	const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
	DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac);
	pos.Z += thing->GetBobOffset(viewpoint.TicFrac);

	bool flipTextureX = false;
	FTexture *tex = RenderPolySprite::GetSpriteTexture(thing, flipTextureX);
	if (tex == nullptr || tex->UseType == FTexture::TEX_Null)
		return;

	DVector2 spriteScale = thing->Scale;
	double thingxscalemul = spriteScale.X / tex->Scale.X;
	double thingyscalemul = spriteScale.Y / tex->Scale.Y;
	double spriteHeight = thingyscalemul * tex->GetHeight();

	DAngle ang = thing->Angles.Yaw + 90;
	double angcos = ang.Cos();
	double angsin = ang.Sin();

	// Determine left and right edges of sprite. The sprite's angle is its normal,
	// so the edges are 90 degrees each side of it.
	double x2 = tex->GetScaledWidth() * spriteScale.X;
	double x1 = tex->GetScaledLeftOffset() * spriteScale.X;
	DVector2 left, right;
	left.X = pos.X - x1 * angcos;
	left.Y = pos.Y - x1 * angsin;
	right.X = left.X + x2 * angcos;
	right.Y = left.Y + x2 * angsin;

	//int scaled_to = tex->GetScaledTopOffset();
	//int scaled_bo = scaled_to - tex->GetScaledHeight();
	//gzt = pos.Z + scale.Y * scaled_to;
	//gzb = pos.Z + scale.Y * scaled_bo;

	DVector2 points[2] = { left, right };

	TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(4);

	bool foggy = false;
	int actualextralight = foggy ? 0 : viewpoint.extralight << 4;

	std::pair<float, float> offsets[4] =
	{
		{ 0.0f,  1.0f },
		{ 1.0f,  1.0f },
		{ 1.0f,  0.0f },
		{ 0.0f,  0.0f },
	};

	for (int i = 0; i < 4; i++)
	{
		auto &p = (i == 0 || i == 3) ? points[0] : points[1];

		vertices[i].x = (float)p.X;
		vertices[i].y = (float)p.Y;
		vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second);
		vertices[i].w = 1.0f;
		vertices[i].u = (float)(offsets[i].first * tex->Scale.X);
		vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y);
		if (flipTextureX)
			vertices[i].u = 1.0f - vertices[i].u;
	}

	bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
	int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight;

	PolyDrawArgs args;
	args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite);
	args.SetTransform(&worldToClip);
	args.SetFaceCullCCW(true);
	args.SetStencilTestValue(stencilValue);
	args.SetTexture(tex);
	args.SetClipPlane(clipPlane);
	args.SetSubsectorDepthTest(true);
	args.SetWriteSubsectorDepth(false);
	args.SetWriteStencil(false);
	args.SetStyle(TriBlendMode::TextureMasked);
	args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
}
Esempio n. 3
0
void GL_RecalcMidWall(seg_t *seg, sector_t *frontSector, gl_poly_t *poly)
{
   float height1, height2, v1[5], v2[5], v3[5], v4[5], txScale, tyScale;
   float yOffset1, yOffset2, yOffset, xOffset;
   float upperHeight, lowerHeight;
   float tmpOffset = seg->sidedef->rowoffset * INV_FRACUNIT;
   long offset = 0;
   int texHeight;
   FTexture *tex = NULL;
   texcoord_t ll, ul, lr, ur;
   sector_t *backSector, ts2;
   vertex_t *vert1, *vert2;

   if (!poly->initialized) GL_InitPolygon(poly);
   poly->lastUpdate = frameStartMS;
   poly->initialized = true;

   tex = TexMan(seg->sidedef->midtexture);

   vert1 = seg->v1;
   vert2 = seg->v2;

   backSector = R_FakeFlat(seg->backsector, &ts2, NULL, NULL, false);

   v1[0] = -vert1->x * MAP_SCALE;
   v1[2] = vert1->y * MAP_SCALE;
   v2[0] = -vert2->x * MAP_SCALE;
   v2[2] = vert2->y * MAP_SCALE;
   v1[1] = (float)frontSector->floorplane.ZatPoint(seg->v1);
   v2[1] = (float)frontSector->floorplane.ZatPoint(seg->v2);

   if ((seg->linedef->special == Line_Mirror && seg->backsector == NULL) || tex == NULL)
   {
      if (backSector)
      {
         height1 = (float)backSector->ceilingplane.ZatPoint(vert1);
         height2 = (float)backSector->ceilingplane.ZatPoint(vert2);
      }
      else
      {
         height1 = (float)frontSector->ceilingplane.ZatPoint(vert1);
         height2 = (float)frontSector->ceilingplane.ZatPoint(vert2);
      }
   }
   else
   {
      //yOffset = seg->sidedef->rowoffset * INV_FRACUNIT;
      yOffset = 0.f;
      tmpOffset = 0.f;
      offset = seg->sidedef->rowoffset;
      yOffset1 = yOffset2 = yOffset;

      // texscale: 8 = 1.0, 16 = 2.0, 4 = 0.5
      txScale = tex->ScaleX ? tex->ScaleX / 8.f : 1.f;
      tyScale = tex->ScaleY ? tex->ScaleY / 8.f : 1.f;

      xOffset = (seg->offset * txScale) * INV_FRACUNIT;
   
      texHeight = (int)(tex->GetHeight() / tyScale);
      textureList.GetTexture(seg->sidedef->midtexture, true);

      ll.x = xOffset / tex->GetWidth();
      ul.x = ll.x;
      lr.x = ll.x + (seg->length / tex->GetWidth() * txScale);
      ur.x = lr.x;

      if (backSector)
      {
         height1 = (float)MIN(frontSector->ceilingplane.ZatPoint(vert1), backSector->ceilingplane.ZatPoint(vert1));
         height2 = (float)MIN(frontSector->ceilingplane.ZatPoint(vert2), backSector->ceilingplane.ZatPoint(vert2));
      }
      else
      {
         height1 = (float)frontSector->ceilingplane.ZatPoint(vert1);
         height2 = (float)frontSector->ceilingplane.ZatPoint(vert2);
      }

      if (backSector && (textureList.IsTransparent() || seg->linedef->flags & ML_TWOSIDED))
      {
         int h = texHeight;

#if 0
         if (seg->linedef->flags & ML_DONTPEGBOTTOM)
         {
            if (backSector)
            {
               v1[1] = MAX (frontSector->floortexz, backSector->floortexz) + offset;
               v2[1] = MAX (frontSector->floortexz, backSector->floortexz) + offset;
            }
            else
            {
               v1[1] = frontSector->floortexz + offset;
               v2[1] = frontSector->floortexz + offset;
            }
         }
         else
         {
            if (backSector)
            {
               v1[1] = MIN (frontSector->ceilingtexz, backSector->ceilingtexz) + offset - (h << FRACBITS);
               v2[1] = MIN (frontSector->ceilingtexz, backSector->ceilingtexz) + offset - (h << FRACBITS);
            }
            else
            {
               v1[1] = frontSector->ceilingtexz + offset - (h << FRACBITS);
               v2[1] = frontSector->ceilingtexz + offset - (h << FRACBITS);
            }
         }

         height1 = (h << FRACBITS) + v1[1];
         height2 = (h << FRACBITS) + v2[1];
#else
         float rbceil = (float)backSector->ceilingtexz,
				rbfloor = (float)backSector->floortexz,
				rfceil = (float)frontSector->ceilingtexz,
				rffloor = (float)frontSector->floortexz;
			float gaptop, gapbottom;

         yOffset = (float)seg->sidedef->rowoffset;
         height1 = gaptop = MIN(rbceil, rfceil);
         v1[1] = gapbottom = MAX(rbfloor, rffloor);

         if (seg->linedef->flags & ML_DONTPEGBOTTOM)
         {
            v1[1] += yOffset;
            height1 = v1[1] + (tex->GetHeight() * FRACUNIT);
         }
         else
         {
            height1 += yOffset;
            v1[1] = height1 - (tex->GetHeight() * FRACUNIT);
         }

         height2 = height1;
         v2[1] = v1[1];
#endif
      }
   }

   // make sure to clip the geometry to the back sector...
   if (backSector)
   {
      if (seg->sidedef->bottomtexture)
      {
         v1[1] = MAX(v1[1], backSector->floorplane.ZatPoint(seg->v1));
         v2[1] = MAX(v2[1], backSector->floorplane.ZatPoint(seg->v2));
      }
      if (seg->sidedef->toptexture)
      {
         height1 = MIN(height1, backSector->ceilingplane.ZatPoint(seg->v1));
         height2 = MIN(height2, backSector->ceilingplane.ZatPoint(seg->v2));
      }
   }

   memcpy(v3, v1, sizeof(float) * 3);
   memcpy(v4, v2, sizeof(float) * 3);

   ul.y = ur.y = 1.f;
   ll.y = lr.y = 0.f;

   if (tex)
   {
      yOffset = 0.f;

      // code borrowed from Legacy ;)
      // damn pegged/unpegged/two sided lines!
      if (backSector)
      {
         float worldHigh = backSector->ceilingtexz * INV_FRACUNIT;
         float worldLow = backSector->floortexz * INV_FRACUNIT;
         float polyBottom, polyTop;

         lowerHeight = frontSector->floortexz * INV_FRACUNIT;
         upperHeight = frontSector->ceilingtexz * INV_FRACUNIT;

         float openTop = upperHeight < worldHigh ? upperHeight : worldHigh;
         float openBottom = lowerHeight > worldLow ? lowerHeight : worldLow;

         if (seg->linedef->flags & ML_DONTPEGBOTTOM)
         {
            polyBottom = openBottom + seg->sidedef->rowoffset * INV_FRACUNIT;
            polyTop = polyBottom + texHeight;

            upperHeight = MIN(openTop, polyTop);
            lowerHeight = MAX(openBottom, polyBottom);

            yOffset = lowerHeight + texHeight - upperHeight + polyBottom - lowerHeight;
         }
         else
         {
            polyTop = openTop + seg->sidedef->rowoffset * INV_FRACUNIT;
            polyBottom = polyTop - texHeight;

            yOffset = polyTop - upperHeight;
         }
      }
      else
      {
         lowerHeight = frontSector->floortexz * INV_FRACUNIT;
         upperHeight = frontSector->ceilingtexz * INV_FRACUNIT;
         yOffset = 0.f;

         if (seg->linedef->flags & ML_DONTPEGBOTTOM)
         {
            yOffset += lowerHeight + texHeight - upperHeight;
         }
      }

      ll.y = lr.y = yOffset / texHeight;
      ul.y = ur.y = ll.y + ((upperHeight - lowerHeight) / texHeight);

      // scale the coordinates
      //ul.y *= tyScale;
      //ur.y *= tyScale;
      //ll.y *= tyScale;
      //lr.y *= tyScale;

      // clip to slopes
      ul.y -= ((v1[1] * INV_FRACUNIT) - lowerHeight) / texHeight;
      ur.y -= ((v2[1] * INV_FRACUNIT) - lowerHeight) / texHeight;
      ll.y += (upperHeight - (height1 * INV_FRACUNIT)) / texHeight;
      lr.y += (upperHeight - (height2 * INV_FRACUNIT)) / texHeight;
   }

   v1[1] *= MAP_SCALE;
   v2[1] *= MAP_SCALE;
   v3[1] = height1 * MAP_SCALE;
   v4[1] = height2 * MAP_SCALE;

   v1[3] = ul.x; v1[4] = ul.y;
   v2[3] = ur.x; v2[4] = ur.y;
   v3[3] = ll.x; v3[4] = ll.y;
   v4[3] = lr.x; v4[4] = lr.y;

   memcpy(poly->vertices + (0 * 3), v3, sizeof(float) * 3);
   memcpy(poly->vertices + (1 * 3), v1, sizeof(float) * 3);
   memcpy(poly->vertices + (2 * 3), v2, sizeof(float) * 3);
   memcpy(poly->vertices + (3 * 3), v4, sizeof(float) * 3);

   memcpy(poly->texCoords + (0 * 2), v3 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (1 * 2), v1 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (2 * 2), v2 + 3, sizeof(float) * 2);
   memcpy(poly->texCoords + (3 * 2), v4 + 3, sizeof(float) * 2);
}
Esempio n. 4
0
void GL_DrawSky()
{
   float angle;
   FTexture *tex;
   bool drawBoth = false;

   int sky1tex, sky2tex;
   int s1p, s2p;

   drawBoth = !((level.flags & LEVEL_SWAPSKIES) || (sky2texture == sky1texture));

	if ((level.flags & LEVEL_SWAPSKIES) || (sky2texture == sky1texture))
	{
		sky1tex = sky2texture;
      s1p = sky2pos;
		sky2tex = sky1texture;
      s2p = sky1pos;
	}
	else
	{
		sky1tex = sky1texture;
      s1p = sky1pos;
		sky2tex = sky2texture;
      s2p = sky2pos;
	}

   glDepthMask(GL_FALSE);
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_FOG);
   glDisable(GL_ALPHA_TEST);

   glPushMatrix();

   angle = s2p * 1.f / (FRACUNIT * 2.f);
   glRotatef(-angle, 0.f, 1.f, 0.f);

   textureList.BindTexture(sky2tex, true);
   tex = TexMan(sky2tex);
   texw = tex->GetWidth();
   texh = tex->GetHeight();
   tx = ty = 1.f;
   yMult = 1.f;

   GL_RenderSkyHemisphere(SKYHEMI_UPPER);
   GL_RenderSkyHemisphere(SKYHEMI_LOWER);

   if (drawBoth)
   {
      angle = (s1p * 1.f / (FRACUNIT * 2.f)) - angle;
      glRotatef(-angle, 0.f, 1.f, 0.f);
      tex = TexMan(sky1tex);
      textureList.BindTexture(sky1tex, true);
      texw = tex->GetWidth();
      texh = tex->GetHeight();
      if (level.flags & LEVEL_DOUBLESKY && texh <= 128)
      {
         yMult = 2.f;
      }
      tx = ty = 1.f;
      GL_RenderSkyHemisphere(SKYHEMI_UPPER);
      GL_RenderSkyHemisphere(SKYHEMI_LOWER);
   }

   glPopMatrix();

   glEnable(GL_DEPTH_TEST);
   glEnable(GL_ALPHA_TEST);
   glFogf(GL_FOG_MODE, GL_EXP);
   glDepthMask(GL_TRUE);
   if (gl_depthfog && !Player->fixedcolormap)
   {
      glEnable(GL_FOG);
   }
}
Esempio n. 5
0
	void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass)
	{
		DVector2 decal_left, decal_right, decal_pos;
		int x1, x2;
		double yscale;
		uint8_t flipx;
		double zpos;
		int needrepeat = 0;
		sector_t *back;
		bool calclighting;
		bool rereadcolormap;
		FDynamicColormap *usecolormap;
		float light = 0;
		const short *mfloorclip;
		const short *mceilingclip;

		if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid())
			return;

		// Determine actor z
		zpos = decal->Z;
		back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector;

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

		switch (decal->RenderFlags & RF_RELMASK)
		{
		default:
			zpos = decal->Z;
			break;
		case RF_RELUPPER:
			if (curline->linedef->flags & ML_DONTPEGTOP)
			{
				zpos = decal->Z + front->GetPlaneTexZ(sector_t::ceiling);
			}
			else
			{
				zpos = decal->Z + back->GetPlaneTexZ(sector_t::ceiling);
			}
			break;
		case RF_RELLOWER:
			if (curline->linedef->flags & ML_DONTPEGBOTTOM)
			{
				zpos = decal->Z + front->GetPlaneTexZ(sector_t::ceiling);
			}
			else
			{
				zpos = decal->Z + back->GetPlaneTexZ(sector_t::floor);
			}
			break;
		case RF_RELMID:
			if (curline->linedef->flags & ML_DONTPEGBOTTOM)
			{
				zpos = decal->Z + front->GetPlaneTexZ(sector_t::floor);
			}
			else
			{
				zpos = decal->Z + front->GetPlaneTexZ(sector_t::ceiling);
			}
		}

		FTexture *WallSpriteTile = TexMan(decal->PicNum, true);
		flipx = (uint8_t)(decal->RenderFlags & RF_XFLIP);

		if (WallSpriteTile == NULL || WallSpriteTile->UseType == ETextureType::Null)
		{
			return;
		}

		// Determine left and right edges of sprite. Since this sprite is bound
		// to a wall, we use the wall's angle instead of the decal's. This is
		// pretty much the same as what R_AddLine() does.

		double edge_right = WallSpriteTile->GetWidth();
		double edge_left = WallSpriteTile->GetLeftOffset(0);	// decals should not use renderer-specific offsets.
		edge_right = (edge_right - edge_left) * decal->ScaleX;
		edge_left *= decal->ScaleX;

		double dcx, dcy;
		decal->GetXY(wall, dcx, dcy);
		decal_pos = { dcx, dcy };

		DVector2 angvec = (curline->v2->fPos() - curline->v1->fPos()).Unit();
		float maskedScaleY;

		decal_left = decal_pos - edge_left * angvec - thread->Viewport->viewpoint.Pos;
		decal_right = decal_pos + edge_right * angvec - thread->Viewport->viewpoint.Pos;

		CameraLight *cameraLight;
		double texturemid;

		FWallCoords WallC;
		if (WallC.Init(thread, decal_left, decal_right, TOO_CLOSE_Z))
			return;

		x1 = WallC.sx1;
		x2 = WallC.sx2;

		if (x1 >= clipper->x2 || x2 <= clipper->x1)
			return;

		FWallTmapVals WallT;
		WallT.InitFromWallCoords(thread, &WallC);

		if (drawsegPass)
		{
			uint32_t clipMode = decal->RenderFlags & RF_CLIPMASK;
			if (clipMode != RF_CLIPMID && clipMode != RF_CLIPFULL)
				return;

			// Clip decal to stay within the draw segment wall
			mceilingclip = walltop;
			mfloorclip = wallbottom;

			// Rumor has it that if RT_CLIPMASK is specified then the decal should be clipped according
			// to the full drawsegment visibility, as implemented in the remarked section below.
			//
			// This is problematic because not all 3d floors may have been drawn yet at this point. The
			// code below might work ok for cases where there is only one 3d floor.

			/*if (clipMode == RF_CLIPFULL)
			{
				mceilingclip = clipper->sprtopclip - clipper->x1;
				mfloorclip = clipper->sprbottomclip - clipper->x1;
			}*/
		}
		else
		{
			// Get the top and bottom clipping arrays
			switch (decal->RenderFlags & RF_CLIPMASK)
			{
			default:
				// keep GCC quiet.
				return;

			case RF_CLIPFULL:
				if (curline->backsector == NULL)
				{
					mceilingclip = walltop;
					mfloorclip = wallbottom;
				}
				else
				{
					mceilingclip = walltop;
					mfloorclip = thread->OpaquePass->ceilingclip;
					needrepeat = 1;
				}
				break;

			case RF_CLIPUPPER:
				mceilingclip = walltop;
				mfloorclip = thread->OpaquePass->ceilingclip;
				break;

			case RF_CLIPMID:
				return;

			case RF_CLIPLOWER:
				mceilingclip = thread->OpaquePass->floorclip;
				mfloorclip = wallbottom;
				break;
			}
		}

		yscale = decal->ScaleY;
		texturemid = WallSpriteTile->GetTopOffset(0) + (zpos - thread->Viewport->viewpoint.Pos.Z) / yscale;

		// Clip sprite to drawseg
		x1 = MAX<int>(clipper->x1, x1);
		x2 = MIN<int>(clipper->x2, x2);
		if (x1 >= x2)
		{
			return;
		}

		ProjectedWallTexcoords walltexcoords;
		walltexcoords.Project(thread->Viewport.get(), WallSpriteTile->GetWidth(), x1, x2, WallT);

		if (flipx)
		{
			int i;
			int right = (WallSpriteTile->GetWidth() << FRACBITS) - 1;

			for (i = x1; i < x2; i++)
			{
				walltexcoords.UPos[i] = right - walltexcoords.UPos[i];
			}
		}

		// Prepare lighting
		calclighting = false;
		usecolormap = basecolormap;
		rereadcolormap = true;

		// Decals that are added to the scene must fade to black.
		if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0)
		{
			usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate);
			rereadcolormap = false;
		}

		light = lightleft + (x1 - savecoord.sx1) * lightstep;

		cameraLight = CameraLight::Instance();

		// Draw it
		bool sprflipvert;
		if (decal->RenderFlags & RF_YFLIP)
		{
			sprflipvert = true;
			yscale = -yscale;
			texturemid -= WallSpriteTile->GetHeight();
		}
		else
		{
			sprflipvert = false;
		}

		maskedScaleY = float(1 / yscale);
		do
		{
			int x = x1;

			SpriteDrawerArgs drawerargs;

			if (cameraLight->FixedLightLevel() >= 0)
				drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, cameraLight->FixedLightLevelShade());
			else if (cameraLight->FixedColormap() != NULL)
				drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0);
			else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
				drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0);
			else
				calclighting = true;

			bool visible = drawerargs.SetStyle(thread->Viewport.get(), decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor, basecolormap);

			// R_SetPatchStyle can modify basecolormap.
			if (rereadcolormap)
			{
				usecolormap = basecolormap;
			}

			if (visible)
			{
				thread->PrepareTexture(WallSpriteTile, decal->RenderStyle);
				while (x < x2)
				{
					if (calclighting)
					{ // calculate lighting
						drawerargs.SetLight(usecolormap, light, wallshade);
					}
					DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
					light += lightstep;
					x++;
				}
			}

			// If this sprite is RF_CLIPFULL on a two-sided line, needrepeat will
			// be set 1 if we need to draw on the lower wall. In all other cases,
			// needrepeat will be 0, and the while will fail.
			mceilingclip = thread->OpaquePass->floorclip;
			mfloorclip = wallbottom;
		} while (needrepeat--);
	}
Esempio n. 6
0
void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2)
{
	if (r_modelscene)
	{
		const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
		int spritenum = thing->sprite;
		bool isPicnumOverride = thing->picnum.isValid();
		FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
		if (modelframe && (thing->Pos() - viewpoint.Pos).LengthSquared() < model_distance_cull)
		{
			DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac);
			PolyRenderModel(thread, PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToClip, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing);
			return;
		}
	}

	DVector2 line[2];
	if (!GetLine(thing, line[0], line[1]))
		return;
	
	const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
	DVector3 thingpos = thing->InterpolatedPosition(viewpoint.TicFrac);

	double posZ = thingpos.Z;

	uint32_t spritetype = (thing->renderflags & RF_SPRITETYPEMASK);

	if (spritetype == RF_FACESPRITE)
		posZ -= thing->Floorclip;

	if (thing->flags2 & MF2_FLOATBOB)
		posZ += thing->GetBobOffset(viewpoint.TicFrac);

	bool flipTextureX = false;
	FTexture *tex = GetSpriteTexture(thing, flipTextureX);
	if (tex == nullptr || tex->UseType == ETextureType::Null)
		return;

	double thingyscalemul = thing->Scale.Y / tex->Scale.Y;
	double spriteHeight = thingyscalemul * tex->GetHeight();

	posZ -= (tex->GetHeight() - tex->GetTopOffsetPo()) * thingyscalemul;
	posZ = PerformSpriteClipAdjustment(thing, thingpos, spriteHeight, posZ);

	//double depth = 1.0;
	//visstyle_t visstyle = GetSpriteVisStyle(thing, depth);
	// Rumor has it that AlterWeaponSprite needs to be called with visstyle passed in somewhere around here..
	//R_SetColorMapLight(visstyle.BaseColormap, 0, visstyle.ColormapNum << FRACBITS);

	TriVertex *vertices = thread->FrameMemory->AllocMemory<TriVertex>(4);

	bool foggy = false;
	int actualextralight = foggy ? 0 : viewpoint.extralight << 4;

	std::pair<float, float> offsets[4] =
	{
		{ t1,  1.0f },
		{ t2,  1.0f },
		{ t2,  0.0f },
		{ t1,  0.0f },
	};

	DVector2 points[2] =
	{
		line[0] * (1.0 - t1) + line[1] * t1,
		line[0] * (1.0 - t2) + line[1] * t2
	};

	for (int i = 0; i < 4; i++)
	{
		auto &p = (i == 0 || i == 3) ? points[0] : points[1];

		vertices[i].x = (float)p.X;
		vertices[i].y = (float)p.Y;
		vertices[i].z = (float)(posZ + spriteHeight * offsets[i].second);
		vertices[i].w = 1.0f;
		vertices[i].u = (float)(offsets[i].first * tex->Scale.X);
		vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y);
		if (flipTextureX)
			vertices[i].u = 1.0f - vertices[i].u;
	}

	bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
	int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight;

	PolyDrawArgs args;
	SetDynlight(thing, args);
	args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
	args.SetStencilTestValue(stencilValue);
	if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency)
		args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite);
	else
		args.SetStyle(thing->RenderStyle, thing->Alpha, thing->fillcolor, thing->Translation, tex, fullbrightSprite);
	args.SetDepthTest(true);
	args.SetWriteDepth(false);
	args.SetWriteStencil(false);
	PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan);
}
void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth)
{
	if (RenderPolySprite::IsThingCulled(thing))
		return;

	DVector3 pos = thing->InterpolatedPosition(r_TicFracF);
	pos.Z += thing->GetBobOffset(r_TicFracF);

	bool flipTextureX = false;
	FTexture *tex = RenderPolySprite::GetSpriteTexture(thing, flipTextureX);
	if (tex == nullptr)
		return;

	DVector2 spriteScale = thing->Scale;
	double thingxscalemul = spriteScale.X / tex->Scale.X;
	double thingyscalemul = spriteScale.Y / tex->Scale.Y;
	double spriteHeight = thingyscalemul * tex->GetHeight();

	DAngle ang = thing->Angles.Yaw + 90;
	double angcos = ang.Cos();
	double angsin = ang.Sin();

	// Determine left and right edges of sprite. The sprite's angle is its normal,
	// so the edges are 90 degrees each side of it.
	double x2 = tex->GetScaledWidth() * spriteScale.X;
	double x1 = tex->GetScaledLeftOffset() * spriteScale.X;
	DVector2 left, right;
	left.X = pos.X - x1 * angcos;
	left.Y = pos.Y - x1 * angsin;
	right.X = left.X + x2 * angcos;
	right.Y = right.Y + x2 * angsin;

	//int scaled_to = tex->GetScaledTopOffset();
	//int scaled_bo = scaled_to - tex->GetScaledHeight();
	//gzt = pos.Z + scale.Y * scaled_to;
	//gzb = pos.Z + scale.Y * scaled_bo;

	DVector2 points[2] = { left, right };

	TriVertex *vertices = PolyVertexBuffer::GetVertices(4);
	if (!vertices)
		return;

	bool foggy = false;
	int actualextralight = foggy ? 0 : extralight << 4;

	std::pair<float, float> offsets[4] =
	{
		{ 0.0f,  1.0f },
		{ 1.0f,  1.0f },
		{ 1.0f,  0.0f },
		{ 0.0f,  0.0f },
	};

	for (int i = 0; i < 4; i++)
	{
		auto &p = (i == 0 || i == 3) ? points[0] : points[1];

		vertices[i].x = (float)p.X;
		vertices[i].y = (float)p.Y;
		vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second);
		vertices[i].w = 1.0f;
		vertices[i].varying[0] = (float)(offsets[i].first * tex->Scale.X);
		vertices[i].varying[1] = (float)((1.0f - offsets[i].second) * tex->Scale.Y);
		if (flipTextureX)
			vertices[i].varying[0] = 1.0f - vertices[i].varying[0];
	}

	bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));

	TriUniforms uniforms;
	if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap)
	{
		uniforms.light = 256;
		uniforms.flags = TriUniforms::fixed_light;
	}
	else
	{
		uniforms.light = (uint32_t)((thing->Sector->lightlevel + actualextralight) / 255.0f * 256.0f);
		uniforms.flags = 0;
	}
	uniforms.subsectorDepth = subsectorDepth;

	PolyDrawArgs args;
	args.uniforms = uniforms;
	args.objectToClip = &worldToClip;
	args.vinput = vertices;
	args.vcount = 4;
	args.mode = TriangleDrawMode::Fan;
	args.ccw = true;
	args.stenciltestvalue = 0;
	args.stencilwritevalue = 1;
	args.SetTexture(tex);
	args.SetColormap(sub->sector->ColorMap);
	PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::AlphaBlend);
}