Esempio n. 1
0
void gl_SetDynModelLight(AActor *self, bool hudmodel)
{
	// Legacy and deferred render paths gets the old flat model light
	if (gl.lightmethod != LM_DIRECT)
	{
		gl_SetDynSpriteLight(self, nullptr);
		return;
	}

	modellightdata.Clear();

	if (self)
	{
		static std::vector<ADynamicLight*> addedLights; // static so that we build up a reserve (memory allocations stop)

		addedLights.clear();

		float x = self->X();
		float y = self->Y();
		float z = self->Center();
		float radiusSquared = self->renderradius * self->renderradius;

		BSPWalkCircle(x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor
		{
			FLightNode * node = subsector->lighthead;
			while (node) // check all lights touching a subsector
			{
				ADynamicLight *light = node->lightsource;
				if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS))
				{
					int group = subsector->sector->PortalGroup;
					DVector3 pos = light->PosRelative(group);
					float radius = light->GetRadius();
					double dx = pos.X - x;
					double dy = pos.Y - y;
					double dz = pos.Z - z;
					double distSquared = dx * dx + dy * dy + dz * dz;
					if (distSquared < radiusSquared + radius * radius) // Light and actor touches
					{
						if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
						{
							gl_AddLightToList(group, light, modellightdata, hudmodel);
							addedLights.push_back(light);
						}
					}
				}
				node = node->nextLight;
			}
		});
	}

	gl_RenderState.SetDynLight(0, 0, 0);
	modellightindex = GLRenderer->mLights->UploadLights(modellightdata);
}
Esempio n. 2
0
void gl_DeleteAllAttachedLights()
{
	TThinkerIterator<AActor> it;
	AActor * a;
	ADynamicLight * l;

	while ((a=it.Next())) 
	{
		a->dynamiclights.Clear();
	}

	TThinkerIterator<ADynamicLight> it2;

	l=it2.Next();
	while (l) 
	{
		ADynamicLight * ll = it2.Next();
		if (l->owned) l->Destroy();
		l=ll;
	}


}
Esempio n. 3
0
void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec)
{
	ADynamicLight *light;
	float frac, lr, lg, lb;
	float radius;
	float out[3] = { 0.0f, 0.0f, 0.0f };
	
	// Go through both light lists
	FLightNode * node = subsec->lighthead;
	while (node)
	{
		light=node->lightsource;
		if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS))
		{
			float dist;

			// This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not.
			// This will do the calculations explicitly rather than calling one of AActor's utility functions.
			if (Displacements.size > 0)
			{
				int fromgroup = light->Sector->PortalGroup;
				int togroup = subsec->sector->PortalGroup;
				if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct;

				DVector2 offset = Displacements.getOffset(fromgroup, togroup);
				dist = FVector3(x - light->X() - offset.X, y - light->Y() - offset.Y, z - light->Z()).LengthSquared();
			}
			else
			{
			direct:
				dist = FVector3(x - light->X(), y - light->Y(), z - light->Z()).LengthSquared();
			}

			radius = light->GetRadius();

			if (dist < radius * radius)
			{
				dist = sqrtf(dist);	// only calculate the square root if we really need it.

				frac = 1.0f - (dist / radius);

				if (frac > 0 && GLRenderer->mShadowMap.ShadowTest(light, { x, y, z }))
				{
					lr = light->GetRed() / 255.0f;
					lg = light->GetGreen() / 255.0f;
					lb = light->GetBlue() / 255.0f;
					if (light->IsSubtractive())
					{
						float bright = FVector3(lr, lg, lb).Length();
						FVector3 lightColor(lr, lg, lb);
						lr = (bright - lr) * -1;
						lg = (bright - lg) * -1;
						lb = (bright - lb) * -1;
					}

					out[0] += lr * frac;
					out[1] += lg * frac;
					out[2] += lb * frac;
				}
			}
		}
		node = node->nextLight;
	}
	gl_RenderState.SetDynLight(out[0], out[1], out[2]);
	modellightindex = -1;
}
Esempio n. 4
0
bool gl_GetSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsector_t * subsec, int desaturation, float * out, line_t *line, int side)
{
	ADynamicLight *light;
	float frac, lr, lg, lb;
	float radius;
	bool changed = false;
	
	out[0]=out[1]=out[2]=0;

	for(int j=0;j<2;j++)
	{
		// Go through both light lists
		FLightNode * node = subsec->lighthead[j];
		while (node)
		{
			light=node->lightsource;
			//if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
			{
				if (!(light->flags2&MF2_DORMANT) &&
					(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
				{
					float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
					radius = light->GetRadius() * gl_lights_size;

					if (dist < radius)
					{
						frac = 1.0f - (dist / radius);

						if (frac > 0)
						{
							if (line != NULL)
							{
								if (P_PointOnLineSide(light->x, light->y, line) != side)
								{
									node = node->nextLight;
									continue;
								}
							}
							lr = light->GetRed() / 255.0f * gl_lights_intensity;
							lg = light->GetGreen() / 255.0f * gl_lights_intensity;
							lb = light->GetBlue() / 255.0f * gl_lights_intensity;
							if (light->IsSubtractive())
							{
								float bright = FVector3(lr, lg, lb).Length();
								FVector3 lightColor(lr, lg, lb);
								lr = (bright - lr) * -1;
								lg = (bright - lg) * -1;
								lb = (bright - lb) * -1;
							}

							out[0] += lr * frac;
							out[1] += lg * frac;
							out[2] += lb * frac;
							changed = true;
						}
					}
				}
			}
			node = node->nextLight;
		}
	}

	// Desaturate dynamic lighting if applicable
	if (desaturation>0 && desaturation<=CM_DESAT31)
	{
		float gray=(out[0]*77 + out[1]*143 + out[2]*37)/257;

		out[0]= (out[0]*(31-desaturation)+ gray*desaturation)/31;
		out[1]= (out[1]*(31-desaturation)+ gray*desaturation)/31;
		out[2]= (out[2]*(31-desaturation)+ gray*desaturation)/31;
	}
	return changed;
}
Esempio n. 5
0
void PolyModelRenderer::AddLights(AActor *actor)
{
	if (r_dynlights && actor)
	{
		auto &addedLights = Thread->AddedLightsArray;

		addedLights.Clear();

		float x = (float)actor->X();
		float y = (float)actor->Y();
		float z = (float)actor->Center();
		float radiusSquared = (float)(actor->renderradius * actor->renderradius);

		BSPWalkCircle(x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor
		{
			FLightNode * node = subsector->lighthead;
			while (node) // check all lights touching a subsector
			{
				ADynamicLight *light = node->lightsource;
				if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != actor) && !(light->lightflags&LF_DONTLIGHTACTORS))
				{
					int group = subsector->sector->PortalGroup;
					DVector3 pos = light->PosRelative(group);
					float radius = (float)(light->GetRadius() + actor->renderradius);
					double dx = pos.X - x;
					double dy = pos.Y - y;
					double dz = pos.Z - z;
					double distSquared = dx * dx + dy * dy + dz * dz;
					if (distSquared < radius * radius) // Light and actor touches
					{
						if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
						{
							addedLights.Push(light);
						}
					}
				}
				node = node->nextLight;
			}
		});

		NumLights = addedLights.Size();
		Lights = Thread->FrameMemory->AllocMemory<PolyLight>(NumLights);
		for (int i = 0; i < NumLights; i++)
		{
			ADynamicLight *lightsource = addedLights[i];

			bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0;

			uint32_t red = lightsource->GetRed();
			uint32_t green = lightsource->GetGreen();
			uint32_t blue = lightsource->GetBlue();

			PolyLight &light = Lights[i];
			light.x = (float)lightsource->X();
			light.y = (float)lightsource->Y();
			light.z = (float)lightsource->Z();
			light.radius = 256.0f / lightsource->GetRadius();
			light.color = (red << 16) | (green << 8) | blue;
			if (is_point_light)
				light.radius = -light.radius;
		}
	}
}