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:
-rw-r--r--intern/cycles/blender/addon/ui.py21
-rw-r--r--intern/cycles/blender/blender_light.cpp1
-rw-r--r--intern/cycles/kernel/kernel_light.h16
-rw-r--r--intern/cycles/kernel/kernel_light_common.h11
-rw-r--r--intern/cycles/kernel/kernel_types.h4
-rw-r--r--intern/cycles/render/light.cpp12
-rw-r--r--intern/cycles/render/light.h1
-rw-r--r--source/blender/blenloader/intern/versioning_290.c7
-rw-r--r--source/blender/makesdna/DNA_light_defaults.h1
-rw-r--r--source/blender/makesdna/DNA_light_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_light.c9
11 files changed, 73 insertions, 12 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index c9b4dc25cf2..4e8527387c0 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1409,15 +1409,15 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
-class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
- bl_label = "Spot Shape"
+class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
+ bl_label = "Beam Shape"
bl_parent_id = "CYCLES_LIGHT_PT_light"
bl_context = "data"
@classmethod
def poll(cls, context):
- light = context.light
- return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
+ if context.light.type in {'SPOT', 'AREA'}:
+ return context.light and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1425,9 +1425,12 @@ class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
layout.use_property_split = True
col = layout.column()
- col.prop(light, "spot_size", text="Size")
- col.prop(light, "spot_blend", text="Blend", slider=True)
- col.prop(light, "show_cone")
+ if light.type == 'SPOT':
+ col.prop(light, "spot_size", text="Spot Size")
+ col.prop(light, "spot_blend", text="Blend", slider=True)
+ col.prop(light, "show_cone")
+ elif light.type == 'AREA':
+ col.prop(light, "spread", text="Spread")
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
@@ -2284,7 +2287,7 @@ classes = (
CYCLES_LIGHT_PT_preview,
CYCLES_LIGHT_PT_light,
CYCLES_LIGHT_PT_nodes,
- CYCLES_LIGHT_PT_spot,
+ CYCLES_LIGHT_PT_beam_shape,
CYCLES_WORLD_PT_preview,
CYCLES_WORLD_PT_surface,
CYCLES_WORLD_PT_volume,
@@ -2314,7 +2317,7 @@ classes = (
node_panel(CYCLES_WORLD_PT_settings_surface),
node_panel(CYCLES_WORLD_PT_settings_volume),
node_panel(CYCLES_LIGHT_PT_light),
- node_panel(CYCLES_LIGHT_PT_spot),
+ node_panel(CYCLES_LIGHT_PT_beam_shape)
)
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index ff4ecc5a3f9..283ed7d0adc 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -82,6 +82,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_axisu(transform_get_column(&tfm, 0));
light->set_axisv(transform_get_column(&tfm, 1));
light->set_sizeu(b_area_light.size());
+ light->set_spread(b_area_light.spread());
switch (b_area_light.shape()) {
case BL::AreaLight::shape_SQUARE:
light->set_sizev(light->get_sizeu());
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 9650b85a5c2..93b05f0ffce 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -147,6 +147,13 @@ ccl_device_inline bool lamp_light_sample(
ls->D = normalize_len(ls->P - P, &ls->t);
ls->eval_fac = 0.25f * invarea;
+
+ if (klight->area.tan_spread > 0.0f) {
+ /* Area Light spread angle attenuation */
+ ls->eval_fac *= light_spread_attenuation(
+ ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
+ }
+
if (is_round) {
ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
}
@@ -286,6 +293,15 @@ ccl_device bool lamp_light_eval(
ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
}
ls->eval_fac = 0.25f * invarea;
+
+ if (klight->area.tan_spread > 0.0f) {
+ /* Area Light spread angle attenuation */
+ ls->eval_fac *= light_spread_attenuation(
+ ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
+ if (ls->eval_fac == 0.0f) {
+ return false;
+ }
+ }
}
else {
return false;
diff --git a/intern/cycles/kernel/kernel_light_common.h b/intern/cycles/kernel/kernel_light_common.h
index 39503a4b479..7efd1e74202 100644
--- a/intern/cycles/kernel/kernel_light_common.h
+++ b/intern/cycles/kernel/kernel_light_common.h
@@ -146,6 +146,17 @@ ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot
return attenuation;
}
+ccl_device float light_spread_attenuation(const float3 D,
+ const float3 Ng,
+ const float tan_spread,
+ const float normalize_spread)
+{
+ const float cos_a = -dot(D, Ng);
+ const float sin_a = safe_sqrtf(1.0f - sqr(cos_a));
+ const float tan_a = sin_a / cos_a;
+ return max((1.0f - (tan_spread * tan_a)) * normalize_spread, 0.0f);
+}
+
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
{
float cos_pi = dot(Ng, I);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index df56360b1df..ab54fda14af 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -1501,9 +1501,9 @@ typedef struct KernelAreaLight {
float axisu[3];
float invarea;
float axisv[3];
- float pad1;
+ float tan_spread;
float dir[3];
- float pad2;
+ float normalize_spread;
} KernelAreaLight;
typedef struct KernelDistantLight {
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 72450e2c546..858b177b69c 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -129,6 +129,7 @@ NODE_DEFINE(Light)
SOCKET_VECTOR(axisv, "Axis V", zero_float3());
SOCKET_FLOAT(sizev, "Size V", 1.0f);
SOCKET_BOOLEAN(round, "Round", false);
+ SOCKET_FLOAT(spread, "Spread", M_PI_F);
SOCKET_INT(map_resolution, "Map Resolution", 0);
@@ -858,6 +859,15 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
float3 dir = light->dir;
+ /* Convert from spread angle 0..180 to 90..0, clamping to a minimum
+ * angle to avoid excessive noise. */
+ const float min_spread_angle = 1.0f * M_PI_F / 180.0f;
+ const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle));
+ /* Normalization computed using:
+ * integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */
+ const float tan_spread = tanf(spread_angle);
+ const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread);
+
dir = safe_normalize(dir);
if (light->use_mis && area != 0.0f)
@@ -877,6 +887,8 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].area.dir[0] = dir.x;
klights[light_index].area.dir[1] = dir.y;
klights[light_index].area.dir[2] = dir.z;
+ klights[light_index].area.tan_spread = tan_spread;
+ klights[light_index].area.normalize_spread = normalize_spread;
}
else if (light->light_type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 39014b5d667..fbd709125ff 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -58,6 +58,7 @@ class Light : public Node {
NODE_SOCKET_API(float3, axisv)
NODE_SOCKET_API(float, sizev)
NODE_SOCKET_API(bool, round)
+ NODE_SOCKET_API(float, spread)
NODE_SOCKET_API(Transform, tfm)
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index d8f798a11cd..0c6817542d1 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -1963,5 +1963,12 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
arm->axes_position = 1.0;
}
}
+
+ /* Initialize the spread parameter for area lights*/
+ if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "area_spread")) {
+ LISTBASE_FOREACH (Light *, la, &bmain->lights) {
+ la->area_spread = DEG2RADF(180.0f);
+ }
+ }
}
}
diff --git a/source/blender/makesdna/DNA_light_defaults.h b/source/blender/makesdna/DNA_light_defaults.h
index f3ccf14ac5b..5e5ce4bf540 100644
--- a/source/blender/makesdna/DNA_light_defaults.h
+++ b/source/blender/makesdna/DNA_light_defaults.h
@@ -68,6 +68,7 @@
.volume_fac = 1.0f, \
.att_dist = 40.0f, \
.sun_angle = DEG2RADF(0.526f), \
+ .area_spread = DEG2RADF(180.0f), \
}
/** \} */
diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h
index 3b7440aedd2..82ff3c95834 100644
--- a/source/blender/makesdna/DNA_light_types.h
+++ b/source/blender/makesdna/DNA_light_types.h
@@ -70,9 +70,9 @@ typedef struct Light {
short area_shape;
float area_size, area_sizey, area_sizez;
+ float area_spread;
float sun_angle;
- char _pad3[4];
/* texact is for buttons */
short texact, shadhalostep;
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index bb99e5c6c1d..0593db0dd56 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -480,6 +480,15 @@ static void rna_def_area_light(BlenderRNA *brna)
"Size Y",
"Size of the area of the area light in the Y direction for rectangle shapes");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+
+ prop = RNA_def_property(srna, "spread", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "area_spread");
+ RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
+ RNA_def_property_ui_text(
+ prop,
+ "Spread",
+ "How widely the emitted light fans out, as in the case of a gridded softbox");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
}
static void rna_def_spot_light(BlenderRNA *brna)