diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-03-31 02:07:30 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-03-31 02:07:51 +0300 |
commit | e254aa896552fa2d06ab406235ace6bdeaf5905c (patch) | |
tree | fac652df1272f4953c2b77c2919c202469a1641e /source/blender/draw/engines | |
parent | 3fdbd78a6b5f271a8022f01ddca649ef16cf5516 (diff) |
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.
Diffstat (limited to 'source/blender/draw/engines')
4 files changed, 192 insertions, 188 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 3b781db90c2..9d2523ada6b 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -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; } diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index b0b48e94809..8af243a0688 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -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) -{ - 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) +vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness) { - 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); - - vec2 area_half_size = vec2(sizeX, sizeY); + vec3 refproj = line_plane_intersect(sd.W, dir, ld.l_position, ld.l_forward); - /* Find the closest point to the rectangular light shape */ - vec3 refdir = refproj - Lpos; - vec2 mrp = vec2(dot(refdir, Lx), dot(refdir, Ly)); + /* 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)); - /* 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 */ } diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl index 953d4e0a551..bf854f6eee5 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -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 = 1.0; - mrp_sphere(radius, Ldist, R, L, roughness, energy_conservation); - float bsdf = bsdf_ggx(N, L, V, roughness); + 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); - 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; - - /* 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); - - vec3 R = reflect(V, N); - mrp_area(R, N, W, W + lco, Lx, Ly, Lz, Lsizex, Lsizey, Ldist, L); + vec3 L = mrp_area(ld, sd, sd.spec_dominant_dir); - float bsdf = bsdf_ggx(N, L, V, roughness) * solidAngle; + float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness) * sd.area_data.solid_angle; - 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; } diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index f2c7b9579dd..84b1b1d599e 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -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,98 +21,110 @@ 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; } -void main() +/* Calculation common to all bsdfs */ +float light_common(inout LightData ld, inout ShadingData sd) { - vec3 N = normalize(worldNormal); + float vis = 1.0; - vec3 V; - if (ProjectionMatrix[3][3] == 0.0) { - V = normalize(cameraPos - worldPosition); + if (ld.l_type == SUN) { + sd.L = -ld.l_forward; } else { - V = normalize(eye); + sd.L = sd.l_vector / sd.l_distance; } - 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)); + 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; +} + +void main() +{ + 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 radiance = vec3(0.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]; + + sd.l_vector = ld.l_position - worldPosition; + sd.l_distance = length(sd.l_vector); + + light_common(ld, sd); - 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); + float vis = light_visibility(ld, sd); + float spec = light_specular(ld, sd, roughness); + float diff = light_diffuse(ld, sd); - radiance += vis * (diff + spec); + radiance += vis * (albedo * diff + specular * spec) * ld.l_color; } fragColor = vec4(radiance, 1.0); |