Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Stockner <lukas.stockner@freenet.de>2018-05-24 04:50:16 +0300
committerLukas Stockner <lukas.stockner@freenet.de>2018-05-24 17:43:47 +0300
commit5505ba8d4753ee6b3c0101ba3e4abf337546a1b0 (patch)
tree1c0fdbed36127f670e8aa0d49a53f72988cc34c5 /intern/cycles/util/util_math_intersect.h
parente8c8ff4f86c276e4dca884ff1a411fcbbf003fed (diff)
Cycles/Eevee: Implement disk and ellipse shapes for area lamps
The implementation is pretty straightforward. In Cycles, sampling the shapes is currently done w.r.t. area instead of solid angle. There is a paper on solid angle sampling for disks [1], but the described algorithm is based on simply sampling the enclosing square and rejecting samples outside of the disk, which is not exactly great for Cycles' RNG (we'd need to setup a LCG for the repeated sampling) and for GPU divergence. Even worse, the algorithm is only defined for disks. For ellipses, the basic idea still works, but a way to analytically calculate the solid angle is required. This is technically possible [2], but the calculation is extremely complex and still requires a lookup table for the Heuman Lambda function. Therefore, I've decided to not implement that for now, we could still look into it later on. In Eevee, the code uses the existing ltc_evaluate_disk to implement the lighting calculations. [1]: "Solid Angle Sampling of Disk and Cylinder Lights" [2]: "Analytical solution for the solid angle subtended at any point by an ellipse via a point source radiation vector potential" Reviewers: sergey, brecht, fclem Differential Revision: https://developer.blender.org/D3171
Diffstat (limited to 'intern/cycles/util/util_math_intersect.h')
-rw-r--r--intern/cycles/util/util_math_intersect.h22
1 files changed, 15 insertions, 7 deletions
diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h
index 61ddcc38f50..5f15487df57 100644
--- a/intern/cycles/util/util_math_intersect.h
+++ b/intern/cycles/util/util_math_intersect.h
@@ -186,12 +186,17 @@ ccl_device_forceinline bool ray_triangle_intersect(
#undef dot3
}
+/* Tests for an intersection between a ray and a quad defined by
+ * its midpoint, normal and sides.
+ * If ellipse is true, hits outside the ellipse that's enclosed by the
+ * quad are rejected.
+ */
ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D,
float ray_mint, float ray_maxt,
float3 quad_P,
float3 quad_u, float3 quad_v, float3 quad_n,
float3 *isect_P, float *isect_t,
- float *isect_u, float *isect_v)
+ float *isect_u, float *isect_v, bool ellipse)
{
/* Perform intersection test. */
float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n);
@@ -200,20 +205,23 @@ ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D,
}
const float3 hit = ray_P + t*ray_D;
const float3 inplane = hit - quad_P;
- const float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f;
- if(u < 0.0f || u > 1.0f) {
+ const float u = dot(inplane, quad_u) / dot(quad_u, quad_u);
+ if(u < -0.5f || u > 0.5f) {
+ return false;
+ }
+ const float v = dot(inplane, quad_v) / dot(quad_v, quad_v);
+ if(v < -0.5f || v > 0.5f) {
return false;
}
- const float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f;
- if(v < 0.0f || v > 1.0f) {
+ if(ellipse && (u*u + v*v > 0.25f)) {
return false;
}
/* Store the result. */
/* TODO(sergey): Check whether we can avoid some checks here. */
if(isect_P != NULL) *isect_P = hit;
if(isect_t != NULL) *isect_t = t;
- if(isect_u != NULL) *isect_u = u;
- if(isect_v != NULL) *isect_v = v;
+ if(isect_u != NULL) *isect_u = u + 0.5f;
+ if(isect_v != NULL) *isect_v = v + 0.5f;
return true;
}