rtx: attenuate lights based on solid angle, not distance and area, #145
breaks previous tuning
This commit is contained in:
parent
de2a52dd71
commit
e3e8693b13
|
@ -9,9 +9,9 @@
|
|||
|
||||
// FIXME what should these be?
|
||||
const float shadow_offset_fudge = .1;
|
||||
const float pdf_culling_threshold = 100.;
|
||||
const float color_factor = 600.;
|
||||
const float color_culling_threshold = 600./color_factor;
|
||||
const float pdf_culling_threshold = 1e6;//100.;
|
||||
const float color_factor = 1.;
|
||||
const float color_culling_threshold = 1e-6;//600./color_factor;
|
||||
const float throughput_threshold = 1e-3;
|
||||
|
||||
layout (constant_id = 4) const float LIGHT_GRID_CELL_SIZE = 256.;
|
||||
|
@ -103,6 +103,16 @@ void evalSplitBRDF(vec3 N, vec3 L, vec3 V, MaterialProperties material, out vec3
|
|||
#endif
|
||||
}
|
||||
|
||||
float triangleSolidAngle(vec3 p, vec3 a, vec3 b, vec3 c) {
|
||||
a = normalize(a - p);
|
||||
b = normalize(b - p);
|
||||
c = normalize(c - p);
|
||||
|
||||
const float tanHalfOmega = dot(a, cross(b,c)) / (1. + dot(b,c) + dot(c,a) + dot(a,b));
|
||||
|
||||
return atan(tanHalfOmega) * 2.;
|
||||
}
|
||||
|
||||
void sampleSurfaceTriangle(
|
||||
vec3 color, vec3 view_dir, MaterialProperties material /* TODO BrdfData instead is supposedly more efficient */,
|
||||
mat4x3 emissive_transform, mat3 emissive_transform_normal,
|
||||
|
@ -145,9 +155,10 @@ void sampleSurfaceTriangle(
|
|||
#endif
|
||||
|
||||
// TODO emissive normals and areas can be precomputed
|
||||
const float area = .5 * length(cross(v1 - v2, v1 - v3));
|
||||
const float area = 1.;//.5 * length(cross(v1 - v2, v1 - v3));
|
||||
const float light_dist2 = dot(light_dir, light_dir);
|
||||
float pdf = light_dist2 / (area * light_dot);
|
||||
//float pdf = /*light_dist2 */ 1./ (area * light_dot);
|
||||
float pdf = TWO_PI / triangleSolidAngle(payload_opaque.hit_pos_t.xyz, v1, v2, v3);
|
||||
|
||||
if (pdf > pdf_culling_threshold)
|
||||
#ifdef DEBUG_LIGHT_CULLING
|
||||
|
@ -203,6 +214,8 @@ void computePointLights(uint cluster_index, vec3 throughput, vec3 view_dir, Mate
|
|||
const bool not_environment = (lights.point_lights[i].environment == 0);
|
||||
|
||||
const vec3 light_dir = not_environment ? (origin_r.xyz - payload_opaque.hit_pos_t.xyz) : -dir; // TODO need to randomize sampling direction for environment soft shadow
|
||||
const float radius = origin_r.w;
|
||||
|
||||
const vec3 light_dir_norm = normalize(light_dir);
|
||||
const float light_dot = dot(light_dir_norm, payload_opaque.normal);
|
||||
if (light_dot < 1e-5)
|
||||
|
@ -216,27 +229,34 @@ void computePointLights(uint cluster_index, vec3 throughput, vec3 view_dir, Mate
|
|||
if (spot_dot < stopdot)
|
||||
spot_attenuation = (spot_dot - stopdot2) / (stopdot - stopdot2);
|
||||
|
||||
float fdist = 1.f;
|
||||
float light_dist = 1e4; // TODO this is supposedly not the right way to do shadows for environment lights. qrad checks for hitting SURF_SKY, and maybe we should too?
|
||||
//float fdist = 1.f;
|
||||
float light_dist = 1e5; // TODO this is supposedly not the right way to do shadows for environment lights. qrad checks for hitting SURF_SKY, and maybe we should too?
|
||||
const float d2 = dot(light_dir, light_dir);
|
||||
const float r2 = origin_r.w * origin_r.w;
|
||||
if (not_environment) {
|
||||
#if 1
|
||||
const float d2 = dot(light_dir, light_dir);
|
||||
const float r2 = origin_r.w * origin_r.w;
|
||||
//light_dist = sqrt(d2);
|
||||
light_dist = sqrt(d2) - origin_r.w;
|
||||
fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
#else
|
||||
const float d2 = dot(light_dir, light_dir);
|
||||
//const float r2 = origin_r.w * origin_r.w;
|
||||
light_dist = sqrt(d2);
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
fdist = (light_dist > 1.) ? 1.f / d2 : 1.f; // qrad workaround
|
||||
#endif
|
||||
}
|
||||
const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
||||
if (radius < 1e-3)
|
||||
continue;
|
||||
|
||||
const float dist = length(light_dir);
|
||||
if (radius > dist)
|
||||
continue;
|
||||
#if 1
|
||||
//light_dist = sqrt(d2);
|
||||
light_dist = dist - radius;
|
||||
//fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
#else
|
||||
light_dist = dist;
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||
//fdist = (light_dist > 1.) ? 1.f / d2 : 1.f; // qrad workaround
|
||||
#endif
|
||||
|
||||
//const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
||||
//const float pdf = TWO_PI / asin(radius / dist);
|
||||
const float pdf = 1. / ((1. - sqrt(d2 - r2) / dist) * spot_attenuation);
|
||||
color /= pdf;
|
||||
}
|
||||
|
||||
color /= pdf;
|
||||
// if (dot(color,color) < color_culling_threshold)
|
||||
// continue;
|
||||
|
||||
|
|
|
@ -839,21 +839,35 @@ static int addSpotLight( const vk_light_entity_t *le, float radius, int lightsty
|
|||
return index;
|
||||
}
|
||||
|
||||
static float sphereSolidAngleFromDistDiv2Pi(float r, float d) {
|
||||
return 1. - sqrt(d*d - r*r)/d;
|
||||
}
|
||||
|
||||
static void addDlight( const dlight_t *dlight ) {
|
||||
const float scaler = 1.f; //dlight->radius / 255.f;
|
||||
const float k_light_radius = 2.f;
|
||||
const float k_threshold = 2.f;
|
||||
|
||||
float max_comp;
|
||||
vec3_t color;
|
||||
int index;
|
||||
float scaler;
|
||||
|
||||
if( !dlight || dlight->die < gpGlobals->time || !dlight->radius )
|
||||
return;
|
||||
|
||||
max_comp = Q_max(dlight->color.r, Q_max(dlight->color.g, dlight->color.b));
|
||||
if (max_comp < k_threshold || dlight->radius <= k_light_radius)
|
||||
return;
|
||||
|
||||
scaler = k_threshold / (max_comp * sphereSolidAngleFromDistDiv2Pi(k_light_radius, dlight->radius));
|
||||
|
||||
VectorSet(
|
||||
color,
|
||||
dlight->color.r * scaler,
|
||||
dlight->color.g * scaler,
|
||||
dlight->color.b * scaler);
|
||||
|
||||
index = addPointLight(dlight->origin, color, dlight->radius, -1, 1e5f);
|
||||
index = addPointLight(dlight->origin, color, k_light_radius, -1, 1.f);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
|
@ -869,9 +883,9 @@ static void processStaticPointLights( void ) {
|
|||
for (int i = 0; i < g_map_entities.num_lights; ++i) {
|
||||
const vk_light_entity_t *le = g_map_entities.lights + i;
|
||||
const float default_radius = 2.f; // FIXME tune
|
||||
const float hack_attenuation = 100.f; // FIXME tune
|
||||
const float hack_attenuation_spot = 100.f; // FIXME tune
|
||||
float radius = le->radius > 0.f ? le->radius : default_radius;
|
||||
const float hack_attenuation = 1.f; // FIXME tune
|
||||
const float hack_attenuation_spot = 1.f; // FIXME tune
|
||||
const float radius = le->radius > 0.f ? le->radius : default_radius;
|
||||
int index;
|
||||
|
||||
switch (le->type) {
|
||||
|
|
|
@ -193,7 +193,7 @@ static void fillLightFromProps( vk_light_entity_t *le, const entity_props_t *pro
|
|||
weirdGoldsrcLightScaling(le->color);
|
||||
}
|
||||
|
||||
gEngine.Con_Reportf("%s light %d (ent=%d): %s targetname=%s color=(%f %f %f) origin=(%f %f %f) style=%d dir=(%f %f %f) stopdot=(%f %f)\n",
|
||||
gEngine.Con_Reportf("%s light %d (ent=%d): %s targetname=%s color=(%f %f %f) origin=(%f %f %f) style=%d R=%f dir=(%f %f %f) stopdot=(%f %f)\n",
|
||||
patch ? "Patch" : "Added",
|
||||
g_map_entities.num_lights, entity_index,
|
||||
le->type == LightTypeEnvironment ? "environment" : le->type == LightTypeSpot ? "spot" : "point",
|
||||
|
@ -201,6 +201,7 @@ static void fillLightFromProps( vk_light_entity_t *le, const entity_props_t *pro
|
|||
le->color[0], le->color[1], le->color[2],
|
||||
le->origin[0], le->origin[1], le->origin[2],
|
||||
le->style,
|
||||
le->radius,
|
||||
le->dir[0], le->dir[1], le->dir[2],
|
||||
le->stopdot, le->stopdot2);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue