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; }
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; }
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; } } }