Пример #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);
}
Пример #2
0
void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata)
{
	modellightdata.Clear();

	if (self)
	{
		auto &addedLights = addedLightsArray;	// avoid going through the thread local storage for each use.

		addedLights.Clear();

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

		BSPWalkCircle(self->Level, x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor
		{
			auto section = subsector->section;
			if (section->validcount == dl_validcount) return;	// already done from a previous subsector.
			FLightNode * node = section->lighthead;
			while (node) // check all lights touching a subsector
			{
				FDynamicLight *light = node->lightsource;
				if (light->ShouldLightActor(self))
				{
					int group = subsector->sector->PortalGroup;
					DVector3 pos = light->PosRelative(group);
					float radius = (float)(light->GetRadius() + self->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
						{
							modellightdata.AddLightToList(group, light, true);
							addedLights.Push(light);
						}
					}
				}
				node = node->nextLight;
			}
		});
	}
}
Пример #3
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;
		}
	}
}