diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-01-12 06:02:53 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-01-12 06:02:53 +0400 |
commit | 94ae0232b0337ab70cecaef03cd845887cd36eaa (patch) | |
tree | caea2819c7fe0400fb91c9bdf0e99a9e0fd50cf6 /intern | |
parent | 9a109c22ae1ef8a5c75932d661610b23ec685bd7 (diff) | |
parent | f68e9db583489d541d535791536ea20bc1ae1d76 (diff) |
Merged changes in the trunk up to revision 53729.
Conflicts resolved:
release/datafiles/startup.blend
source/blender/blenloader/intern/readfile.c
Diffstat (limited to 'intern')
33 files changed, 807 insertions, 269 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 2bc4afe969e..8b90b0bd4ff 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -95,6 +95,14 @@ enum_curves_interpolation = ( ('CARDINAL', "Cardinal interpolation", "Use cardinal interpolation between segments"), ('BSPLINE', "B-spline interpolation", "Use b-spline interpolation between segments"), ) + +enum_tile_order = ( + ('CENTER', "Center", "Render from center to the edges"), + ('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"), + ('LEFT_TO_RIGHT', "Left to Right", "Render from left to right"), + ('TOP_TO_BOTTOM', "Top to Bottom", "Render from top to bottom"), + ('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"), + ) class CyclesRenderSettings(bpy.types.PropertyGroup): @classmethod @@ -352,6 +360,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Cache last built BVH to disk for faster re-render if no geometry changed", default=False, ) + cls.tile_order = EnumProperty( + name="Tile Order", + description="Tile order for rendering", + items=enum_tile_order, + default='CENTER', + ) cls.use_progressive_refine = BoolProperty( name="Progressive Refine", description="Instead of rendering each tile until it is finished, " diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 554a9204c7f..6a3a0c63236 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -191,7 +191,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(rd, "threads") sub = col.column(align=True) - sub.label(text="Tile Size:") + sub.label(text="Tiles:") + sub.prop(cscene, "tile_order", text="") sub.prop(rd, "tile_x", text="X") sub.prop(rd, "tile_y", text="Y") diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 4fad7d45162..41e1249dae7 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -330,13 +330,17 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents) { +#if 0 int keyno = 0; +#endif if(!(mesh && b_mesh && b_ob && CData)) return false; +#if 0 Transform tfm = get_transform(b_ob->matrix_world()); Transform itfm = transform_quick_inverse(tfm); +#endif BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { @@ -348,12 +352,13 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) { - +#if 0 int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1); int shader = mesh->used_shaders[mi]; int draw_step = b_psys.settings().draw_step(); int ren_step = (int)pow((float)2.0f,(float)draw_step); - /*b_psys.settings().render_step(draw_step);*/ + b_psys.settings().render_step(draw_step); +#endif int totparts = b_psys.particles.length(); int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100; @@ -397,13 +402,16 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num) { +#if 0 int keyno = 0; - +#endif if(!(mesh && b_mesh && b_ob && CData)) return false; +#if 0 Transform tfm = get_transform(b_ob->matrix_world()); Transform itfm = transform_quick_inverse(tfm); +#endif BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { @@ -415,13 +423,13 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) { - +#if 0 int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1); int shader = mesh->used_shaders[mi]; int draw_step = b_psys.settings().draw_step(); int ren_step = (int)pow((float)2.0f,(float)draw_step); - /*b_psys.settings().render_step(draw_step);*/ - + b_psys.settings().render_step(draw_step); +#endif int totparts = b_psys.particles.length(); int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100; int totcurves = totchild; diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index ad701266c5b..e9bcea70ab6 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -127,8 +127,8 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI case BL::Lamp::type_AREA: { BL::AreaLamp b_area_lamp(b_lamp); light->size = 1.0f; - light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x); - light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y); + light->axisu = transform_get_column(&tfm, 0); + light->axisv = transform_get_column(&tfm, 1); light->sizeu = b_area_lamp.size(); if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE) light->sizev = b_area_lamp.size_y(); @@ -140,8 +140,8 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI } /* location and (inverted!) direction */ - light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w); - light->dir = -make_float3(tfm.x.z, tfm.y.z, tfm.z.z); + light->co = transform_get_column(&tfm, 3); + light->dir = -transform_get_column(&tfm, 2); /* shader */ vector<uint> used_shaders; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 770b71afcdc..d0c7c06cbb3 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -139,6 +139,8 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) session->progress.reset(); scene->reset(); + session->tile_manager.set_tile_order(session_params.tile_order); + /* peak memory usage should show current render peak, not peak for all renders * made by this render session */ diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index b9860ca90f2..a2a8c23404f 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -396,6 +396,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.tile_size = make_int2(tile_x, tile_y); } + + params.tile_order = RNA_enum_get(&cscene, "tile_order"); params.start_resolution = get_int(cscene, "preview_start_resolution"); diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 0071bbe5cdc..661d43ab036 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -18,11 +18,14 @@ set(SRC device_cpu.cpp device_cuda.cpp device_multi.cpp - device_network.cpp device_opencl.cpp device_task.cpp ) +if(WITH_NETWORK) + list(APPEND SRC device_network.cpp) +endif() + set(SRC_HEADERS device.h device_memory.h diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 97d37a8b3f4..cd896ffe133 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -199,7 +199,6 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f)); ray->dD.dy = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y))) - ray->D; - #endif } diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index d5506ad1dd0..54bc0717b60 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -66,6 +66,8 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, else eval = make_float3(0.0f, 0.0f, 0.0f); } + + eval *= ls->eval_fac; shader_release(kg, &sd); @@ -74,29 +76,29 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval, - bool *is_lamp) + int *lamp) { LightSample ls; - float pdf = -1.0f; - #ifdef __NON_PROGRESSIVE__ if(lindex != -1) { /* sample position on a specified light */ - light_select(kg, lindex, randu, randv, sd->P, &ls, &pdf); + light_select(kg, lindex, randu, randv, sd->P, &ls); } else #endif { /* sample a light and position on int */ - light_sample(kg, randt, randu, randv, sd->time, sd->P, &ls, &pdf); + light_sample(kg, randt, randu, randv, sd->time, sd->P, &ls); } - /* compute pdf */ - if(pdf < 0.0f) - pdf = light_sample_pdf(kg, &ls, -ls.D, ls.t); + /* return lamp index for MIS */ + if(ls.use_mis) + *lamp = ls.lamp; + else + *lamp= ~0; - if(pdf == 0.0f) + if(ls.pdf == 0.0f) return false; /* evaluate closure */ @@ -112,13 +114,13 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf); - if(ls.prim != ~0 || ls.type == LIGHT_BACKGROUND) { + if(ls.use_mis) { /* multiple importance sampling */ - float mis_weight = power_heuristic(pdf, bsdf_pdf); + float mis_weight = power_heuristic(ls.pdf, bsdf_pdf); light_eval *= mis_weight; } - bsdf_eval_mul(eval, light_eval*(ls.eval_fac/pdf)); + bsdf_eval_mul(eval, light_eval/ls.pdf); if(bsdf_eval_is_zero(eval)) return false; @@ -144,14 +146,12 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, ray->t = 0.0f; } - *is_lamp = (ls.prim == ~0); - return true; } -/* Indirect Emission */ +/* Indirect Primitive Emission */ -__device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf) +__device float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf) { /* evaluate emissive closure */ float3 L = shader_emissive_eval(kg, sd); @@ -172,6 +172,35 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in return L; } +/* Indirect Lamp Emission */ + +__device bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission) +{ + LightSample ls; + int lamp = lamp_light_eval_sample(kg, randt); + + if(lamp == ~0) + return false; + + if(!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls)) + return false; + + /* todo: missing texture coordinates */ + float u = 0.0f; + float v = 0.0f; + float3 L = direct_emissive_eval(kg, 0.0f, &ls, u, v, -ray->D, ls.t, ray->time); + + if(!(path_flag & PATH_RAY_MIS_SKIP)) { + /* multiple importance sampling, get regular light pdf, + * and compute weight with respect to BSDF pdf */ + float mis_weight = power_heuristic(bsdf_pdf, ls.pdf); + L *= mis_weight; + } + + *emission = L; + return true; +} + /* Indirect Background */ __device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index ea0e4d014fe..e0d0802ae84 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -18,49 +18,27 @@ CCL_NAMESPACE_BEGIN +/* Light Sample result */ + typedef struct LightSample { - float3 P; - float3 D; - float3 Ng; - float t; - float eval_fac; - int object; - int prim; - int shader; - LightType type; + float3 P; /* position on light, or direction for distant light */ + float3 Ng; /* normal on light */ + float3 D; /* direction from shading point to light */ + float t; /* distance to light (FLT_MAX for distant light) */ + float pdf; /* light sampling probability density function */ + float eval_fac; /* intensity multiplier */ + int object; /* object id for triangle/curve lights */ + int prim; /* primitive id for triangle/curve ligths */ + int shader; /* shader id */ + int lamp; /* lamp id */ + int use_mis; /* for lamps with size zero */ + LightType type; /* type of light */ } LightSample; -/* Regular Light */ - -__device float3 disk_light_sample(float3 v, float randu, float randv) -{ - float3 ru, rv; - - make_orthonormals(v, &ru, &rv); - to_unit_disk(&randu, &randv); - - return ru*randu + rv*randv; -} - -__device float3 distant_light_sample(float3 D, float size, float randu, float randv) -{ - return normalize(D + disk_light_sample(D, randu, randv)*size); -} - -__device float3 sphere_light_sample(float3 P, float3 center, float size, float randu, float randv) -{ - return disk_light_sample(normalize(P - center), randu, randv)*size; -} - -__device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv) -{ - randu = randu - 0.5f; - randv = randv - 0.5f; - - return axisu*randu + axisv*randv; -} +/* Background Light */ #ifdef __BACKGROUND_MIS__ + __device float3 background_light_sample(KernelGlobals *kg, float randu, float randv, float *pdf) { /* for the following, the CDF values are actually a pair of floats, with the @@ -169,33 +147,108 @@ __device float background_light_pdf(KernelGlobals *kg, float3 direction) } #endif -__device void regular_light_sample(KernelGlobals *kg, int point, - float randu, float randv, float3 P, LightSample *ls, float *pdf) +/* Regular Light */ + +__device float3 disk_light_sample(float3 v, float randu, float randv) +{ + float3 ru, rv; + + make_orthonormals(v, &ru, &rv); + to_unit_disk(&randu, &randv); + + return ru*randu + rv*randv; +} + +__device float3 distant_light_sample(float3 D, float radius, float randu, float randv) +{ + return normalize(D + disk_light_sample(D, randu, randv)*radius); +} + +__device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv) { - float4 data0 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 0); - float4 data1 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 1); + return disk_light_sample(normalize(P - center), randu, randv)*radius; +} + +__device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv) +{ + randu = randu - 0.5f; + randv = randv - 0.5f; + + return axisu*randu + axisv*randv; +} + +__device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls) +{ + float3 dir = make_float3(data2.y, data2.z, data2.w); + float3 I = ls->Ng; + + float spot_angle = data1.w; + float spot_smooth = data2.x; + + float attenuation = dot(dir, I); + + if(attenuation <= spot_angle) { + attenuation = 0.0f; + } + else { + float t = attenuation - spot_angle; + + if(t < spot_smooth && spot_smooth != 0.0f) + attenuation *= smoothstepf(t/spot_smooth); + } + + return attenuation; +} + +__device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) +{ + float cos_pi = dot(Ng, I); + + if(cos_pi <= 0.0f) + return 0.0f; + + return t*t/cos_pi; +} + +__device void lamp_light_sample(KernelGlobals *kg, int lamp, + float randu, float randv, float3 P, LightSample *ls) +{ + float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0); + float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1); LightType type = (LightType)__float_as_int(data0.x); ls->type = type; +#ifdef __LAMP_MIS__ + ls->use_mis = true; +#else + ls->use_mis = false; +#endif if(type == LIGHT_DISTANT) { /* distant light */ - float3 D = make_float3(data0.y, data0.z, data0.w); - float size = data1.y; + float3 lightD = make_float3(data0.y, data0.z, data0.w); + float3 D = lightD; + float radius = data1.y; + float invarea = data1.w; - if(size > 0.0f) - D = distant_light_sample(D, size, randu, randv); + if(radius > 0.0f) + D = distant_light_sample(D, radius, randu, randv); + else + ls->use_mis = false; ls->P = D; ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; - ls->eval_fac = 1.0f; + + float costheta = dot(lightD, D); + ls->pdf = invarea/(costheta*costheta*costheta); + ls->eval_fac = ls->pdf*kernel_data.integrator.inv_pdf_lights; } #ifdef __BACKGROUND_MIS__ else if(type == LIGHT_BACKGROUND) { /* infinite area light (e.g. light dome or env light) */ - float3 D = background_light_sample(kg, randu, randv, pdf); + float3 D = background_light_sample(kg, randu, randv, &ls->pdf); ls->P = D; ls->Ng = D; @@ -207,127 +260,235 @@ __device void regular_light_sample(KernelGlobals *kg, int point, else { ls->P = make_float3(data0.y, data0.z, data0.w); - if(type == LIGHT_POINT) { - float size = data1.y; - - /* sphere light */ - if(size > 0.0f) - ls->P += sphere_light_sample(P, ls->P, size, randu, randv); + if(type == LIGHT_POINT || type == LIGHT_SPOT) { + float radius = data1.y; - ls->Ng = normalize(P - ls->P); - ls->eval_fac = 0.25f*M_1_PI_F; - } - else if(type == LIGHT_SPOT) { - float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2); - float size = data1.y; - - /* spot light */ - if(size > 0.0f) - ls->P += sphere_light_sample(P, ls->P, size, randu, randv); - - float3 dir = make_float3(data1.z, data1.w, data2.x); - float3 I = normalize(P - ls->P); + if(radius > 0.0f) + /* sphere light */ + ls->P += sphere_light_sample(P, ls->P, radius, randu, randv); + else + ls->use_mis = false; - float spot_angle = data2.y; - float spot_smooth = data2.z; + ls->D = normalize_len(ls->P - P, &ls->t); + ls->Ng = -ls->D; - float eval_fac = dot(dir, I); + float invarea = data1.z; + ls->eval_fac = (0.25f*M_1_PI_F)*invarea; + ls->pdf = invarea; - if(eval_fac <= spot_angle) { - eval_fac = 0.0f; + if(type == LIGHT_SPOT) { + /* spot light attentuation */ + float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); + ls->eval_fac *= spot_light_attenuation(data1, data2, ls); } - else { - float t = eval_fac - spot_angle; - - if(t < spot_smooth && spot_smooth != 0.0f) - eval_fac *= smoothstepf(t/spot_smooth); - } - - ls->Ng = I; - ls->eval_fac = eval_fac*0.25f*M_1_PI_F; } else { /* area light */ - float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2); - float4 data3 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 3); + float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); + float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3); - float3 axisu = make_float3(data1.y, data1.z, data2.w); + float3 axisu = make_float3(data1.y, data1.z, data1.w); float3 axisv = make_float3(data2.y, data2.z, data2.w); float3 D = make_float3(data3.y, data3.z, data3.w); ls->P += area_light_sample(axisu, axisv, randu, randv); ls->Ng = D; - ls->eval_fac = 0.25f; + ls->D = normalize_len(ls->P - P, &ls->t); + + float invarea = data2.x; + + if(invarea == 0.0f) { + ls->use_mis = false; + invarea = 1.0f; + } + + ls->eval_fac = 0.25f*invarea; + ls->pdf = invarea; } - ls->t = 0.0f; + ls->eval_fac *= kernel_data.integrator.inv_pdf_lights; + ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); } ls->shader = __float_as_int(data1.x); ls->object = ~0; ls->prim = ~0; + ls->lamp = lamp; } -__device float regular_light_pdf(KernelGlobals *kg, - const float3 Ng, const float3 I, float t) +__device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls) { - float pdf = kernel_data.integrator.pdf_lights; + float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0); + float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1); - if(t == FLT_MAX) - return pdf; + LightType type = (LightType)__float_as_int(data0.x); + ls->type = type; + ls->shader = __float_as_int(data1.x); + ls->object = ~0; + ls->prim = ~0; + ls->lamp = lamp; + ls->use_mis = false; /* flag not used for eval */ - float cos_pi = dot(Ng, I); + if(type == LIGHT_DISTANT) { + /* distant light */ + float radius = data1.y; + + if(radius == 0.0f) + return false; + if(t != FLT_MAX) + return false; + + /* a distant light is infinitely far away, but equivalent to a disk + * shaped light exactly 1 unit away from the current shading point. + * + * radius t^2/cos(theta) + * <----------> t = sqrt(1^2 + tan(theta)^2) + * tan(th) area = radius*radius*pi + * <-----> + * \ | (1 + tan(theta)^2)/cos(theta) + * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta) + * t \th| 1 simplifies to + * \-| 1/(cos(theta)^3) + * \| magic! + * P + */ + + float3 lightD = make_float3(data0.y, data0.z, data0.w); + float costheta = dot(-lightD, D); + float cosangle = data1.z; + + if(costheta < cosangle) + return false; + + ls->P = -D; + ls->Ng = -D; + ls->D = D; + ls->t = FLT_MAX; - if(cos_pi <= 0.0f) - return 0.0f; + float invarea = data1.w; + ls->pdf = invarea/(costheta*costheta*costheta); + ls->eval_fac = ls->pdf; + } + else if(type == LIGHT_POINT || type == LIGHT_SPOT) { + float3 lightP = make_float3(data0.y, data0.z, data0.w); + float radius = data1.y; - return t*t*pdf/cos_pi; + /* sphere light */ + if(radius == 0.0f) + return false; + + if(!ray_aligned_disk_intersect(P, D, t, + lightP, radius, &ls->P, &ls->t)) + return false; + + ls->Ng = -D; + ls->D = D; + + float invarea = data1.z; + ls->eval_fac = (0.25f*M_1_PI_F)*invarea; + ls->pdf = invarea; + + if(type == LIGHT_SPOT) { + /* spot light attentuation */ + float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); + ls->eval_fac *= spot_light_attenuation(data1, data2, ls); + + if(ls->eval_fac == 0.0f) + return false; + } + } + else if(type == LIGHT_AREA) { + /* area light */ + float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); + float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3); + + float invarea = data2.x; + if(invarea == 0.0f) + return false; + + float3 axisu = make_float3(data1.y, data1.z, data1.w); + float3 axisv = make_float3(data2.y, data2.z, data2.w); + float3 Ng = make_float3(data3.y, data3.z, data3.w); + + /* one sided */ + if(dot(D, Ng) >= 0.0f) + return false; + + ls->P = make_float3(data0.y, data0.z, data0.w); + + if(!ray_quad_intersect(P, D, t, + ls->P, axisu, axisv, &ls->P, &ls->t)) + return false; + + ls->D = D; + ls->Ng = Ng; + ls->pdf = invarea; + ls->eval_fac = 0.25f*ls->pdf; + } + else + return false; + + /* compute pdf */ + if(ls->t != FLT_MAX) + ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); + ls->eval_fac *= kernel_data.integrator.inv_pdf_lights; + + return true; } /* Triangle Light */ -__device void triangle_light_sample(KernelGlobals *kg, int prim, int object, - float randu, float randv, float time, LightSample *ls) +__device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls, int object, float time) { - /* triangle, so get position, normal, shader */ - ls->P = triangle_sample_MT(kg, prim, randu, randv); - ls->Ng = triangle_normal_MT(kg, prim, &ls->shader); - ls->object = object; - ls->prim = prim; - ls->t = 0.0f; - ls->type = LIGHT_AREA; - ls->eval_fac = 1.0f; - #ifdef __INSTANCING__ /* instance transform */ - if(ls->object >= 0) { + if(object >= 0) { #ifdef __OBJECT_MOTION__ Transform itfm; Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); #else - Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM); - Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif ls->P = transform_point(&tfm, ls->P); - ls->Ng = normalize(transform_direction_transposed(&itfm, ls->Ng)); + ls->Ng = normalize(transform_direction(&tfm, ls->Ng)); } #endif } +__device void triangle_light_sample(KernelGlobals *kg, int prim, int object, + float randu, float randv, float time, LightSample *ls) +{ + /* triangle, so get position, normal, shader */ + ls->P = triangle_sample_MT(kg, prim, randu, randv); + ls->Ng = triangle_normal_MT(kg, prim, &ls->shader); + ls->object = object; + ls->prim = prim; + ls->lamp = ~0; + ls->use_mis = true; + ls->t = 0.0f; + ls->type = LIGHT_AREA; + ls->eval_fac = 1.0f; + + object_transform_light_sample(kg, ls, object, time); +} + __device float triangle_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) { + float pdf = kernel_data.integrator.pdf_triangles; float cos_pi = fabsf(dot(Ng, I)); if(cos_pi == 0.0f) return 0.0f; - return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi; + return t*t*pdf/cos_pi; } +/* Curve Light */ + #ifdef __HAIR__ -/* Strand Light */ __device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object, int segment, float randu, float randv, float time, LightSample *ls) @@ -358,27 +519,16 @@ __device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object ls->P = randu * l * tg + (gd * l + r1) * ls->Ng; ls->object = object; ls->prim = prim; + ls->lamp = ~0; + ls->use_mis = true; ls->t = 0.0f; ls->type = LIGHT_STRAND; ls->eval_fac = 1.0f; ls->shader = __float_as_int(v00.z); -#ifdef __INSTANCING__ - /* instance transform */ - if(ls->object >= 0) { -#ifdef __OBJECT_MOTION__ - Transform itfm; - Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); -#else - Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM); - Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM); -#endif - - ls->P = transform_point(&tfm, ls->P); - ls->Ng = normalize(transform_direction(&tfm, ls->Ng)); - } -#endif + object_transform_light_sample(kg, ls, object, time); } + #endif /* Light Distribution */ @@ -412,7 +562,7 @@ __device int light_distribution_sample(KernelGlobals *kg, float randt) /* Generic Light */ -__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls, float *pdf) +__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls) { /* sample index */ int index = light_distribution_sample(kg, randt); @@ -420,12 +570,12 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra /* fetch light data */ float4 l = kernel_tex_fetch(__light_distribution, index); int prim = __float_as_int(l.y); -#ifdef __HAIR__ - int segment = __float_as_int(l.z); -#endif if(prim >= 0) { int object = __float_as_int(l.w); +#ifdef __HAIR__ + int segment = __float_as_int(l.z); +#endif #ifdef __HAIR__ if (segment != ~0) @@ -433,27 +583,15 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra else #endif triangle_light_sample(kg, prim, object, randu, randv, time, ls); + + /* compute incoming direction, distance and pdf */ + ls->D = normalize_len(ls->P - P, &ls->t); + ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t); } else { - int point = -prim-1; - regular_light_sample(kg, point, randu, randv, P, ls, pdf); + int lamp = -prim-1; + lamp_light_sample(kg, lamp, randu, randv, P, ls); } - - /* compute incoming direction and distance */ - if(ls->t != FLT_MAX) - ls->D = normalize_len(ls->P - P, &ls->t); -} - -__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t) -{ - float pdf; - - if(ls->prim != ~0) - pdf = triangle_light_pdf(kg, ls->Ng, I, t); - else - pdf = regular_light_pdf(kg, ls->Ng, I, t); - - return pdf; } __device int light_select_num_samples(KernelGlobals *kg, int index) @@ -462,18 +600,26 @@ __device int light_select_num_samples(KernelGlobals *kg, int index) return __float_as_int(data3.x); } -__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls, float *pdf) +__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls) { - regular_light_sample(kg, index, randu, randv, P, ls, pdf); - - /* compute incoming direction and distance */ - if(ls->t != FLT_MAX) - ls->D = normalize_len(ls->P - P, &ls->t); + lamp_light_sample(kg, index, randu, randv, P, ls); } -__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t) +__device int lamp_light_eval_sample(KernelGlobals *kg, float randt) { - return regular_light_pdf(kg, ls->Ng, I, t); + /* sample index */ + int index = light_distribution_sample(kg, randt); + + /* fetch light data */ + float4 l = kernel_tex_fetch(__light_distribution, index); + int prim = __float_as_int(l.y); + + if(prim < 0) { + int lamp = -prim-1; + return lamp; + } + else + return ~0; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 20feaf50a2e..532c32896d9 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -238,6 +238,9 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, float min_ray_pdf = FLT_MAX; float ray_pdf = 0.0f; +#ifdef __LAMP_MIS__ + float ray_t = 0.0f; +#endif PathState state; int rng_offset = PRNG_BASE_NUM; @@ -248,8 +251,29 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* intersect scene */ Intersection isect; uint visibility = path_state_ray_visibility(kg, &state); + bool hit = scene_intersect(kg, &ray, visibility, &isect); - if(!scene_intersect(kg, &ray, visibility, &isect)) { +#ifdef __LAMP_MIS__ + if(kernel_data.integrator.pdf_lights > 0.0f && !(state.flag & PATH_RAY_CAMERA)) { + /* ray starting from previous non-transparent bounce */ + Ray light_ray; + + light_ray.P = ray.P - ray_t*ray.D; + ray_t += isect.t; + light_ray.D = ray.D; + light_ray.t = ray_t; + light_ray.time = ray.time; + + /* intersect with lamp */ + float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT); + float3 emission; + + if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission)) + path_radiance_accum_emission(&L, throughput, emission, state.bounce); + } +#endif + + if(!hit) { /* eval background shader if nothing hit */ if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) { L_transparent += average(throughput); @@ -313,7 +337,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __EMISSION__ /* emission */ if(sd.flag & SD_EMISSION) { - float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf); + /* todo: is isect.t wrong here for transparent surfaces? */ + float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf); path_radiance_accum_emission(&L, throughput, emission, state.bounce); } #endif @@ -374,18 +399,19 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray; BsdfEval L_light; - bool is_lamp; + int lamp; #ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif - if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &lamp)) { /* trace shadow ray */ float3 shadow; if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { /* accumulate */ + bool is_lamp = (lamp != ~0); path_radiance_accum_light(&L, throughput, &L_light, shadow, state.bounce, is_lamp); } } @@ -422,6 +448,9 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* set labels */ if(!(label & LABEL_TRANSPARENT)) { ray_pdf = bsdf_pdf; +#ifdef __LAMP_MIS__ + ray_t = 0.0f; +#endif min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf); } @@ -457,15 +486,41 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __NON_PROGRESSIVE__ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer, - float3 throughput, float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L) + float3 throughput, float throughput_normalize, + float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L) { +#ifdef __LAMP_MIS__ + float ray_t = 0.0f; +#endif + /* path iteration */ for(;; rng_offset += PRNG_BOUNCE_NUM) { /* intersect scene */ Intersection isect; uint visibility = path_state_ray_visibility(kg, &state); + bool hit = scene_intersect(kg, &ray, visibility, &isect); - if(!scene_intersect(kg, &ray, visibility, &isect)) { +#ifdef __LAMP_MIS__ + if(kernel_data.integrator.pdf_lights > 0.0f && !(state.flag & PATH_RAY_CAMERA)) { + /* ray starting from previous non-transparent bounce */ + Ray light_ray; + + light_ray.P = ray.P - ray_t*ray.D; + ray_t += isect.t; + light_ray.D = ray.D; + light_ray.t = ray_t; + light_ray.time = ray.time; + + /* intersect with lamp */ + float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT); + float3 emission; + + if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission)) + path_radiance_accum_emission(L, throughput, emission, state.bounce); + } +#endif + + if(!hit) { #ifdef __BACKGROUND__ /* sample background shader */ float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf); @@ -496,7 +551,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #ifdef __EMISSION__ /* emission */ if(sd.flag & SD_EMISSION) { - float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf); + float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf); path_radiance_accum_emission(L, throughput, emission, state.bounce); } #endif @@ -504,7 +559,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray /* path termination. this is a strange place to put the termination, it's * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate */ - float probability = path_state_terminate_probability(kg, &state, throughput); + float probability = path_state_terminate_probability(kg, &state, throughput*throughput_normalize); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); if(terminate >= probability) { @@ -557,19 +612,20 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray Ray light_ray; BsdfEval L_light; - bool is_lamp; + int lamp; #ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif /* sample random light */ - if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &lamp)) { /* trace shadow ray */ float3 shadow; if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { /* accumulate */ + bool is_lamp = (lamp != ~0); path_radiance_accum_light(L, throughput, &L_light, shadow, state.bounce, is_lamp); } } @@ -606,6 +662,9 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray /* set labels */ if(!(label & LABEL_TRANSPARENT)) { ray_pdf = bsdf_pdf; +#ifdef __LAMP_MIS__ + ray_t = 0.0f; +#endif min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf); } @@ -697,7 +756,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam #ifdef __EMISSION__ /* emission */ if(sd.flag & SD_EMISSION) { - float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf); + float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf); path_radiance_accum_emission(&L, throughput, emission, state.bounce); } #endif @@ -760,7 +819,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam if(sd.flag & SD_BSDF_HAS_EVAL) { Ray light_ray; BsdfEval L_light; - bool is_lamp; + int lamp; #ifdef __OBJECT_MOTION__ light_ray.time = sd.time; @@ -778,12 +837,13 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U); float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V); - if(direct_emission(kg, &sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &lamp)) { /* trace shadow ray */ float3 shadow; if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { /* accumulate */ + bool is_lamp = (lamp != ~0); path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp); } } @@ -807,12 +867,13 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam if(kernel_data.integrator.num_all_lights) light_t = 0.5f*light_t; - if(direct_emission(kg, &sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + if(direct_emission(kg, &sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &lamp)) { /* trace shadow ray */ float3 shadow; if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { /* accumulate */ + bool is_lamp = (lamp != ~0); path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp); } } @@ -885,8 +946,9 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam bsdf_ray.time = sd.time; #endif - kernel_path_indirect(kg, rng, sample*num_samples, bsdf_ray, buffer, - tp*num_samples_inv, min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L); + kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer, + tp*num_samples_inv, num_samples, + min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L); } } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 2bd6b5859f3..102be440978 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -48,6 +48,7 @@ CCL_NAMESPACE_BEGIN #endif #define __NON_PROGRESSIVE__ #define __HAIR__ +#define __LAMP_MIS__ #endif #ifdef __KERNEL_CUDA__ @@ -384,7 +385,7 @@ typedef enum AttributeStandard { /* Closure data */ -#define MAX_CLOSURE 8 +#define MAX_CLOSURE 16 typedef struct ShaderClosure { ClosureType type; @@ -636,6 +637,7 @@ typedef struct KernelIntegrator { int num_all_lights; float pdf_triangles; float pdf_lights; + float inv_pdf_lights; int pdf_background_res; /* bounces */ @@ -671,7 +673,7 @@ typedef struct KernelIntegrator { int transmission_samples; int ao_samples; int mesh_light_samples; - int pad1, pad2; + int pad1; } KernelIntegrator; typedef struct KernelBVH { diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 28742d56e3b..92a023bd765 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -605,7 +605,11 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD return set_attribute_int(3, type, derivatives, val); } else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) +#ifdef __HAIR__ && sd->segment == ~0) { +#else + ) { +#endif float3 P[3]; triangle_vertices(kg, sd->prim, P); @@ -675,7 +679,11 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri else { object = sd->object; prim = sd->prim; +#ifdef __HAIR__ segment = sd->segment; +#else + segment = ~0; +#endif if (object == ~0) return get_background_attribute(kg, sd, name, type, derivatives, val); diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 59e307bb408..a32c526a2be 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -457,7 +457,11 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem) { /* for OSL, a hash map is used to lookup the attribute by name. */ - int object = sd->object*ATTR_PRIM_TYPES + (sd->segment != ~0); + int object = sd->object*ATTR_PRIM_TYPES; +#ifdef __HAIR__ + if(sd->segment != ~0) object += ATTR_PRIM_CURVE; +#endif + OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object]; ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id))); OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 541f26b4e56..38232ea0aeb 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -37,14 +37,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float int i; for (i = 0; i < (int)octaves; i++) { - value += noise("perlin", p) * pwr; + value += safe_noise(p) * pwr; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) - value += rmd * noise("perlin", p) * pwr; + value += rmd * safe_noise(p) * pwr; return value; } @@ -65,14 +65,14 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar int i; for (i = 0; i < (int)octaves; i++) { - value *= (pwr * noise("perlin", p) + 1.0); + value *= (pwr * safe_noise(p) + 1.0); pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) - value *= (rmd * pwr * noise("perlin", p) + 1.0); /* correct? */ + value *= (rmd * pwr * safe_noise(p) + 1.0); /* correct? */ return value; } @@ -93,11 +93,11 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna int i; /* first unscaled octave of function; later octaves are scaled */ - value = offset + noise("perlin", p); + value = offset + safe_noise(p); p *= lacunarity; for (i = 1; i < (int)octaves; i++) { - increment = (noise("perlin", p) + offset) * pwr * value; + increment = (safe_noise(p) + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; @@ -105,7 +105,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna rmd = octaves - floor(octaves); if (rmd != 0.0) { - increment = (noise("perlin", p) + offset) * pwr * value; + increment = (safe_noise(p) + offset) * pwr * value; value += rmd * increment; } @@ -128,7 +128,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float pwr = pwHL; int i; - result = noise("perlin", p) + offset; + result = safe_noise(p) + offset; weight = gain * result; p *= lacunarity; @@ -136,7 +136,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, if (weight > 1.0) weight = 1.0; - signal = (noise("perlin", p) + offset) * pwr; + signal = (safe_noise(p) + offset) * pwr; pwr *= pwHL; result += weight * signal; weight *= gain * signal; @@ -145,7 +145,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, rmd = octaves - floor(octaves); if (rmd != 0.0) - result += rmd * ((noise("perlin", p) + offset) * pwr); + result += rmd * ((safe_noise(p) + offset) * pwr); return result; } @@ -166,7 +166,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float pwr = pwHL; int i; - signal = offset - fabs(noise("perlin", p)); + signal = offset - fabs(safe_noise(p)); signal *= signal; result = signal; weight = 1.0; @@ -174,7 +174,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, for (i = 1; i < (int)octaves; i++) { p *= lacunarity; weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - fabs(noise("perlin", p)); + signal = offset - fabs(safe_noise(p)); signal *= signal; signal *= weight; result += signal * pwr; diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h index 1b3ba8207ab..2de0fc0ea57 100644 --- a/intern/cycles/kernel/shaders/node_texture.h +++ b/intern/cycles/kernel/shaders/node_texture.h @@ -151,12 +151,23 @@ float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; } /* Noise Bases */ +float safe_noise(point p) +{ + float f = noise(p); + + /* can happen for big coordinates, things even out to 0.5 then anyway */ + if(!isfinite(f)) + return 0.5; + + return f; +} + float noise_basis(point p, string basis) { float result = 0.0; if (basis == "Perlin") - result = noise(p); /* returns perlin noise in range 0..1 */ + result = safe_noise(p); /* returns perlin noise in range 0..1 */ if (basis == "Voronoi F1") result = voronoi_F1S(p); if (basis == "Voronoi F2") diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index 224a1d96543..5ead6486dd6 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -84,9 +84,8 @@ __device uint phash(int kx, int ky, int kz, int3 p) __device float floorfrac(float x, int* i) { - float f = floorf(x); - *i = (int)f; - return x - f; + *i = quick_floor(x); + return x - *i; } __device float fade(float t) @@ -133,7 +132,10 @@ __device_noinline float perlin(float x, float y, float z) grad (hash (X+1, Y , Z+1), fx-1.0f, fy , fz-1.0f )), nerp (u, grad (hash (X , Y+1, Z+1), fx , fy-1.0f, fz-1.0f ), grad (hash (X+1, Y+1, Z+1), fx-1.0f, fy-1.0f, fz-1.0f )))); - return scale3(result); + float r = scale3(result); + + /* can happen for big coordinates, things even out to 0.0 then anyway */ + return (isfinite(r))? r: 0.0f; } __device_noinline float perlin_periodic(float x, float y, float z, float3 pperiod) @@ -162,7 +164,10 @@ __device_noinline float perlin_periodic(float x, float y, float z, float3 pperio grad (phash (X+1, Y , Z+1, p), fx-1.0f, fy , fz-1.0f )), nerp (u, grad (phash (X , Y+1, Z+1, p), fx , fy-1.0f, fz-1.0f ), grad (phash (X+1, Y+1, Z+1, p), fx-1.0f, fy-1.0f, fz-1.0f )))); - return scale3(result); + float r = scale3(result); + + /* can happen for big coordinates, things even out to 0.0 then anyway */ + return (isfinite(r))? r: 0.0f; } /* perlin noise in range 0..1 */ diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index c8e3e94ec98..1b94d603a26 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -323,6 +323,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* precompute pdfs */ kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; + kintegrator->inv_pdf_lights = 0.0f; /* sample one, with 0.5 probability of light or triangle */ kintegrator->num_all_lights = num_lights; @@ -337,6 +338,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen kintegrator->pdf_lights = 1.0f/num_lights; if(trianglearea > 0.0f) kintegrator->pdf_lights *= 0.5f; + + kintegrator->inv_pdf_lights = 1.0f/kintegrator->pdf_lights; } /* CDF */ @@ -349,6 +352,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen kintegrator->num_all_lights = 0; kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; + kintegrator->inv_pdf_lights = 0.0f; } } @@ -475,16 +479,25 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(light->type == LIGHT_POINT) { shader_id &= ~SHADER_AREA_LIGHT; + float radius = light->size; + float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f; + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f); + light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_DISTANT) { shader_id &= ~SHADER_AREA_LIGHT; + float radius = light->size; + float angle = atanf(radius); + float cosangle = cosf(angle); + float area = M_PI_F*radius*radius; + float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f); + light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); } @@ -499,21 +512,25 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce else if(light->type == LIGHT_AREA) { float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); + float area = len(axisu)*len(axisv); + float invarea = (area > 0.0f)? 1.0f/area: 0.0f; light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); - light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z); + light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z); } else if(light->type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; + float radius = light->size; + float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f; float spot_angle = cosf(light->spot_angle*0.5f); float spot_smooth = (1.0f - spot_angle)*light->spot_smooth; light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, dir.x, dir.y); - light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f); + light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); + light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); } } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 36948adce17..e49a4a3ed34 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -41,7 +41,7 @@ CCL_NAMESPACE_BEGIN Session::Session(const SessionParams& params_) : params(params_), tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution, - params.background == false || params.progressive_refine, params.background, + params.background == false || params.progressive_refine, params.background, params.tile_order, max(params.device.multi_devices.size(), 1)), stats() { diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index cfc1502287d..27073d2fd9c 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -51,6 +51,7 @@ public: bool experimental; int samples; int2 tile_size; + int tile_order; int start_resolution; int threads; diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index bbcdb47260e..d62ecd8a88c 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -24,10 +24,11 @@ CCL_NAMESPACE_BEGIN TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, - bool preserve_tile_device_, bool background_, int num_devices_) + bool preserve_tile_device_, bool background_, int tile_order_, int num_devices_) { progressive = progressive_; tile_size = tile_size_; + tile_order = tile_order_; start_resolution = start_resolution_; num_devices = num_devices_; preserve_tile_device = preserve_tile_device_; @@ -165,6 +166,20 @@ void TileManager::set_tiles() state.buffer.full_height = max(1, params.full_height/resolution); } +list<Tile>::iterator TileManager::next_viewport_tile(int device) +{ + list<Tile>::iterator iter; + + int logical_device = preserve_tile_device? device: 0; + + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { + if(iter->device == logical_device && iter->rendering == false) + return iter; + } + + return state.tiles.end(); +} + list<Tile>::iterator TileManager::next_center_tile(int device) { list<Tile>::iterator iter, best = state.tiles.end(); @@ -210,28 +225,53 @@ list<Tile>::iterator TileManager::next_center_tile(int device) return best; } -list<Tile>::iterator TileManager::next_simple_tile(int device) +list<Tile>::iterator TileManager::next_simple_tile(int device, int tile_order) { - list<Tile>::iterator iter; + list<Tile>::iterator iter, best = state.tiles.end(); + int resolution = state.resolution_divider; int logical_device = preserve_tile_device? device: 0; + int64_t cordx = max(1, params.width/resolution); + int64_t cordy = max(1, params.height/resolution); + int64_t mindist = cordx * cordy; + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { - if(iter->device == logical_device && iter->rendering == false) - return iter; + if(iter->device == logical_device && iter->rendering == false) { + Tile &cur_tile = *iter; + + int64_t distx = cordx; + + if (tile_order == TileManager::RIGHT_TO_LEFT) + distx = cordx - cur_tile.x; + else if (tile_order == TileManager::LEFT_TO_RIGHT) + distx = cordx + cur_tile.x; + else if (tile_order == TileManager::TOP_TO_BOTTOM) + distx = cordx - cur_tile.y; + else /* TileManager::BOTTOM_TO_TOP */ + distx = cordx + cur_tile.y; + + if(distx < mindist) { + best = iter; + mindist = distx; + } + } } - return state.tiles.end(); + return best; } bool TileManager::next_tile(Tile& tile, int device) { list<Tile>::iterator tile_it; - - if(background) - tile_it = next_center_tile(device); + if (background) { + if(tile_order == TileManager::CENTER) + tile_it = next_center_tile(device); + else + tile_it = next_simple_tile(device, tile_order); + } else - tile_it = next_simple_tile(device); + tile_it = next_viewport_tile(device); if(tile_it != state.tiles.end()) { tile_it->rendering = true; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 6f7a8f20734..99cffb49c08 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -59,7 +59,7 @@ public: } state; TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, - bool preserve_tile_device, bool background, int num_devices = 1); + bool preserve_tile_device, bool background, int tile_order, int num_devices = 1); ~TileManager(); void reset(BufferParams& params, int num_samples); @@ -68,12 +68,23 @@ public: bool next_tile(Tile& tile, int device = 0); bool done(); + void set_tile_order(int tile_order_) { tile_order = tile_order_; } protected: + /* Note: this should match enum_tile_order in properties.py */ + enum { + CENTER = 0, + RIGHT_TO_LEFT = 1, + LEFT_TO_RIGHT = 2, + TOP_TO_BOTTOM = 3, + BOTTOM_TO_TOP = 4 + } TileOrder; + void set_tiles(); bool progressive; int num_samples; int2 tile_size; + int tile_order; int start_resolution; int num_devices; @@ -106,9 +117,12 @@ protected: * mimics behavior of blender internal's tile order */ list<Tile>::iterator next_center_tile(int device); + + /* returns simple tile order */ + list<Tile>::iterator next_simple_tile(int device, int tile_order); - /* returns first unhandled tile starting from left bottom corner of the image */ - list<Tile>::iterator next_simple_tile(int device); + /* returns first unhandled tile (for viewport) */ + list<Tile>::iterator next_viewport_tile(int device); }; CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 8932c85db07..c37fa1a4dc6 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1161,6 +1161,130 @@ __device float safe_divide(float a, float b) return result; } +/* Ray Intersection */ + +__device bool ray_sphere_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 sphere_P, float sphere_radius, + float3 *isect_P, float *isect_t) +{ + float3 d = sphere_P - ray_P; + float radiussq = sphere_radius*sphere_radius; + float tsq = dot(d, d); + + if(tsq > radiussq) { /* ray origin outside sphere */ + float tp = dot(d, ray_D); + + if(tp < 0.0f) /* dir points away from sphere */ + return false; + + float dsq = tsq - tp*tp; /* pythagoras */ + + if(dsq > radiussq) /* closest point on ray outside sphere */ + return false; + + float t = tp - sqrtf(radiussq - dsq); /* pythagoras */ + + if(t < ray_t) { + *isect_t = t; + *isect_P = ray_P + ray_D*t; + return true; + } + } + + return false; +} + +__device bool ray_aligned_disk_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 disk_P, float disk_radius, + float3 *isect_P, float *isect_t) +{ + /* aligned disk normal */ + float disk_t; + float3 disk_N = normalize_len(ray_P - disk_P, &disk_t); + float div = dot(ray_D, disk_N); + + if(div == 0.0f) + return false; + + /* compute t to intersection point */ + float t = -disk_t/div; + if(t < 0.0f || t > ray_t) + return false; + + /* test if within radius */ + float3 P = ray_P + ray_D*t; + if(len_squared(P - disk_P) > disk_radius*disk_radius) + return false; + + *isect_P = P; + *isect_t = t; + + return true; +} + +__device bool ray_triangle_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 v0, float3 v1, float3 v2, + float3 *isect_P, float *isect_t) +{ + /* Calculate intersection */ + float3 e1 = v1 - v0; + float3 e2 = v2 - v0; + float3 s1 = cross(ray_D, e2); + + const float divisor = dot(s1, e1); + if(divisor == 0.0f) + return false; + + const float invdivisor = 1.0f/divisor; + + /* compute first barycentric coordinate */ + const float3 d = ray_P - v0; + const float u = dot(d, s1)*invdivisor; + if(u < 0.0f) + return false; + + /* Compute second barycentric coordinate */ + const float3 s2 = cross(d, e1); + const float v = dot(ray_D, s2)*invdivisor; + if(v < 0.0f) + return false; + + const float b0 = 1.0f - u - v; + if(b0 < 0.0f) + return false; + + /* compute t to intersection point */ + const float t = dot(e2, s2)*invdivisor; + if(t < 0.0f || t > ray_t) + return false; + + *isect_t = t; + *isect_P = ray_P + ray_D*t; + + return true; +} + +__device bool ray_quad_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 quad_P, float3 quad_u, float3 quad_v, + float3 *isect_P, float *isect_t) +{ + float3 v0 = quad_P - quad_u*0.5f - quad_v*0.5f; + float3 v1 = quad_P + quad_u*0.5f - quad_v*0.5f; + float3 v2 = quad_P + quad_u*0.5f + quad_v*0.5f; + float3 v3 = quad_P - quad_u*0.5f + quad_v*0.5f; + + if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v1, v2, isect_P, isect_t)) + return true; + else if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v2, v3, isect_P, isect_t)) + return true; + + return false; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 2d9d89d9ad0..ac3e22368bc 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -574,13 +574,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() rstring = (char*)malloc( len ); sysctl( mib, 2, rstring, &len, NULL, 0 ); - //Hack on MacBook revision, as multitouch avail. function missing - //MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1) - if (strstr(rstring,"MacBookAir") || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9'))) - m_hasMultiTouchTrackpad = true; - else m_hasMultiTouchTrackpad = false; + m_hasMultiTouchTrackpad = false; free( rstring ); rstring = NULL; @@ -1445,6 +1439,27 @@ bool GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) } +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +enum { + NSEventPhaseNone = 0, + NSEventPhaseBegan = 0x1 << 0, + NSEventPhaseStationary = 0x1 << 1, + NSEventPhaseChanged = 0x1 << 2, + NSEventPhaseEnded = 0x1 << 3, + NSEventPhaseCancelled = 0x1 << 4, +}; +typedef NSUInteger NSEventPhase; + +@interface NSEvent (AvailableOn1070AndLater) +- (BOOL)hasPreciseScrollingDeltas; +- (CGFloat)scrollingDeltaX; +- (CGFloat)scrollingDeltaY; +- (NSEventPhase)momentumPhase; +- (BOOL)isDirectionInvertedFromDevice; +- (NSEventPhase)phase; +@end +#endif + GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; @@ -1577,15 +1592,23 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } break; + /* these events only happen on swiping trackpads */ + case NSEventTypeBeginGesture: + m_hasMultiTouchTrackpad = 1; + break; + case NSEventTypeEndGesture: + m_hasMultiTouchTrackpad = 0; + break; + case NSScrollWheel: { - int momentum = 0; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 - m_hasMultiTouchTrackpad = 0; - momentum = [event momentumPhase] || [event phase]; -#endif - /* standard scrollwheel case */ - if (!m_hasMultiTouchTrackpad && momentum == 0) { + int *momentum = NULL; + + if ([event respondsToSelector:@selector(momentumPhase)]) + momentum = (int *)[event momentumPhase]; + + /* standard scrollwheel case, if no swiping happened, and no momentum (kinetic scroll) works */ + if (!m_hasMultiTouchTrackpad && momentum == NULL) { GHOST_TInt32 delta; double deltaF = [event deltaY]; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 9f62ed76735..75d606a5d79 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -761,6 +761,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_ if (type == GHOST_kEventWindowActivate) { system->getWindowManager()->setActiveWindow(window); + ((GHOST_WindowWin32*)window)->bringTabletContextToFront(); } return new GHOST_Event(system->getMilliSeconds(), type, window); diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 2d3cc4f88dc..f5cb0d9323c 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -132,7 +132,7 @@ GHOST_SystemX11( GHOST_ASSERT(false, "Could not instantiate timer!"); } - /* Taking care not to overflow the tv.tv_sec*1000 */ + /* Taking care not to overflow the tv.tv_sec * 1000 */ m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000; @@ -190,7 +190,7 @@ getMilliSeconds() const GHOST_ASSERT(false, "Could not compute time!"); } - /* Taking care not to overflow the tv.tv_sec*1000 */ + /* Taking care not to overflow the tv.tv_sec * 1000 */ return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time; } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 2d58f0612ce..e89dd1b41dc 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -428,6 +428,14 @@ extern "C" { #pragma mark initialization / finalization +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +@interface NSView (NSOpenGLSurfaceResolution) +- (BOOL)wantsBestResolutionOpenGLSurface; +- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag; +- (NSRect)convertRectToBacking:(NSRect)bounds; +@end +#endif + NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil; GHOST_WindowCocoa::GHOST_WindowCocoa( @@ -579,13 +587,15 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( setDrawingContextType(type); updateDrawingContext(); activateDrawingContext(); -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 // retina support started with 10.7.4 afaik + if (m_systemCocoa->m_nativePixel) { - [m_openGLView setWantsBestResolutionOpenGLSurface:YES]; - NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]]; - m_systemCocoa->m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width; + if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) { + [m_openGLView setWantsBestResolutionOpenGLSurface:YES]; + + NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]]; + m_systemCocoa->m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width; + } } -#endif m_tablet.Active = GHOST_kTabletModeNone; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index fead1884f8a..bf429527199 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -1192,6 +1192,16 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) } } +void GHOST_WindowWin32::bringTabletContextToFront() +{ + if (m_wintab) { + GHOST_WIN32_WTOverlap fpWTOverlap = (GHOST_WIN32_WTOverlap) ::GetProcAddress(m_wintab, "WTOverlap"); + if (fpWTOverlap) { + fpWTOverlap(m_tablet, TRUE); + } + } +} + /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 9e4377b8225..7f50d58ce35 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -58,6 +58,7 @@ typedef UINT (API * GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID); typedef HCTX (API * GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL); typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX); typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); +typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL); /** * GHOST window on M$ Windows OSs. @@ -273,6 +274,7 @@ public: void processWin32TabletInitEvent(); void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); + void bringTabletContextToFront(); protected: GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd); diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 44c02d1442b..d01d8d4c8f4 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -331,7 +331,7 @@ void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *) } OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) + long chanStrideBytes, long xStrideBytes, long yStrideBytes) { OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription), "OCIO_PackedImageDescription"); diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 18fa4b7cb1b..4f839a61fad 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -238,12 +238,12 @@ void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) } OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) + long chanStrideBytes, long xStrideBytes, long yStrideBytes) { return impl->createOCIO_PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); } -void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id) +void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id) { impl->OCIO_PackedImageDescRelease(id); } diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 0ce5f8a1456..19fd8fe643b 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -105,9 +105,9 @@ void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_Const void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes); + long chanStrideBytes, long xStrideBytes, long yStrideBytes); -void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); +void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void); void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 2d73d2ff56b..b073a038f0d 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -479,7 +479,7 @@ void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) } OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) + long chanStrideBytes, long xStrideBytes, long yStrideBytes) { try { void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); |