Eevee: Codestyle, optimisation and a few fixes
Something is very wrong with the energy factor. For now I tweaked them by hand to fit cycles.
This commit is contained in:
@@ -91,7 +91,7 @@ void EEVEE_lights_update(EEVEE_StorageList *stl)
|
||||
EEVEE_Light *evli = stl->lights_data + i;
|
||||
Object *ob = stl->lights_ref[i];
|
||||
Lamp *la = (Lamp *)ob->data;
|
||||
float mat[4][4], scale[3];
|
||||
float mat[4][4], scale[3], power;
|
||||
|
||||
/* Position */
|
||||
copy_v3_v3(evli->position, ob->obmat[3]);
|
||||
@@ -124,13 +124,35 @@ void EEVEE_lights_update(EEVEE_StorageList *stl)
|
||||
evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
|
||||
}
|
||||
else if (la->type == LA_AREA) {
|
||||
evli->sizex = la->area_size * scale[0] * 0.5f;
|
||||
evli->sizey = la->area_sizey * scale[1] * 0.5f;
|
||||
evli->sizex = MAX2(0.0001f, la->area_size * scale[0] * 0.5f);
|
||||
if (la->area_shape == LA_AREA_RECT) {
|
||||
evli->sizey = MAX2(0.0001f, la->area_sizey * scale[1] * 0.5f);
|
||||
}
|
||||
else {
|
||||
evli->sizey = evli->sizex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
evli->sizex = la->area_size * scale[0] * 0.5f;
|
||||
evli->sizex = MAX2(0.0001f, la->area_size);
|
||||
}
|
||||
|
||||
/* Make illumination power constant */
|
||||
if (la->type == LA_AREA) {
|
||||
power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) /* 1/(w*h*Pi) */
|
||||
* M_PI * 10.0f; /* XXX : Empirical, Fit cycles power */
|
||||
}
|
||||
else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
|
||||
power = 1.0f / (4.0f * evli->sizex * evli->sizex * M_PI * M_PI) /* 1/(4*r²*Pi²) */
|
||||
* M_PI * 100.0; /* XXX : Empirical, Fit cycles power */
|
||||
|
||||
/* for point lights (a.k.a radius == 0.0) */
|
||||
// power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
|
||||
}
|
||||
else {
|
||||
power = 1.0f;
|
||||
}
|
||||
mul_v3_fl(evli->color, power);
|
||||
|
||||
/* Lamp Type */
|
||||
evli->lamptype = (float)la->type;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,49 @@
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_1_PI 0.318309886183790671538 /* 1/pi */
|
||||
|
||||
/* ------- Structures -------- */
|
||||
|
||||
struct LightData {
|
||||
vec4 position_influence; /* w : InfluenceRadius */
|
||||
vec4 color_spec; /* w : Spec Intensity */
|
||||
vec4 spotdata_shadow; /* x : spot size, y : spot blend */
|
||||
vec4 rightvec_sizex; /* xyz: Normalized up vector, w: Lamp Type */
|
||||
vec4 upvec_sizey; /* xyz: Normalized right vector, w: Lamp Type */
|
||||
vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
#define l_color color_spec.rgb
|
||||
#define l_spec color_spec.a
|
||||
#define l_position position_influence.xyz
|
||||
#define l_influence position_influence.w
|
||||
#define l_sizex rightvec_sizex.w
|
||||
#define l_radius rightvec_sizex.w
|
||||
#define l_sizey upvec_sizey.w
|
||||
#define l_right rightvec_sizex.xyz
|
||||
#define l_up upvec_sizey.xyz
|
||||
#define l_forward forwardvec_type.xyz
|
||||
#define l_type forwardvec_type.w
|
||||
#define l_spot_size spotdata_shadow.x
|
||||
#define l_spot_blend spotdata_shadow.y
|
||||
|
||||
struct AreaData {
|
||||
vec3 corner[4];
|
||||
float solid_angle;
|
||||
};
|
||||
|
||||
struct ShadingData {
|
||||
vec3 V; /* View vector */
|
||||
vec3 N; /* World Normal of the fragment */
|
||||
vec3 W; /* World Position of the fragment */
|
||||
vec3 R; /* Reflection vector */
|
||||
vec3 L; /* Current Light vector (normalized) */
|
||||
vec3 spec_dominant_dir; /* dominant direction of the specular rays */
|
||||
vec3 l_vector; /* Current Light vector */
|
||||
float l_distance; /* distance(l_position, W) */
|
||||
AreaData area_data; /* If current light is an area light */
|
||||
};
|
||||
|
||||
/* ------- Convenience functions --------- */
|
||||
|
||||
vec3 mul(mat3 m, vec3 v) { return m * v; }
|
||||
@@ -30,12 +73,12 @@ vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin,
|
||||
return lineorigin + linedirection * dist;
|
||||
}
|
||||
|
||||
float rectangle_solid_angle(vec3 p0, vec3 p1, vec3 p2, vec3 p3)
|
||||
float rectangle_solid_angle(AreaData ad)
|
||||
{
|
||||
vec3 n0 = normalize(cross(p0, p1));
|
||||
vec3 n1 = normalize(cross(p1, p2));
|
||||
vec3 n2 = normalize(cross(p2, p3));
|
||||
vec3 n3 = normalize(cross(p3, p0));
|
||||
vec3 n0 = normalize(cross(ad.corner[0], ad.corner[1]));
|
||||
vec3 n1 = normalize(cross(ad.corner[1], ad.corner[2]));
|
||||
vec3 n2 = normalize(cross(ad.corner[2], ad.corner[3]));
|
||||
vec3 n3 = normalize(cross(ad.corner[3], ad.corner[0]));
|
||||
|
||||
float g0 = acos(dot(-n0, n1));
|
||||
float g1 = acos(dot(-n1, n2));
|
||||
@@ -45,67 +88,48 @@ float rectangle_solid_angle(vec3 p0, vec3 p1, vec3 p2, vec3 p3)
|
||||
return max(0.0, (g0 + g1 + g2 + g3 - 2.0 * M_PI));
|
||||
}
|
||||
|
||||
|
||||
/* ------- Energy Conversion for lights ------- */
|
||||
/* from Sebastien Lagarde
|
||||
* course_notes_moving_frostbite_to_pbr.pdf */
|
||||
|
||||
float sphere_energy(float radius)
|
||||
vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness)
|
||||
{
|
||||
radius = max(radius, 1e-8);
|
||||
return 0.25 / (radius*radius * M_PI * M_PI) /* 1/(4*r²*Pi²) */
|
||||
* M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
|
||||
}
|
||||
|
||||
float rectangle_energy(float width, float height)
|
||||
{
|
||||
return M_1_PI / (width*height) /* 1/(w*h*Pi) */
|
||||
* 20.0; /* XXX : Empirical, Fit cycles power */
|
||||
return normalize(mix(N, R, (1.0 - roughness * roughness)));
|
||||
}
|
||||
|
||||
/* From UE4 paper */
|
||||
void mrp_sphere(
|
||||
float radius, float dist, vec3 R, inout vec3 L,
|
||||
inout float roughness, inout float energy_conservation)
|
||||
vec3 mrp_sphere(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out float energy_conservation)
|
||||
{
|
||||
L = dist * L;
|
||||
|
||||
/* Sphere Light */
|
||||
roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */
|
||||
|
||||
/* energy preservation */
|
||||
float sphere_angle = saturate(radius / dist);
|
||||
energy_conservation *= pow(roughness / saturate(roughness + 0.5 * sphere_angle), 2.0);
|
||||
float sphere_angle = saturate(ld.l_radius / sd.l_distance);
|
||||
energy_conservation = pow(roughness / saturate(roughness + 0.5 * sphere_angle), 2.0);
|
||||
|
||||
/* sphere light */
|
||||
float inter_dist = dot(L, R);
|
||||
vec3 closest_point_on_ray = inter_dist * R;
|
||||
vec3 center_to_ray = closest_point_on_ray - L;
|
||||
float inter_dist = dot(sd.l_vector, dir);
|
||||
vec3 closest_point_on_ray = inter_dist * dir;
|
||||
vec3 center_to_ray = closest_point_on_ray - sd.l_vector;
|
||||
|
||||
/* closest point on sphere */
|
||||
L = L + center_to_ray * saturate(radius * inverse_distance(center_to_ray));
|
||||
vec3 closest_point_on_sphere = sd.l_vector + center_to_ray * saturate(ld.l_radius * inverse_distance(center_to_ray));
|
||||
|
||||
L = normalize(L);
|
||||
return normalize(closest_point_on_sphere);
|
||||
}
|
||||
|
||||
void mrp_area(vec3 R, vec3 N, vec3 W, vec3 Lpos, vec3 Lx, vec3 Ly, vec3 Lz, float sizeX, float sizeY, float dist, inout vec3 L)
|
||||
vec3 mrp_area(LightData ld, ShadingData sd, vec3 dir)
|
||||
{
|
||||
vec3 refproj = line_plane_intersect(W, R, Lpos, Lz);
|
||||
vec3 norproj = line_plane_intersect(W, N, Lpos, Lz);
|
||||
vec3 refproj = line_plane_intersect(sd.W, dir, ld.l_position, ld.l_forward);
|
||||
|
||||
vec2 area_half_size = vec2(sizeX, sizeY);
|
||||
/* Project the point onto the light plane */
|
||||
vec3 refdir = refproj - ld.l_position;
|
||||
vec2 mrp = vec2(dot(refdir, ld.l_right), dot(refdir, ld.l_up));
|
||||
|
||||
/* Find the closest point to the rectangular light shape */
|
||||
vec3 refdir = refproj - Lpos;
|
||||
vec2 mrp = vec2(dot(refdir, Lx), dot(refdir, Ly));
|
||||
|
||||
/* clamp to corners */
|
||||
/* clamp to light shape bounds */
|
||||
vec2 area_half_size = vec2(ld.l_sizex, ld.l_sizey);
|
||||
mrp = clamp(mrp, -area_half_size, area_half_size);
|
||||
|
||||
L = dist * L;
|
||||
L = L + mrp.x * Lx + mrp.y * Ly ;
|
||||
/* go back in world space */
|
||||
vec3 closest_point_on_rectangle = sd.l_vector + mrp.x * ld.l_right + mrp.y * ld.l_up;
|
||||
|
||||
L = normalize(L);
|
||||
return normalize(closest_point_on_rectangle);
|
||||
}
|
||||
|
||||
/* GGX */
|
||||
@@ -121,7 +145,7 @@ float G1_Smith_GGX(float NX, float a2)
|
||||
* this way the (2*NL)*(2*NV) in G = G1(V) * G1(L) gets canceled by the brdf denominator 4*NL*NV
|
||||
* Rcp is done on the whole G later
|
||||
* Note that this is not convenient for the transmition formula */
|
||||
return NX + sqrt( NX * (NX - NX * a2) + a2 );
|
||||
return NX + sqrt(NX * (NX - NX * a2) + a2);
|
||||
/* return 2 / (1 + sqrt(1 + a2 * (1 - NX*NX) / (NX*NX) ) ); /* Reference function */
|
||||
}
|
||||
|
||||
|
||||
@@ -11,22 +11,21 @@
|
||||
|
||||
/* ------------ Diffuse ------------- */
|
||||
|
||||
float direct_diffuse_point(vec3 N, vec3 L, float Ldist)
|
||||
float direct_diffuse_point(LightData ld, ShadingData sd)
|
||||
{
|
||||
float bsdf = max(0.0, dot(N, L));
|
||||
bsdf /= Ldist * Ldist;
|
||||
bsdf *= M_PI / 2.0; /* Normalize */
|
||||
float bsdf = max(0.0, dot(sd.N, sd.L));
|
||||
bsdf /= sd.l_distance * sd.l_distance;
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
/* From Frostbite PBR Course
|
||||
* Analitical irradiance from a sphere with correct horizon handling
|
||||
* http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
|
||||
float direct_diffuse_sphere(vec3 N, vec3 L, float Ldist, float radius)
|
||||
float direct_diffuse_sphere(LightData ld, ShadingData sd)
|
||||
{
|
||||
radius = max(radius, 0.0001);
|
||||
float costheta = clamp(dot(N, L), -0.999, 0.999);
|
||||
float h = min(radius / Ldist , 0.9999);
|
||||
float radius = max(ld.l_sizex, 0.0001);
|
||||
float costheta = clamp(dot(sd.N, sd.L), -0.999, 0.999);
|
||||
float h = min(ld.l_radius / sd.l_distance , 0.9999);
|
||||
float h2 = h*h;
|
||||
float costheta2 = costheta * costheta;
|
||||
float bsdf;
|
||||
@@ -42,47 +41,31 @@ float direct_diffuse_sphere(vec3 N, vec3 L, float Ldist, float radius)
|
||||
bsdf = (costheta * acos(y) - x * sinthetasqrty) * h2 + atan(sinthetasqrty / x);
|
||||
}
|
||||
|
||||
/* Energy conservation + cycle matching */
|
||||
bsdf = max(bsdf, 0.0);
|
||||
bsdf *= M_1_PI;
|
||||
bsdf *= sphere_energy(radius);
|
||||
bsdf *= M_1_PI * M_1_PI;
|
||||
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
/* From Frostbite PBR Course
|
||||
* http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
|
||||
float direct_diffuse_rectangle(
|
||||
vec3 W, vec3 N, vec3 L,
|
||||
float Ldist, vec3 Lx, vec3 Ly, vec3 Lz, float Lsizex, float Lsizey)
|
||||
float direct_diffuse_rectangle(LightData ld, ShadingData sd)
|
||||
{
|
||||
vec3 lco = L * Ldist;
|
||||
|
||||
/* Surface to corner vectors */
|
||||
vec3 p0 = lco + Lx * -Lsizex + Ly * Lsizey;
|
||||
vec3 p1 = lco + Lx * -Lsizex + Ly * -Lsizey;
|
||||
vec3 p2 = lco + Lx * Lsizex + Ly * -Lsizey;
|
||||
vec3 p3 = lco + Lx * Lsizex + Ly * Lsizey;
|
||||
|
||||
float solidAngle = rectangle_solid_angle(p0, p1, p2, p3);
|
||||
|
||||
float bsdf = solidAngle * 0.2 * (
|
||||
max(0.0, dot(normalize(p0), N)) +
|
||||
max(0.0, dot(normalize(p1), N)) +
|
||||
max(0.0, dot(normalize(p2), N)) +
|
||||
max(0.0, dot(normalize(p3), N)) +
|
||||
max(0.0, dot(L, N))
|
||||
float bsdf = sd.area_data.solid_angle * 0.2 * (
|
||||
max(0.0, dot(normalize(sd.area_data.corner[0]), sd.N)) +
|
||||
max(0.0, dot(normalize(sd.area_data.corner[1]), sd.N)) +
|
||||
max(0.0, dot(normalize(sd.area_data.corner[2]), sd.N)) +
|
||||
max(0.0, dot(normalize(sd.area_data.corner[3]), sd.N)) +
|
||||
max(0.0, dot(sd.L, sd.N))
|
||||
);
|
||||
|
||||
bsdf *= rectangle_energy(Lsizex * 2.0, Lsizey * 2.0);
|
||||
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
/* infinitly far away point source, no decay */
|
||||
float direct_diffuse_sun(vec3 N, vec3 L)
|
||||
float direct_diffuse_sun(LightData ld, ShadingData sd)
|
||||
{
|
||||
float bsdf = max(0.0, dot(N, L));
|
||||
float bsdf = max(0.0, dot(sd.N, sd.L));
|
||||
bsdf *= M_1_PI; /* Normalize */
|
||||
return bsdf;
|
||||
}
|
||||
@@ -95,47 +78,32 @@ float direct_diffuse_unit_disc(vec3 N, vec3 L)
|
||||
#endif
|
||||
|
||||
/* ----------- GGx ------------ */
|
||||
float direct_ggx_point(vec3 N, vec3 L, vec3 V, float roughness)
|
||||
float direct_ggx_point(ShadingData sd, float roughness)
|
||||
{
|
||||
return bsdf_ggx(N, L, V, roughness);
|
||||
float bsdf = bsdf_ggx(sd.N, sd.L, sd.V, roughness);
|
||||
bsdf /= sd.l_distance * sd.l_distance;
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
float direct_ggx_sphere(vec3 N, vec3 L, vec3 V, float Ldist, float radius, float roughness)
|
||||
float direct_ggx_sphere(LightData ld, ShadingData sd, float roughness)
|
||||
{
|
||||
vec3 R = reflect(V, N);
|
||||
float energy_conservation;
|
||||
vec3 L = mrp_sphere(ld, sd, sd.spec_dominant_dir, roughness, energy_conservation);
|
||||
float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
|
||||
|
||||
float energy_conservation = 1.0;
|
||||
mrp_sphere(radius, Ldist, R, L, roughness, energy_conservation);
|
||||
float bsdf = bsdf_ggx(N, L, V, roughness);
|
||||
|
||||
bsdf *= energy_conservation / (Ldist * Ldist);
|
||||
bsdf *= sphere_energy(radius) * max(radius * radius, 1e-16); /* radius is already inside energy_conservation */
|
||||
bsdf *= M_PI;
|
||||
bsdf *= energy_conservation / (sd.l_distance * sd.l_distance);
|
||||
bsdf *= max(ld.l_radius * ld.l_radius, 1e-16); /* radius is already inside energy_conservation */
|
||||
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
float direct_ggx_rectangle(
|
||||
vec3 W, vec3 N, vec3 L, vec3 V,
|
||||
float Ldist, vec3 Lx, vec3 Ly, vec3 Lz, float Lsizex, float Lsizey, float roughness)
|
||||
float direct_ggx_rectangle(LightData ld, ShadingData sd, float roughness)
|
||||
{
|
||||
vec3 lco = L * Ldist;
|
||||
vec3 L = mrp_area(ld, sd, sd.spec_dominant_dir);
|
||||
|
||||
/* Surface to corner vectors */
|
||||
vec3 p0 = lco + Lx * -Lsizex + Ly * Lsizey;
|
||||
vec3 p1 = lco + Lx * -Lsizex + Ly * -Lsizey;
|
||||
vec3 p2 = lco + Lx * Lsizex + Ly * -Lsizey;
|
||||
vec3 p3 = lco + Lx * Lsizex + Ly * Lsizey;
|
||||
float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness) * sd.area_data.solid_angle;
|
||||
|
||||
float solidAngle = rectangle_solid_angle(p0, p1, p2, p3);
|
||||
|
||||
vec3 R = reflect(V, N);
|
||||
mrp_area(R, N, W, W + lco, Lx, Ly, Lz, Lsizex, Lsizey, Ldist, L);
|
||||
|
||||
float bsdf = bsdf_ggx(N, L, V, roughness) * solidAngle;
|
||||
|
||||
bsdf *= pow(max(0.0, dot(R, Lz)), 0.5); /* fade mrp artifacts */
|
||||
bsdf *= rectangle_energy(Lsizex * 2.0, Lsizey * 2.0);
|
||||
bsdf *= max(0.0, dot(-sd.spec_dominant_dir, ld.l_forward)); /* fade mrp artifacts */
|
||||
|
||||
return bsdf;
|
||||
}
|
||||
|
||||
@@ -4,28 +4,6 @@ uniform vec3 cameraPos;
|
||||
uniform vec3 eye;
|
||||
uniform mat4 ProjectionMatrix;
|
||||
|
||||
struct LightData {
|
||||
vec4 positionAndInfluence; /* w : InfluenceRadius */
|
||||
vec4 colorAndSpec; /* w : Spec Intensity */
|
||||
vec4 spotDataRadiusShadow; /* x : spot size, y : spot blend */
|
||||
vec4 rightVecAndSizex; /* xyz: Normalized up vector, w: Lamp Type */
|
||||
vec4 upVecAndSizey; /* xyz: Normalized right vector, w: Lamp Type */
|
||||
vec4 forwardVecAndType; /* xyz: Normalized forward vector, w: Lamp Type */
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
#define lampColor colorAndSpec.rgb
|
||||
#define lampSpec colorAndSpec.a
|
||||
#define lampPosition positionAndInfluence.xyz
|
||||
#define lampInfluence positionAndInfluence.w
|
||||
#define lampSizeX rightVecAndSizex.w
|
||||
#define lampSizeY upVecAndSizey.w
|
||||
#define lampRight rightVecAndSizex.xyz
|
||||
#define lampUp upVecAndSizey.xyz
|
||||
#define lampForward forwardVecAndType.xyz
|
||||
#define lampType forwardVecAndType.w
|
||||
#define lampSpotSize spotDataRadiusShadow.x
|
||||
#define lampSpotBlend spotDataRadiusShadow.y
|
||||
|
||||
layout(std140) uniform light_block {
|
||||
LightData lights_data[MAX_LIGHT];
|
||||
@@ -43,67 +21,74 @@ out vec4 fragColor;
|
||||
#define HEMI 3.0
|
||||
#define AREA 4.0
|
||||
|
||||
vec3 light_diffuse(LightData ld, vec3 N, vec3 W, vec3 wL, vec3 L, float Ldist, vec3 color)
|
||||
float light_diffuse(LightData ld, ShadingData sd)
|
||||
{
|
||||
vec3 light;
|
||||
|
||||
if (ld.lampType == SUN) {
|
||||
L = -ld.lampForward;
|
||||
light = color * direct_diffuse_sun(N, L) * ld.lampColor;
|
||||
if (ld.l_type == SUN) {
|
||||
return direct_diffuse_sun(ld, sd);
|
||||
}
|
||||
else if (ld.lampType == AREA) {
|
||||
light = color * direct_diffuse_rectangle(W, N, L, Ldist,
|
||||
ld.lampRight, ld.lampUp, ld.lampForward,
|
||||
ld.lampSizeX, ld.lampSizeY) * ld.lampColor;
|
||||
else if (ld.l_type == AREA) {
|
||||
return direct_diffuse_rectangle(ld, sd);
|
||||
}
|
||||
else {
|
||||
// light = color * direct_diffuse_point(N, L, Ldist) * ld.lampColor;
|
||||
light = color * direct_diffuse_sphere(N, L, Ldist, ld.lampSizeX) * ld.lampColor;
|
||||
return direct_diffuse_sphere(ld, sd);
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
vec3 light_specular(
|
||||
LightData ld, vec3 V, vec3 N, vec3 W, vec3 wL,
|
||||
vec3 L, float Ldist, vec3 spec, float roughness)
|
||||
float light_specular(LightData ld, ShadingData sd, float roughness)
|
||||
{
|
||||
vec3 light;
|
||||
|
||||
if (ld.lampType == SUN) {
|
||||
L = -ld.lampForward;
|
||||
light = spec * direct_ggx_point(N, L, V, roughness) * ld.lampColor;
|
||||
if (ld.l_type == SUN) {
|
||||
return direct_ggx_point(sd, roughness);
|
||||
}
|
||||
else if (ld.lampType == AREA) {
|
||||
light = spec * direct_ggx_rectangle(W, N, L, V, Ldist, ld.lampRight, ld.lampUp, ld.lampForward,
|
||||
ld.lampSizeX, ld.lampSizeY, roughness) * ld.lampColor;
|
||||
else if (ld.l_type == AREA) {
|
||||
return direct_ggx_rectangle(ld, sd, roughness);
|
||||
}
|
||||
else {
|
||||
light = spec * direct_ggx_sphere(N, L, V, Ldist, ld.lampSizeX, roughness) * ld.lampColor;
|
||||
// return direct_ggx_point(sd, roughness);
|
||||
return direct_ggx_sphere(ld, sd, roughness);
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
float light_visibility(
|
||||
LightData ld, vec3 V, vec3 N, vec3 W, vec3 wL, vec3 L, float Ldist)
|
||||
float light_visibility(LightData ld, ShadingData sd)
|
||||
{
|
||||
float vis = 1.0;
|
||||
|
||||
if (ld.lampType == SPOT) {
|
||||
float z = dot(ld.lampForward, wL);
|
||||
vec3 lL = wL / z;
|
||||
float x = dot(ld.lampRight, lL) / ld.lampSizeX;
|
||||
float y = dot(ld.lampUp, lL) / ld.lampSizeY;
|
||||
if (ld.l_type == SPOT) {
|
||||
float z = dot(ld.l_forward, sd.l_vector);
|
||||
vec3 lL = sd.l_vector / z;
|
||||
float x = dot(ld.l_right, lL) / ld.l_sizex;
|
||||
float y = dot(ld.l_up, lL) / ld.l_sizey;
|
||||
|
||||
float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
|
||||
|
||||
float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.lampSpotSize) / ld.lampSpotBlend);
|
||||
float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
|
||||
|
||||
vis *= spotmask;
|
||||
}
|
||||
else if (ld.lampType == AREA) {
|
||||
vis *= step(0.0, -dot(L, ld.lampForward));
|
||||
else if (ld.l_type == AREA) {
|
||||
vis *= step(0.0, -dot(sd.L, ld.l_forward));
|
||||
}
|
||||
|
||||
return vis;
|
||||
}
|
||||
|
||||
/* Calculation common to all bsdfs */
|
||||
float light_common(inout LightData ld, inout ShadingData sd)
|
||||
{
|
||||
float vis = 1.0;
|
||||
|
||||
if (ld.l_type == SUN) {
|
||||
sd.L = -ld.l_forward;
|
||||
}
|
||||
else {
|
||||
sd.L = sd.l_vector / sd.l_distance;
|
||||
}
|
||||
|
||||
if (ld.l_type == AREA) {
|
||||
sd.area_data.corner[0] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
|
||||
sd.area_data.corner[1] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
|
||||
sd.area_data.corner[2] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
|
||||
sd.area_data.corner[3] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
|
||||
sd.area_data.solid_angle = rectangle_solid_angle(sd.area_data);
|
||||
}
|
||||
|
||||
return vis;
|
||||
@@ -111,30 +96,35 @@ float light_visibility(
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 N = normalize(worldNormal);
|
||||
ShadingData sd;
|
||||
sd.N = normalize(worldNormal);
|
||||
sd.V = (ProjectionMatrix[3][3] == 0.0) /* if perspective */
|
||||
? normalize(cameraPos - worldPosition)
|
||||
: normalize(eye);
|
||||
sd.W = worldPosition;
|
||||
sd.R = reflect(-sd.V, sd.N);
|
||||
|
||||
/* hardcoded test vars */
|
||||
vec3 albedo = vec3(0.0);
|
||||
vec3 specular = mix(vec3(1.0), vec3(1.0), pow(max(0.0, 1.0 - dot(sd.N, sd.V)), 5.0));
|
||||
float roughness = 0.5;
|
||||
|
||||
sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughness);
|
||||
|
||||
vec3 V;
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
V = normalize(cameraPos - worldPosition);
|
||||
}
|
||||
else {
|
||||
V = normalize(eye);
|
||||
}
|
||||
vec3 radiance = vec3(0.0);
|
||||
|
||||
vec3 albedo = vec3(1.0, 1.0, 1.0);
|
||||
vec3 specular = mix(vec3(0.03), vec3(1.0), pow(max(0.0, 1.0 - dot(N,V)), 5.0));
|
||||
|
||||
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
|
||||
vec3 wL = lights_data[i].lampPosition - worldPosition;
|
||||
float dist = length(wL);
|
||||
vec3 L = wL / dist;
|
||||
LightData ld = lights_data[i];
|
||||
|
||||
float vis = light_visibility(lights_data[i], V, N, worldPosition, wL, L, dist);
|
||||
vec3 spec = light_specular(lights_data[i], V, N, worldPosition, wL, L, dist, vec3(1.0), .2);
|
||||
vec3 diff = light_diffuse(lights_data[i], N, worldPosition, wL, L, dist, albedo);
|
||||
sd.l_vector = ld.l_position - worldPosition;
|
||||
sd.l_distance = length(sd.l_vector);
|
||||
|
||||
radiance += vis * (diff + spec);
|
||||
light_common(ld, sd);
|
||||
|
||||
float vis = light_visibility(ld, sd);
|
||||
float spec = light_specular(ld, sd, roughness);
|
||||
float diff = light_diffuse(ld, sd);
|
||||
|
||||
radiance += vis * (albedo * diff + specular * spec) * ld.l_color;
|
||||
}
|
||||
|
||||
fragColor = vec4(radiance, 1.0);
|
||||
|
||||
Reference in New Issue
Block a user