184 lines
6.4 KiB
GLSL
184 lines
6.4 KiB
GLSL
#extension GL_EXT_control_flow_attributes : require
|
|
layout (set = 0, binding = BINDING_LIGHTS) readonly buffer SBOLights { LightsMetadata m; } lights;
|
|
layout (set = 0, binding = BINDING_LIGHT_CLUSTERS, align = 1) readonly buffer UBOLightClusters {
|
|
//ivec3 grid_min, grid_size;
|
|
//uint8_t clusters_data[MAX_LIGHT_CLUSTERS * LIGHT_CLUSTER_SIZE + HACK_OFFSET];
|
|
LightCluster clusters_[MAX_LIGHT_CLUSTERS];
|
|
} light_grid;
|
|
|
|
const float color_culling_threshold = 0;//600./color_factor;
|
|
const float shadow_offset_fudge = .1;
|
|
|
|
#ifdef RAY_QUERY
|
|
// TODO sync with native code
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
#endif
|
|
|
|
#include "brdf.h"
|
|
#include "light_common.glsl"
|
|
|
|
#if LIGHT_POLYGON
|
|
#include "light_polygon.glsl"
|
|
#endif
|
|
|
|
#if LIGHT_POINT
|
|
void computePointLights(vec3 P, vec3 N, uint cluster_index, vec3 throughput, vec3 view_dir, MaterialProperties material, out vec3 diffuse, out vec3 specular) {
|
|
diffuse = specular = vec3(0.);
|
|
|
|
//diffuse = vec3(1.);//float(lights.m.num_point_lights) / 64.);
|
|
#define USE_CLUSTERS
|
|
#ifdef USE_CLUSTERS
|
|
const uint num_point_lights = uint(light_grid.clusters_[cluster_index].num_point_lights);
|
|
for (uint j = 0; j < num_point_lights; ++j) {
|
|
const uint i = uint(light_grid.clusters_[cluster_index].point_lights[j]);
|
|
#else
|
|
for (uint i = 0; i < lights.m.num_point_lights; ++i) {
|
|
#endif
|
|
|
|
vec3 color = lights.m.point_lights[i].color_stopdot.rgb * throughput;
|
|
if (dot(color,color) < color_culling_threshold)
|
|
continue;
|
|
|
|
const vec4 origin_r = lights.m.point_lights[i].origin_r;
|
|
const float stopdot = lights.m.point_lights[i].color_stopdot.a;
|
|
const vec3 dir = lights.m.point_lights[i].dir_stopdot2.xyz;
|
|
const float stopdot2 = lights.m.point_lights[i].dir_stopdot2.a;
|
|
const bool is_environment = (lights.m.point_lights[i].environment != 0);
|
|
|
|
const vec3 light_dir = is_environment ? -dir : (origin_r.xyz - P); // 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, N);
|
|
if (light_dot < 1e-5)
|
|
continue;
|
|
|
|
const float spot_dot = -dot(light_dir_norm, dir);
|
|
if (spot_dot < stopdot2)
|
|
continue;
|
|
|
|
float spot_attenuation = 1.f;
|
|
if (spot_dot < stopdot)
|
|
spot_attenuation = (spot_dot - stopdot2) / (stopdot - stopdot2);
|
|
|
|
//float fdist = 1.f;
|
|
float light_dist = 1e5; // TODO this is supposedly not the right way to do shadows for environment lights.m. 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 (is_environment) {
|
|
color *= 2; // TODO WHY?
|
|
} else {
|
|
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;
|
|
}
|
|
|
|
// if (dot(color,color) < color_culling_threshold)
|
|
// continue;
|
|
|
|
vec3 ldiffuse, lspecular;
|
|
evalSplitBRDF(N, light_dir_norm, view_dir, material, ldiffuse, lspecular);
|
|
ldiffuse *= color;
|
|
lspecular *= color;
|
|
|
|
vec3 combined = ldiffuse + lspecular;
|
|
|
|
if (dot(combined,combined) < color_culling_threshold)
|
|
continue;
|
|
|
|
vec3 shadow_sample_offset = normalize(vec3(rand01(), rand01(), rand01()) - vec3(0.5, 0.5, 0.5));
|
|
const float shadow_sample_radius = is_environment ? 1000. : 10.; // 10000 for some maps!
|
|
const vec3 shadow_sample_dir = light_dir_norm * light_dist + shadow_sample_offset * shadow_sample_radius;
|
|
|
|
// TODO split environment and other lights
|
|
if (is_environment) {
|
|
//if (shadowedSky(P, light_dir_norm))
|
|
if (shadowedSky(P, normalize(shadow_sample_dir)))
|
|
continue;
|
|
} else {
|
|
//if (shadowed(P, light_dir_norm, light_dist + shadow_offset_fudge))
|
|
if (shadowed(P, normalize(shadow_sample_dir), length(shadow_sample_dir) + shadow_offset_fudge))
|
|
continue;
|
|
}
|
|
|
|
diffuse += ldiffuse;
|
|
specular += lspecular;
|
|
} // for all lights
|
|
}
|
|
#endif
|
|
|
|
void computeLighting(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, MaterialProperties material, out vec3 diffuse, out vec3 specular) {
|
|
diffuse = specular = vec3(0.);
|
|
|
|
const ivec3 light_cell = ivec3(floor(P / LIGHT_GRID_CELL_SIZE)) - lights.m.grid_min_cell;
|
|
const uint cluster_index = uint(dot(light_cell, ivec3(1, lights.m.grid_size.x, lights.m.grid_size.x * lights.m.grid_size.y)));
|
|
|
|
#ifdef USE_CLUSTERS
|
|
if (any(greaterThanEqual(light_cell, lights.m.grid_size)) || cluster_index >= MAX_LIGHT_CLUSTERS)
|
|
return; // throughput * vec3(1., 0., 0.);
|
|
#endif
|
|
|
|
//diffuse = specular = vec3(1.);
|
|
//return;
|
|
|
|
// const uint cluster_offset = cluster_index * LIGHT_CLUSTER_SIZE + HACK_OFFSET;
|
|
// const int num_dlights = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_DLIGHTS_OFFSET]);
|
|
// const int num_emissive_surfaces = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_EMISSIVE_SURFACES_OFFSET]);
|
|
// const uint emissive_surfaces_offset = cluster_offset + LIGHT_CLUSTER_EMISSIVE_SURFACES_DATA_OFFSET;
|
|
//C = vec3(float(num_emissive_surfaces));
|
|
|
|
//C = vec3(float(int(light_grid.clusters[cluster_index].num_emissive_surfaces)));
|
|
//C += .3 * fract(vec3(light_cell) / 4.);
|
|
|
|
#if LIGHT_POLYGON
|
|
sampleEmissiveSurfaces(P, N, throughput, view_dir, material, cluster_index, diffuse, specular);
|
|
// These constants are empirical. There's no known math reason behind them
|
|
diffuse /= 25.0;
|
|
specular /= 25.0;
|
|
#endif
|
|
|
|
#if LIGHT_POINT
|
|
vec3 ldiffuse = vec3(0.), lspecular = vec3(0.);
|
|
computePointLights(P, N, cluster_index, throughput, view_dir, material, ldiffuse, lspecular);
|
|
// These constants are empirical. There's no known math reason behind them
|
|
ldiffuse /= 4.;
|
|
lspecular /= 4.;
|
|
|
|
diffuse += ldiffuse;
|
|
specular += lspecular;
|
|
#endif
|
|
|
|
if (any(isnan(diffuse)))
|
|
diffuse = vec3(1.,0.,0.);
|
|
|
|
if (any(isnan(specular)))
|
|
specular = vec3(0.,1.,0.);
|
|
|
|
if (any(lessThan(diffuse,vec3(0.))))
|
|
diffuse = vec3(1., 0., 1.);
|
|
|
|
if (any(lessThan(specular,vec3(0.))))
|
|
specular = vec3(0., 1., 1.);
|
|
|
|
//specular = vec3(0.,1.,0.);
|
|
//diffuse = vec3(0.);
|
|
}
|