Use spotlight cone angle for D-light pass object culling
Lowers the GPU cost of spotlights.
This commit is contained in:
parent
7853329e6d
commit
adc944a415
@ -25,11 +25,11 @@ namespace spades {
|
||||
GLDynamicLight::GLDynamicLight(const client::DynamicLightParam ¶m) : param(param) {
|
||||
|
||||
if (param.type == client::DynamicLightTypeSpotlight) {
|
||||
float t = tanf(param.spotAngle * .5f) * 2.f;
|
||||
float t = tanf(param.spotAngle * .5f);
|
||||
Matrix4 mat;
|
||||
mat = Matrix4::FromAxis(param.spotAxis[0], param.spotAxis[1], param.spotAxis[2],
|
||||
param.origin);
|
||||
mat = mat * Matrix4::Scale(t, t, 1.f);
|
||||
mat = mat * Matrix4::Scale(t * 2.0f, t * 2.0f, 1.f);
|
||||
|
||||
projMatrix = mat.InversedFast();
|
||||
|
||||
@ -40,18 +40,53 @@ namespace spades {
|
||||
m.m[8] += .5f;
|
||||
m.m[9] += .5f;
|
||||
projMatrix = m * projMatrix;
|
||||
|
||||
// Construct clipping planes which are oriented inside.
|
||||
// To do that, first we calculate tangent vectors:
|
||||
Vector3 planeTan[] = {
|
||||
param.spotAxis[2] + param.spotAxis[0] * t,
|
||||
param.spotAxis[2] + param.spotAxis[1] * t,
|
||||
param.spotAxis[2] - param.spotAxis[0] * t,
|
||||
param.spotAxis[2] - param.spotAxis[1] * t,
|
||||
};
|
||||
// Then, use them to derive normal vectors:
|
||||
Vector3 planeN[] = {
|
||||
Vector3::Cross(param.spotAxis[1], planeTan[0]),
|
||||
Vector3::Cross(planeTan[1], param.spotAxis[0]),
|
||||
Vector3::Cross(planeTan[2], param.spotAxis[1]),
|
||||
Vector3::Cross(param.spotAxis[0], planeTan[3]),
|
||||
};
|
||||
// Finally, find planes with these normal vectors:
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
clipPlanes[i] = Plane3::PlaneWithPointOnPlane(param.origin, planeN[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GLDynamicLight::Cull(const spades::AABB3 &box) const {
|
||||
// TOOD: more tighter check?
|
||||
// TODO: spotlight check?
|
||||
if (param.type == client::DynamicLightTypeSpotlight) {
|
||||
for (const Plane3 &plane : clipPlanes) {
|
||||
if (!PlaneCullTest(plane, box)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const client::DynamicLightParam ¶m = GetParam();
|
||||
return box.Inflate(param.radius) && param.origin;
|
||||
}
|
||||
|
||||
bool GLDynamicLight::SphereCull(const spades::Vector3 ¢er, float radius) const {
|
||||
const client::DynamicLightParam ¶m = GetParam();
|
||||
|
||||
if (param.type == client::DynamicLightTypeSpotlight) {
|
||||
for (const Plane3 &plane : clipPlanes) {
|
||||
if (plane.GetDistanceTo(center) < -radius) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float maxDistance = radius + param.radius;
|
||||
return (center - param.origin).GetPoweredLength() < maxDistance * maxDistance;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <Client/IRenderer.h>
|
||||
#include <Core/Math.h>
|
||||
#include <array>
|
||||
|
||||
namespace spades {
|
||||
namespace draw {
|
||||
@ -28,6 +30,9 @@ namespace spades {
|
||||
client::DynamicLightParam param;
|
||||
Matrix4 projMatrix;
|
||||
|
||||
/** World-space clip planes (spotlight only) */
|
||||
std::array<Plane3, 4> clipPlanes;
|
||||
|
||||
public:
|
||||
GLDynamicLight(const client::DynamicLightParam ¶m);
|
||||
const client::DynamicLightParam &GetParam() const { return param; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user