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
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-02-28 20:45:08 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-02-28 20:45:08 +0400
commit22abc63f676dc7681ee8f734cbc96a7279172d24 (patch)
tree8f945d2a9db54869802aa5eb24c975488c99edd1 /intern
parent6cb896ff0a7d24be3ff500585642ae5d61a5b788 (diff)
Cycles: ambient occlusion support, with AO factor and distance, and a render pass.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/World#Ambient_Occlusion http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes#Lighting_Passes
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/addon/ui.py54
-rw-r--r--intern/cycles/blender/blender_session.cpp3
-rw-r--r--intern/cycles/blender/blender_shader.cpp14
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h22
-rw-r--r--intern/cycles/kernel/kernel_passes.h2
-rw-r--r--intern/cycles/kernel/kernel_path.h53
-rw-r--r--intern/cycles/kernel/kernel_types.h18
-rw-r--r--intern/cycles/render/background.cpp11
-rw-r--r--intern/cycles/render/background.h3
-rw-r--r--intern/cycles/render/film.cpp7
-rw-r--r--intern/cycles/render/integrator.cpp3
11 files changed, 158 insertions, 32 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index e006238a70d..faf057e13cc 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -196,6 +196,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_emit")
col.prop(rl, "use_pass_environment")
+ col.prop(rl, "use_pass_ambient_occlusion")
col = split.column()
col.label()
@@ -483,48 +484,67 @@ class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
layout.prop(world, "horizon_color", text="Color")
-
-class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
- bl_label = "Settings"
+class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
+ bl_label = "Volume"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- return context.world and CyclesButtonsPanel.poll(context)
+ # world = context.world
+ # world and world.node_tree and CyclesButtonsPanel.poll(context)
+ return False
def draw(self, context):
layout = self.layout
+ layout.active = False
world = context.world
- cworld = world.cycles
+ panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
- col = layout.column()
+class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
+ bl_label = "Ambient Occlusion"
+ bl_context = "world"
- col.prop(cworld, "sample_as_light")
- row = col.row()
- row.active = cworld.sample_as_light
- row.prop(cworld, "sample_map_resolution")
+ @classmethod
+ def poll(cls, context):
+ return context.world and CyclesButtonsPanel.poll(context)
+ def draw_header(self, context):
+ light = context.world.light_settings
+ self.layout.prop(light, "use_ambient_occlusion", text="")
-class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
- bl_label = "Volume"
+ def draw(self, context):
+ layout = self.layout
+ light = context.world.light_settings
+
+ layout.active = light.use_ambient_occlusion
+
+ split = layout.split()
+ split.prop(light, "ao_factor", text="Factor")
+ split.prop(light, "distance", text="Distance")
+
+class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
+ bl_label = "Settings"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- # world = context.world
- # world and world.node_tree and CyclesButtonsPanel.poll(context)
- return False
+ return context.world and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
- layout.active = False
world = context.world
- panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
+ cworld = world.cycles
+ col = layout.column()
+
+ col.prop(cworld, "sample_as_light")
+ row = col.row()
+ row.active = cworld.sample_as_light
+ row.prop(cworld, "sample_map_resolution")
class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index cc6ba073188..7f666706470 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -158,10 +158,11 @@ static PassType get_pass_type(BL::RenderPass b_pass)
return PASS_EMISSION;
case BL::RenderPass::type_ENVIRONMENT:
return PASS_BACKGROUND;
+ case BL::RenderPass::type_AO:
+ return PASS_AO;
case BL::RenderPass::type_DIFFUSE:
case BL::RenderPass::type_SHADOW:
- case BL::RenderPass::type_AO:
case BL::RenderPass::type_COLOR:
case BL::RenderPass::type_REFRACTION:
case BL::RenderPass::type_SPECULAR:
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 5310e35dc25..a88bcaf3ace 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -696,6 +696,20 @@ void BlenderSync::sync_world()
graph->connect(closure->output("Background"), out->input("Surface"));
}
+ /* AO */
+ if(b_world) {
+ BL::WorldLighting b_light = b_world.light_settings();
+
+ if(b_light.use_ambient_occlusion()) {
+ background->ao_factor = b_light.ao_factor();
+ background->ao_distance = b_light.distance();
+ }
+ else {
+ background->ao_factor = 0.0f;
+ background->ao_distance = 0.0f;
+ }
+ }
+
shader->set_graph(graph);
shader->tag_update(scene);
}
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index e71fad58c96..7d9aaf81906 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -135,6 +135,7 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
L->emission = make_float3(0.0f, 0.0f, 0.0f);
L->background = make_float3(0.0f, 0.0f, 0.0f);
+ L->ao = make_float3(0.0f, 0.0f, 0.0f);
}
else
L->emission = make_float3(0.0f, 0.0f, 0.0f);
@@ -199,6 +200,27 @@ __device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throug
#endif
}
+__device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 bsdf, float3 ao, int bounce)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ if(bounce == 0) {
+ /* directly visible lighting */
+ L->direct_diffuse += throughput*bsdf*ao;
+ L->ao += throughput*ao;
+ }
+ else {
+ /* indirectly visible lighting after BSDF bounce */
+ L->indirect += throughput*bsdf*ao;
+ }
+ }
+ else
+ L->emission += throughput*bsdf*ao;
+#else
+ *L += throughput*bsdf*ao;
+#endif
+}
+
__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, int bounce)
{
#ifdef __PASSES__
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index a1b3b0e9038..44e06be8c16 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -123,6 +123,8 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, sample, L->emission);
if(flag & PASS_BACKGROUND)
kernel_write_pass_float3(buffer + kernel_data.film.pass_background, sample, L->background);
+ if(flag & PASS_AO)
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, sample, L->ao);
if(flag & PASS_DIFFUSE_COLOR)
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, sample, L->color_diffuse);
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 05ee3212b4c..154add55004 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -145,12 +145,15 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput);
}
-__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, BsdfEval *L_light)
+__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
{
if(ray->t == 0.0f)
return false;
- bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect);
+ Intersection isect;
+ bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect);
+
+ *shadow = make_float3(1.0f, 1.0f, 1.0f);
#ifdef __TRANSPARENT_SHADOWS__
if(result && kernel_data.integrator.transparent_shadows) {
@@ -162,7 +165,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
also note that for this to work correct, multi close sampling must
be used, since we don't pass a random number to shader_eval_surface */
- if(shader_transparent_shadow(kg, isect)) {
+ if(shader_transparent_shadow(kg, &isect)) {
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 Pend = ray->P + ray->D*ray->t;
int bounce = state->transparent_bounce;
@@ -184,16 +187,16 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
#endif
}
- if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect)) {
- bsdf_eval_mul(L_light, throughput);
+ if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect)) {
+ *shadow *= throughput;
return false;
}
- if(!shader_transparent_shadow(kg, isect))
+ if(!shader_transparent_shadow(kg, &isect))
return true;
ShaderData sd;
- shader_setup_from_ray(kg, &sd, isect, ray);
+ shader_setup_from_ray(kg, &sd, &isect, ray);
shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW);
throughput *= shader_bsdf_transparency(kg, &sd);
@@ -285,6 +288,35 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
throughput /= probability;
+
+#ifdef __AO__
+ /* ambient occlusion */
+ if(kernel_data.integrator.use_ambient_occlusion) {
+ /* todo: solve correlation */
+ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
+ float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
+
+ float3 ao_D;
+ float ao_pdf;
+
+ sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+
+ if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
+ Ray light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(sd.P, sd.Ng);
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+
+ if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
+ float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
+ path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce);
+ }
+ }
+ }
+#endif
+
#ifdef __EMISSION__
if(kernel_data.integrator.use_direct_light) {
/* sample illumination from lights to find path contribution */
@@ -307,8 +339,13 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
#endif
if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &L_light)) {
/* trace shadow ray */
- if(!shadow_blocked(kg, &state, &light_ray, &isect, &L_light))
+ float3 shadow;
+
+ if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
+ /* accumulate */
+ bsdf_eval_mul(&L_light, shadow);
path_radiance_accum_light(&L, throughput, &L_light, state.bounce);
+ }
}
#ifdef __MULTI_LIGHT__
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 61335d5f9fa..e5e03cedc18 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -72,6 +72,7 @@ CCL_NAMESPACE_BEGIN
#define __TRANSPARENT_SHADOWS__
#define __PASSES__
#define __BACKGROUND_MIS__
+#define __AO__
#endif
//#define __MULTI_LIGHT__
@@ -172,7 +173,8 @@ typedef enum PassType {
PASS_GLOSSY_DIRECT = 16384,
PASS_TRANSMISSION_DIRECT = 32768,
PASS_EMISSION = 65536,
- PASS_BACKGROUND = 131072
+ PASS_BACKGROUND = 131072,
+ PASS_AO = 262144
} PassType;
#define PASS_ALL (~0)
@@ -186,6 +188,7 @@ typedef struct PathRadiance {
float3 emission;
float3 background;
+ float3 ao;
float3 indirect;
float3 direct_throughput;
@@ -237,7 +240,8 @@ typedef enum LightType {
LIGHT_POINT,
LIGHT_DISTANT,
LIGHT_BACKGROUND,
- LIGHT_AREA
+ LIGHT_AREA,
+ LIGHT_AO
} LightType;
/* Camera Type */
@@ -458,7 +462,7 @@ typedef struct KernelFilm {
int pass_emission;
int pass_background;
- int pass_pad1;
+ int pass_ao;
int pass_pad2;
} KernelFilm;
@@ -466,7 +470,10 @@ typedef struct KernelBackground {
/* only shader index */
int shader;
int transparent;
- int pad1, pad2;
+
+ /* ambient occlusion */
+ float ao_factor;
+ float ao_distance;
} KernelBackground;
typedef struct KernelSunSky {
@@ -482,6 +489,7 @@ typedef struct KernelSunSky {
typedef struct KernelIntegrator {
/* emission */
int use_direct_light;
+ int use_ambient_occlusion;
int num_distribution;
int num_all_lights;
float pdf_triangles;
@@ -509,7 +517,7 @@ typedef struct KernelIntegrator {
/* render layer */
int layer_flag;
- int pad1, pad2, pad3;
+ int pad1, pad2;
} KernelIntegrator;
typedef struct KernelBVH {
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index bf4131b6d38..c5b003fe6c5 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -31,6 +31,9 @@ CCL_NAMESPACE_BEGIN
Background::Background()
{
+ ao_factor = 0.0f;
+ ao_distance = FLT_MAX;
+
transparent = false;
need_update = true;
}
@@ -48,6 +51,10 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
/* set shader index and transparent option */
KernelBackground *kbackground = &dscene->data.background;
+
+ kbackground->ao_factor = ao_factor;
+ kbackground->ao_distance = ao_distance;
+
kbackground->transparent = transparent;
kbackground->shader = scene->shader_manager->get_shader_id(scene->default_background);
@@ -60,7 +67,9 @@ void Background::device_free(Device *device, DeviceScene *dscene)
bool Background::modified(const Background& background)
{
- return !(transparent == background.transparent);
+ return !(transparent == background.transparent &&
+ ao_factor == background.ao_factor &&
+ ao_distance == background.ao_distance);
}
void Background::tag_update(Scene *scene)
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 16d2ccb6caa..40dacd9d6b1 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -29,6 +29,9 @@ class Scene;
class Background {
public:
+ float ao_factor;
+ float ao_distance;
+
bool transparent;
bool need_update;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 376e9d6d0ca..daadb6c04c8 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -111,6 +111,10 @@ void Pass::add(PassType type, vector<Pass>& passes)
pass.components = 4;
pass.exposure = true;
break;
+ case PASS_AO:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
}
passes.push_back(pass);
@@ -224,6 +228,9 @@ void Film::device_update(Device *device, DeviceScene *dscene)
case PASS_BACKGROUND:
kfilm->pass_background = kfilm->pass_stride;
kfilm->use_light_pass = 1;
+ case PASS_AO:
+ kfilm->pass_ao = kfilm->pass_stride;
+ kfilm->use_light_pass = 1;
case PASS_NONE:
break;
}
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 47059a0a009..ff2afc7119b 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -83,6 +83,9 @@ void Integrator::device_update(Device *device, DeviceScene *dscene)
kintegrator->seed = hash_int(seed);
kintegrator->layer_flag = layer_flag << PATH_RAY_LAYER_SHIFT;
+ kintegrator->use_ambient_occlusion =
+ ((dscene->data.film.pass_flag & PASS_AO) || dscene->data.background.ao_factor != 0.0f);
+
/* sobol directions table */
int dimensions = PRNG_BASE_NUM + (max_bounce + transparent_max_bounce + 2)*PRNG_BOUNCE_NUM;
uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);