diff options
Diffstat (limited to 'intern')
78 files changed, 1078 insertions, 258 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 576c048288e..8d4045b1ff4 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -65,6 +65,10 @@ if(WITH_CYCLES) add_subdirectory(cycles) endif() +if(WITH_INTERNATIONAL) + add_subdirectory(locale) +endif() + if(WITH_INPUT_TOUCH) add_subdirectory(touch) endif() diff --git a/intern/SConscript b/intern/SConscript index 59e412333b0..5360ce4ea88 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -30,6 +30,9 @@ if env['WITH_BF_CYCLES']: if env['WITH_BF_BOOLEAN']: SConscript(['bsp/SConscript']) +if env['WITH_BF_INTERNATIONAL']: + SConscript(['locale/SConscript']) + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): SConscript(['utfconv/SConscript']) diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h index da52c7e0fb2..3291c1ad03a 100644 --- a/intern/audaspace/intern/AUD_FileWriter.h +++ b/intern/audaspace/intern/AUD_FileWriter.h @@ -64,8 +64,8 @@ public: * Writes a reader to a writer. * \param reader The reader to read from. * \param writer The writer to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_IWriter> writer, unsigned int length, unsigned int buffersize); @@ -73,8 +73,8 @@ public: * Writes a reader to several writers. * \param reader The reader to read from. * \param writers The writers to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr<AUD_IReader> reader, std::vector<boost::shared_ptr<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize); }; diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 7495a98aed1..2a1eddcec27 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -21,8 +21,11 @@ elseif(CMAKE_COMPILER_IS_GNUCC) endif() # for OSL -set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") -# set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +if(WIN32 AND MSVC) + set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +elseif(CMAKE_COMPILER_IS_GNUCC) + set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +endif() # Definitions and Includes diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index c0e0353d37d..1a127e364fe 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -23,6 +23,10 @@ defs.append('WITH_OPENCL') defs.append('WITH_MULTI') defs.append('WITH_CUDA') +if env['WITH_BF_CYCLES_OSL']: + defs.append('WITH_OSL') + incs.append(cycles['BF_OSL_INC']) + if env['WITH_BF_CYCLES_CUDA_BINARIES']: defs.append('WITH_CUDA_BINARIES') @@ -32,7 +36,8 @@ incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.sp incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) -incs.append(cycles['BF_PYTHON_INC']) +incs.append(cycles['BF_OPENEXR_INC'].split()) +incs.extend(cycles['BF_PYTHON_INC'].split()) if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) @@ -62,6 +67,12 @@ if env['WITH_BF_RAYOPTIMIZATION']: cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], cxx_compileflags=cxxflags) +if env['WITH_BF_CYCLES_OSL']: + oso_files = SConscript(['kernel/shaders/SConscript']) + cycles.Depends("kernel/osl/osl_shader.o", oso_files) + + SConscript(['kernel/osl/SConscript']) + # cuda kernel binaries if env['WITH_BF_CYCLES_CUDA_BINARIES']: kernel_binaries = SConscript(['kernel/SConscript']) diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index aac1e2422b9..79ce3df20c3 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -79,12 +79,13 @@ def update_script_node(node, report): if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path): # write text datablock contents to temporary file - osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True) + osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=False) osl_file.write(script.as_string()) - osl_file.flush() + osl_file.close() + ok, oso_path = osl_compile(osl_file.name, report) oso_file_remove = False - osl_file.close() + os.remove(osl_file.name) else: # compile text datablock from disk directly ok, oso_path = osl_compile(osl_path, report) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 61fe7cf254d..0cbd2a0291f 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,13 +56,16 @@ struct BlenderCamera { float sensor_width; float sensor_height; + int full_width; + int full_height; + BoundBox2D border; BoundBox2D pano_viewplane; Transform matrix; }; -static void blender_camera_init(BlenderCamera *bcam) +static void blender_camera_init(BlenderCamera *bcam, BL::Scene b_scene) { memset(bcam, 0, sizeof(BlenderCamera)); @@ -77,6 +80,12 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->border.top = 1.0f; bcam->pano_viewplane.right = 1.0f; bcam->pano_viewplane.top = 1.0f; + + /* render resolution */ + BL::RenderSettings r = b_scene.render(); + + bcam->full_width = (int)(r.resolution_x()*r.resolution_percentage()/100); + bcam->full_height = (int)(r.resolution_y()*r.resolution_percentage()/100); } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -207,10 +216,9 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, /* compute x/y aspect and ratio */ float xaspect, yaspect; - - /* sensor fitting */ bool horizontal_fit; + /* sensor fitting */ if(bcam->sensor_fit == BlenderCamera::AUTO) { horizontal_fit = (xratio > yratio); *sensor_size = bcam->sensor_width; @@ -277,9 +285,35 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int blender_camera_viewplane(bcam, width, height, &cam->viewplane, &aspectratio, &sensor_size); - /* sensor */ - cam->sensorwidth = bcam->sensor_width; - cam->sensorheight = bcam->sensor_height; + /* panorama sensor */ + if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { + float fit_xratio = bcam->full_width*bcam->pixelaspect.x; + float fit_yratio = bcam->full_height*bcam->pixelaspect.y; + bool horizontal_fit; + float sensor_size; + + if(bcam->sensor_fit == BlenderCamera::AUTO) { + horizontal_fit = (fit_xratio > fit_yratio); + sensor_size = bcam->sensor_width; + } + else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) { + horizontal_fit = true; + sensor_size = bcam->sensor_width; + } + else { /* vertical */ + horizontal_fit = false; + sensor_size = bcam->sensor_height; + } + + if(horizontal_fit) { + cam->sensorwidth = sensor_size; + cam->sensorheight = sensor_size * fit_yratio / fit_xratio; + } + else { + cam->sensorwidth = sensor_size * fit_xratio / fit_yratio; + cam->sensorheight = sensor_size; + } + } /* clipping distances */ cam->nearclip = bcam->nearclip; @@ -320,7 +354,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int void BlenderSync::sync_camera(BL::Object b_override, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); /* pixel aspect */ BL::RenderSettings r = b_scene.render(); @@ -435,13 +469,13 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) { - BL::RenderSettings r = b_scene.render(); +// BL::RenderSettings r = b_scene.render(); /* UNUSED */ BoundBox2D cam, view; float view_aspect, cam_aspect, sensor_size; /* get viewport viewplane */ BlenderCamera view_bcam; - blender_camera_init(&view_bcam); + blender_camera_init(&view_bcam, b_scene); blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); blender_camera_viewplane(&view_bcam, width, height, @@ -449,13 +483,10 @@ static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::S /* get camera viewplane */ BlenderCamera cam_bcam; - blender_camera_init(&cam_bcam); + blender_camera_init(&cam_bcam, b_scene); blender_camera_from_object(&cam_bcam, b_ob, true); - width = (int)(r.resolution_x()*r.resolution_percentage()/100); - height = (int)(r.resolution_y()*r.resolution_percentage()/100); - - blender_camera_viewplane(&cam_bcam, width, height, + blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, &cam, &cam_aspect, &sensor_size); /* return */ @@ -513,7 +544,7 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); blender_camera_border(&bcam, b_scene, b_v3d, b_rv3d, width, height); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index ad43c39469c..b8ed942f5b6 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -518,8 +518,8 @@ void BlenderSession::get_progress(float& progress, double& total_time) sample = session->progress.get_sample(); samples_per_tile = session->params.samples; - if(samples_per_tile) - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile && tile_total) + progress = ((float)sample / (float)(tile_total * samples_per_tile)); else progress = 0.0; } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 63cf719d010..da06f1d0a38 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -500,8 +500,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); /* todo: handle generated/builtin images */ - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + image->animated = b_image_node.image_user().use_auto_refresh(); + } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; image->projection_blend = b_image_node.projection_blend(); @@ -513,8 +515,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); + env->animated = b_env_node.image_user().use_auto_refresh(); + } env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); @@ -821,7 +825,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha /* Sync Materials */ -void BlenderSync::sync_materials() +void BlenderSync::sync_materials(bool update_all) { shader_map.set_default(scene->shaders[scene->default_surface]); @@ -832,7 +836,7 @@ void BlenderSync::sync_materials() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_mat)) { + if(shader_map.sync(&shader, *b_mat) || update_all) { ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat->name().c_str(); @@ -868,14 +872,14 @@ void BlenderSync::sync_materials() /* Sync World */ -void BlenderSync::sync_world() +void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); - if(world_recalc || b_world.ptr.data != world_map) { + if(world_recalc || update_all || b_world.ptr.data != world_map) { Shader *shader = scene->shaders[scene->default_background]; ShaderGraph *graph = new ShaderGraph(); @@ -922,7 +926,7 @@ void BlenderSync::sync_world() /* Sync Lamps */ -void BlenderSync::sync_lamps() +void BlenderSync::sync_lamps(bool update_all) { shader_map.set_default(scene->shaders[scene->default_light]); @@ -933,7 +937,7 @@ void BlenderSync::sync_lamps() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_lamp)) { + if(shader_map.sync(&shader, *b_lamp) || update_all) { ShaderGraph *graph = new ShaderGraph(); /* create nodes */ @@ -972,11 +976,20 @@ void BlenderSync::sync_lamps() void BlenderSync::sync_shaders() { + /* for auto refresh images */ + bool auto_refresh_update = false; + + if(preview) { + ImageManager *image_manager = scene->image_manager; + int frame = b_scene.frame_current(); + auto_refresh_update = image_manager->set_animation_frame_update(frame); + } + shader_map.pre_sync(); - sync_world(); - sync_lamps(); - sync_materials(); + sync_world(auto_refresh_update); + sync_lamps(auto_refresh_update); + sync_materials(auto_refresh_update); /* false = don't delete unused shaders, not supported */ shader_map.post_sync(false); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 9ebdcfd04bd..d0e8b508df6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -179,12 +179,14 @@ void BlenderSync::sync_integrator() integrator->sample_clamp = get_float(cscene, "sample_clamp"); #ifdef __CAMERA_MOTION__ - if(integrator->motion_blur != r.use_motion_blur()) { - scene->object_manager->tag_update(scene); - scene->camera->tag_update(); - } + if(!preview) { + if(integrator->motion_blur != r.use_motion_blur()) { + scene->object_manager->tag_update(scene); + scene->camera->tag_update(); + } - integrator->motion_blur = (!preview && r.use_motion_blur()); + integrator->motion_blur = r.use_motion_blur(); + } #endif integrator->diffuse_samples = get_int(cscene, "diffuse_samples"); diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 71781bc5459..d3d21fbdf72 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -68,14 +68,14 @@ public: private: /* sync */ - void sync_lamps(); - void sync_materials(); + void sync_lamps(bool update_all); + void sync_materials(bool update_all); void sync_objects(BL::SpaceView3D b_v3d, int motion = 0); void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override); void sync_film(); void sync_integrator(); void sync_view(); - void sync_world(); + void sync_world(bool update_all); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 721c262f094..ee160b275ce 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -191,18 +191,6 @@ vector<DeviceInfo>& Device::available_devices() { static vector<DeviceInfo> devices; static bool devices_init = false; - static double device_update_time = 0.0; - - /* only update device list if we're not actively rendering already, things - * could go very wrong if a device suddenly becomes (un)available. also do - * it only every 5 seconds. it not super cpu intensive but don't want to do - * it on every redraw. */ - if(devices_init) { - if(!TaskScheduler::active() && (time_dt() > device_update_time + 5.0)) { - devices.clear(); - devices_init = false; - } - } if(!devices_init) { #ifdef WITH_CUDA @@ -226,7 +214,6 @@ vector<DeviceInfo>& Device::available_devices() #endif devices_init = true; - device_update_time = time_dt(); } return devices; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 440971e2663..58c590a8de5 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -60,7 +60,7 @@ public: return (CUdeviceptr)mem; } - const char *cuda_error_string(CUresult result) + static const char *cuda_error_string(CUresult result) { switch(result) { case CUDA_SUCCESS: return "No errors"; @@ -917,12 +917,21 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) void device_cuda_info(vector<DeviceInfo>& devices) { + CUresult result; int count = 0; - if(cuInit(0) != CUDA_SUCCESS) + result = cuInit(0); + if(result != CUDA_SUCCESS) { + if(result != CUDA_ERROR_NO_DEVICE) + fprintf(stderr, "CUDA cuInit: %s\n", CUDADevice::cuda_error_string(result)); return; - if(cuDeviceGetCount(&count) != CUDA_SUCCESS) + } + + result = cuDeviceGetCount(&count); + if(result != CUDA_SUCCESS) { + fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result)); return; + } vector<DeviceInfo> display_devices; diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 2f2314c9a8b..d99beb8905a 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -301,10 +301,6 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) { - #ifdef __OSL__ - using std::isfinite; - #endif - float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z); if(!isfinite(sum)) { diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 1b2fe8c56ee..abc63d99c74 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -229,5 +229,20 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray); } +/* Utilities */ + +__device_inline float camera_distance(KernelGlobals *kg, float3 P) +{ + Transform cameratoworld = kernel_data.cam.cameratoworld; + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) { + float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z); + return fabsf(dot((P - camP), camD)); + } + else + return len(P - camP); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 42733d691e0..7f8b611ba14 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -52,9 +52,7 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float if(!(path_flag & PATH_RAY_TRANSPARENT)) { if(sample == 0) { if(flag & PASS_DEPTH) { - Transform tfm = kernel_data.cam.worldtocamera; - float depth = len(transform_point(&tfm, sd->P)); - + float depth = camera_distance(kg, sd->P); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth); } if(flag & PASS_OBJECT_ID) { diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 585068ce8e2..195291898c6 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -331,10 +331,13 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, 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); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -347,11 +350,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; - ao_bsdf += shader_bsdf_ao(kg, &sd); + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -424,7 +424,12 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* setup ray */ ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); ray.D = bsdf_omega_in; - ray.t = FLT_MAX; + + if(state.bounce == 0) + ray.t -= sd.ray_length; /* clipping works through transparent */ + else + ray.t = FLT_MAX; + #ifdef __RAY_DIFFERENTIALS__ ray.dP = sd.dP; ray.dD = bsdf_domega_in; @@ -509,10 +514,13 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray 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); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -525,11 +533,8 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; - ao_bsdf += shader_bsdf_ao(kg, &sd); + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -712,6 +717,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam int num_samples = kernel_data.integrator.ao_samples; float num_samples_inv = 1.0f/num_samples; float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); for(int j = 0; j < num_samples; j++) { /* todo: solve correlation */ @@ -721,7 +728,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; @@ -734,11 +741,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor; - ao_bsdf += shader_bsdf_ao(kg, &sd); + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); - } } } } @@ -888,6 +892,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam path_state_next(kg, &state, LABEL_TRANSPARENT); ray.P = ray_offset(sd.P, -sd.Ng); + ray.t -= sd.ray_length; /* clipping works through transparent */ } float3 L_sum = path_radiance_sum(kg, &L); diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 1af5e048ad9..879160312cf 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -599,21 +599,38 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) #endif } -__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd) +__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N) { #ifdef __MULTI_CLOSURE__ float3 eval = make_float3(0.0f, 0.0f, 0.0f); + *N = make_float3(0.0f, 0.0f, 0.0f); + for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { + eval += sc->weight*ao_factor; + *N += sc->N*average(sc->weight); + } + if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) { eval += sc->weight; + *N += sd->N*average(sc->weight); + } } + if(is_zero(*N)) + *N = sd->N; + else + *N = normalize(*N); + return eval; #else - if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type)) + *N = sd->N; + + if(CLOSURE_IS_BSDF_DIFFUSE(sd->closure.type)) + return sd->closure.weight*ao_factor; + else if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type)) return sd->closure.weight; else return make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d4d88466688..977fb8c4fd4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -111,6 +111,7 @@ CCL_NAMESPACE_BEGIN #define __BACKGROUND_MIS__ #define __AO__ #define __CAMERA_MOTION__ +#define __ANISOTROPIC__ #ifndef __KERNEL_CUDA__ #define __OBJECT_MOTION__ @@ -375,7 +376,9 @@ typedef struct ShaderClosure { float data1; float3 N; +#ifdef __ANISOTROPIC__ float3 T; +#endif } ShaderClosure; diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript new file mode 100644 index 00000000000..d4b42d2becb --- /dev/null +++ b/intern/cycles/kernel/osl/SConscript @@ -0,0 +1,27 @@ +#!/usr/bin/python + +Import('env') + +defs = [] +incs = [] +cxxflags = Split(env['CXXFLAGS']) + +sources = env.Glob('*.cpp') + +incs.extend('. .. ../svm ../../render ../../util ../../device'.split()) +incs.append(env['BF_OIIO_INC']) +incs.append(env['BF_BOOST_INC']) +incs.append(env['BF_OSL_INC']) +incs.append(env['BF_OPENEXR_INC'].split()) + +defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') +defs.append('CCL_NAMESPACE_END=}') +defs.append('WITH_OSL') + +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + incs.append(env['BF_PTHREADS_INC']) +else: + cxxflags.append('-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + +env.BlenderLib ('cycles_kernel_osl', sources, incs, defs, libtype=['intern'], priority=[10], cxx_compileflags=cxxflags) diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 71e9e5ae4fd..2d91b37be7e 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -66,6 +66,8 @@ void name(RendererServices *, int id, void *data) \ new (data) classname(); \ } +#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname) + #define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) #define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) @@ -77,26 +79,26 @@ public: ShaderClosure sc; OSL::Vec3 N, T; - CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), - m_scattering_label(scattering), m_shaderdata_flag(0) { } - ~CBSDFClosure() { } + CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), + m_scattering_label(scattering), m_shaderdata_flag(0) { } + ~CBSDFClosure() { } - int scattering() const { return m_scattering_label; } - int shaderdata_flag() const { return m_shaderdata_flag; } + int scattering() const { return m_scattering_label; } + int shaderdata_flag() const { return m_shaderdata_flag; } ClosureType shaderclosure_type() const { return sc.type; } - virtual void blur(float roughness) = 0; - virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual void blur(float roughness) = 0; + virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual int sample(const float3 &Ng, - const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, - float randu, float randv, - float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, - float &pdf, float3 &eval) const = 0; + virtual int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const = 0; protected: - int m_scattering_label; + int m_scattering_label; int m_shaderdata_flag; }; @@ -151,7 +153,7 @@ public: \ } \ }; \ \ -ClosureParam *bsdf_##lower##_params() \ +static ClosureParam *bsdf_##lower##_params() \ { \ static ClosureParam params[] = { @@ -164,7 +166,7 @@ ClosureParam *bsdf_##lower##_params() \ return params; \ } \ \ -CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure) +CLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 80ced9dfd62..ce283023c5c 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -22,12 +22,17 @@ #ifdef WITH_OSL #include <OSL/oslexec.h> +#include <cmath> #include "util_map.h" #include "util_param.h" #include "util_thread.h" #include "util_vector.h" +#ifndef WIN32 +using std::isfinite; +#endif + CCL_NAMESPACE_BEGIN class OSLRenderServices; @@ -38,6 +43,7 @@ struct OSLGlobals { /* shading system */ OSL::ShadingSystem *ss; + OSL::TextureSystem *ts; OSLRenderServices *services; /* shader states */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 54cbf49704f..e79c509b144 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -649,6 +649,80 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst return false; /* never called by OSL */ } +bool OSLRenderServices::texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl.ts; + bool status = ts->texture(filename, options, s, t, dsdx, dtdx, dsdy, dtdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl.ts; + bool status = ts->texture3d(filename, options, P, dPdx, dPdy, dPdz, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + + } + + return status; +} + +bool OSLRenderServices::environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl.ts; + bool status = ts->environment(filename, options, R, dRdx, dRdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::get_texture_info(ustring filename, int subimage, + ustring dataname, + TypeDesc datatype, void *data) +{ + OSL::TextureSystem *ts = kernel_globals->osl.ts; + return ts->get_texture_info(filename, subimage, dataname, datatype, data); +} + int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, float radius, int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index ce62eaf8994..b5a7bbae7e5 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -84,6 +84,23 @@ public: bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, TypeDesc type, void *val, bool derivatives); + bool texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result); + + bool texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result); + + bool environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result); + + bool get_texture_info(ustring filename, int subimage, + ustring dataname, TypeDesc datatype, void *data); + struct TraceData { Ray ray; Intersection isect; diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 4f5a97c1bb6..f7fec62fd6d 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -89,7 +89,7 @@ foreach(_file ${SRC_OSL}) list(APPEND SRC_OSO ${_OSO_FILE} ) - + unset(_OSL_FILE) unset(_OSO_FILE) endforeach() diff --git a/intern/cycles/kernel/shaders/SConscript b/intern/cycles/kernel/shaders/SConscript new file mode 100644 index 00000000000..36b86d7b4f6 --- /dev/null +++ b/intern/cycles/kernel/shaders/SConscript @@ -0,0 +1,42 @@ +#!/usr/bin/python +import sys +import os +import Blender as B + +def normpath(path): + return os.path.abspath(os.path.normpath(path)) + +Import ('env') + +oso_files = [] + +if env['WITH_BF_CYCLES_OSL']: + shaders = env.Clone() + + # osl compiler + osl_compiler = File(env.subst(env['BF_OSL_COMPILER'])).abspath + + # build directory + root_build_dir = normpath(env['BF_BUILDDIR']) + build_dir = os.path.join(root_build_dir, 'intern/cycles/kernel/shaders') + + # source directories and files + source_dir = Dir('.').srcnode().path + + # dependencies + dependencies = shaders.Glob('*.h') + + for f in os.listdir(source_dir): + if f.endswith('.osl'): + osl_file = os.path.join(source_dir, f) + oso_file = os.path.join(build_dir, f.replace('.osl', '.oso')) + + command = "%s -O2 -I%s -o %s %s" % (osl_compiler, source_dir, oso_file, osl_file) + + shaders.Command(oso_file, f, command) + shaders.Depends(oso_file, [f] + dependencies) + + oso_files.append(oso_file) + + +Return('oso_files') diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl index 57a06f35461..b9423344e73 100644 --- a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl +++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl @@ -19,6 +19,7 @@ #include "stdosl.h" shader node_ambient_occlusion( + normal NormalIn = N, color Color = color(0.8, 0.8, 0.8), output closure color AO = ambient_occlusion()) { diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl index 478d9457001..b1f2a35789f 100644 --- a/intern/cycles/kernel/shaders/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -58,6 +58,8 @@ float brick(point p, float mortar_size, float bias, } shader node_brick_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Offset = 0.5, int OffsetFrequency = 2, float Squash = 1.0, @@ -74,10 +76,15 @@ shader node_brick_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + float tint = 0.0; color Col = Color1; - Fac = brick(Vector * Scale, MortarSize, Bias, BrickWidth, RowHeight, + Fac = brick(p * Scale, MortarSize, Bias, BrickWidth, RowHeight, Offset, OffsetFrequency, Squash, SquashFrequency, tint); if (Fac != 1.0) { diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl index 8e9f5c9c796..b263d815566 100644 --- a/intern/cycles/kernel/shaders/node_brightness.osl +++ b/intern/cycles/kernel/shaders/node_brightness.osl @@ -20,32 +20,15 @@ shader node_brightness( color ColorIn = color(0.8, 0.8, 0.8), - float Brightness = 0.0, + float Bright = 0.0, float Contrast = 0.0, output color ColorOut = color(0.8, 0.8, 0.8)) { - float delta = Contrast * (1.0 / 200.0); - float a = 1.0 - delta * 2.0; - float b; + float a = 1.0 + Contrast; + float b = Bright - Contrast*0.5; - /* input value is a percentage */ - float bright_factor = Brightness / 100.0; - - /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - - if (Contrast > 0.0) { - a = (a < 0.0 ? 1.0 / a : 0.0); - b = a * (bright_factor - delta); - } - else { - delta *= -1.0; - b = a * (bright_factor + delta); - } - - ColorOut = a * ColorIn + b; + ColorOut[0] = max(a*ColorIn[0] + b, 0.0); + ColorOut[1] = max(a*ColorIn[1] + b, 0.0); + ColorOut[2] = max(a*ColorIn[2] + b, 0.0); } diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl index 577caf308ff..eed56f4453a 100644 --- a/intern/cycles/kernel/shaders/node_checker_texture.osl +++ b/intern/cycles/kernel/shaders/node_checker_texture.osl @@ -40,6 +40,8 @@ float checker(point p) } shader node_checker_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Scale = 5.0, point Vector = P, color Color1 = color(0.8, 0.8, 0.8), @@ -47,7 +49,12 @@ shader node_checker_texture( output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = checker(Vector * Scale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = checker(p * Scale); if (Fac == 1.0) { Color = Color1; } diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl index bad62e56ab4..4367f7f4994 100644 --- a/intern/cycles/kernel/shaders/node_environment_texture.osl +++ b/intern/cycles/kernel/shaders/node_environment_texture.osl @@ -19,14 +19,52 @@ #include "stdosl.h" #include "node_color.h" +vector environment_texture_direction_to_equirectangular(vector dir) +{ + float u = -atan2(dir[1], dir[0])/(2.0*M_PI) + 0.5; + float v = atan2(dir[2], hypot(dir[0], dir[1]))/M_PI + 0.5; + + return vector(u, v, 0.0); +} + +vector environment_texture_direction_to_mirrorball(vector dir) +{ + dir[1] -= 1.0; + + float div = 2.0*sqrt(max(-0.5*dir[1], 0.0)); + if(div > 0.0) + dir /= div; + + float u = 0.5*(dir[0] + 1.0); + float v = 0.5*(dir[2] + 1.0); + + return vector(u, v, 0.0); +} + shader node_environment_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, string filename = "", + string projection = "Equirectangular", string color_space = "sRGB", output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { - Color = (color)environment(filename, Vector, "alpha", Alpha); + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = normalize(p); + + if (projection == "Equirectangular") + p = environment_texture_direction_to_equirectangular(p); + else + p = environment_texture_direction_to_mirrorball(p); + + /* todo: use environment for better texture filtering of equirectangular */ + Color = (color)texture(filename, p[0], 1.0 - p[1], "wrap", "periodic", "alpha", Alpha); if (color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl index ae7cfa51f59..8d862dbad67 100644 --- a/intern/cycles/kernel/shaders/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -63,12 +63,19 @@ float gradient(point p, string type) } shader node_gradient_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Linear", point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = gradient(Vector, Type); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = gradient(p, Type); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl index 8fd7a1612e8..0f4bedfb0f8 100644 --- a/intern/cycles/kernel/shaders/node_hsv.osl +++ b/intern/cycles/kernel/shaders/node_hsv.osl @@ -27,7 +27,6 @@ shader node_hsv( color ColorIn = color(0.0, 0.0, 0.0), output color ColorOut = color(0.0, 0.0, 0.0)) { - float t = clamp(Fac, 0.0, 1.0); color Color = rgb_to_hsv(ColorIn); // remember: fmod doesn't work for negative numbers @@ -38,6 +37,6 @@ shader node_hsv( Color = hsv_to_rgb(Color); - ColorOut = mix(Color, ColorIn, t); + ColorOut = mix(ColorIn, Color, Fac); } diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 6393605e6b5..53c4aeaeb5f 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -30,6 +30,8 @@ color image_texture_lookup(string filename, string color_space, float u, float v } shader node_image_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), point Vector = P, string filename = "", string color_space = "sRGB", @@ -38,8 +40,13 @@ shader node_image_texture( output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + if (projection == "Flat") { - Color = image_texture_lookup(filename, color_space, Vector[0], Vector[1], Alpha); + Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha); } else if (projection == "Box") { /* object space normal */ @@ -104,15 +111,15 @@ shader node_image_texture( float tmp_alpha; if (weight[0] > 0.0) { - Color += weight[0]*image_texture_lookup(filename, color_space, Vector[1], Vector[2], tmp_alpha); + Color += weight[0]*image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha); Alpha += weight[0]*tmp_alpha; } if (weight[1] > 0.0) { - Color += weight[1]*image_texture_lookup(filename, color_space, Vector[0], Vector[2], tmp_alpha); + Color += weight[1]*image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha); Alpha += weight[1]*tmp_alpha; } if (weight[2] > 0.0) { - Color += weight[2]*image_texture_lookup(filename, color_space, Vector[1], Vector[0], tmp_alpha); + Color += weight[2]*image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha); Alpha += weight[2]*tmp_alpha; } } diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl index e464b83bc9e..b81a30499b2 100644 --- a/intern/cycles/kernel/shaders/node_magic_texture.osl +++ b/intern/cycles/kernel/shaders/node_magic_texture.osl @@ -93,12 +93,19 @@ color magic(point p, int n, float distortion) } shader node_magic_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), int Depth = 2, float Distortion = 5.0, float Scale = 5.0, point Vector = P, output color Color = color(0.0, 0.0, 0.0)) { - Color = magic(Vector * Scale, Depth, Distortion); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Color = magic(p * Scale, Depth, Distortion); } diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 71461b8fd79..afdbca27a3f 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -187,6 +187,8 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, /* Shader */ shader node_musgrave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "fBM", float Dimension = 2.0, float Lacunarity = 1.0, @@ -204,7 +206,12 @@ shader node_musgrave_texture( string Basis = "Perlin"; float intensity = 1.0; - point p = Vector * Scale; + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = p * Scale; if (Type == "Multifractal") Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl index 227b2bf8cea..0a379491781 100644 --- a/intern/cycles/kernel/shaders/node_noise_texture.osl +++ b/intern/cycles/kernel/shaders/node_noise_texture.osl @@ -43,6 +43,8 @@ float noise(point p, string basis, float distortion, float detail, float fac, co } shader node_noise_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Distortion = 0.0, float Scale = 5.0, float Detail = 2.0, @@ -50,7 +52,12 @@ shader node_noise_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + string Basis = "Perlin"; - Fac = noise(Vector * Scale, Basis, Distortion, Detail, Fac, Color); + Fac = noise(p * Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index 932fb1e2f17..24a63c78458 100644 --- a/intern/cycles/kernel/shaders/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -43,9 +43,9 @@ color xyY_to_xyz(float x, float y, float Y) color xyz_to_rgb(float x, float y, float z) { - return color(3.240479 * x + -1.537150 * y + -0.498535 * z, - -0.969256 * x + 1.875991 * y + 0.041556 * z, - 0.055648 * x + -0.204043 * y + 1.057311 * z); + return color( 3.240479 * x + -1.537150 * y + -0.498535 * z, + -0.969256 * x + 1.875991 * y + 0.041556 * z, + 0.055648 * x + -0.204043 * y + 1.057311 * z); } float sky_angle_between(float thetav, float phiv, float theta, float phi) @@ -149,14 +149,21 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky) } shader node_sky_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, vector sun_direction = vector(0, 0, 1), float turbidity = 2.2, output color Color = color(0.0, 0.0, 0.0)) { + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + KernelSunSky sunsky; precompute_sunsky(sun_direction, turbidity, sunsky); - Color = sky_xyz_radiance(sunsky, Vector); + Color = sky_xyz_radiance(sunsky, p); } diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl index 791838dfffe..37460bcfc98 100644 --- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -56,7 +56,7 @@ shader node_texture_coordinate( Camera = transform("camera", P); Window = transform("NDC", P); Normal = transform("world", "object", NormalIn); - Reflection = reflect(I, NormalIn); + Reflection = -reflect(I, NormalIn); } if (bump_offset == "dx") { @@ -77,5 +77,7 @@ shader node_texture_coordinate( Camera += Dy(Camera); Window += Dy(Window); } + + Window[2] = 0.0; } diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl index a44df00a267..43f8ecc666a 100644 --- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl +++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl @@ -22,17 +22,24 @@ /* Voronoi */ shader node_voronoi_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Coloring = "Intensity", float Scale = 5.0, point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + /* compute distance and point coordinate of 4 nearest neighbours */ float da[4]; point pa[4]; - voronoi(Vector * Scale, "Distance Squared", 1.0, da, pa); + voronoi(p * Scale, "Distance Squared", 1.0, da, pa); /* Colored output */ if (Coloring == "Intensity") { diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index e5c6f0ad705..82ce15ab9b6 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -30,20 +30,20 @@ shader node_ward_bsdf( /* rotate tangent around normal */ vector T = Tangent; - if(Rotation != 0.0) + if (Rotation != 0.0) T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); /* compute roughness */ float RoughnessU, RoughnessV; float aniso = clamp(Anisotropy, -0.99, 0.99); - if(aniso < 0.0) { - RoughnessU = Roughness/(1.0 + aniso); - RoughnessV = Roughness*(1.0 + aniso); + if (aniso < 0.0) { + RoughnessU = Roughness / (1.0 + aniso); + RoughnessV = Roughness * (1.0 + aniso); } else { - RoughnessU = Roughness*(1.0 - aniso); - RoughnessV = Roughness/(1.0 - aniso); + RoughnessU = Roughness * (1.0 - aniso); + RoughnessV = Roughness / (1.0 - aniso); } BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index 79b8a8885d1..6648cd06278 100644 --- a/intern/cycles/kernel/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -46,6 +46,8 @@ float wave(point p, float scale, string type, float detail, float distortion, fl } shader node_wave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Bands", float Scale = 5.0, float Distortion = 0.0, @@ -55,7 +57,12 @@ shader node_wave_texture( output float Fac = 0.0, output color Color = color (0.0, 0.0, 0.0)) { - Fac = wave(Vector, Scale, Type, Detail, Distortion, DetailScale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = wave(p, Scale, Type, Detail, Distortion, DetailScale); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index 373710446e5..07927fe5691 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -24,7 +24,7 @@ #include "../closure/bsdf_reflection.h" #include "../closure/bsdf_refraction.h" #include "../closure/bsdf_transparent.h" -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ #include "../closure/bsdf_ward.h" #endif #include "../closure/bsdf_westin.h" @@ -75,7 +75,7 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -138,7 +138,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -187,7 +187,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; @@ -244,7 +244,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: bsdf_microfacet_beckmann_blur(sc, roughness); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: bsdf_ward_blur(sc, roughness); break; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index f378d24463d..a4f8546f62b 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -225,7 +225,6 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; } -#ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: { #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) @@ -233,9 +232,11 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st #endif ShaderClosure *sc = svm_node_closure_get(sd); sc->N = N; - sc->T = stack_load_float3(stack, data_node.z); svm_node_closure_set_mix_weight(sc, mix_weight); +#ifdef __ANISOTROPIC__ + sc->T = stack_load_float3(stack, data_node.z); + /* rotate tangent */ float rotation = stack_load_float(stack, data_node.w); @@ -256,9 +257,11 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st } sd->flag |= bsdf_ward_setup(sc); +#else + sd->flag |= bsdf_diffuse_setup(sc); +#endif break; } -#endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { ShaderClosure *sc = svm_node_closure_get(sd); sc->N = N; diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index bce11d62923..26b6141ee3f 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -110,7 +110,7 @@ __device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint color = rgb_to_hsv(color); - // remember: fmod doesn't work for negative numbers + /* remember: fmod doesn't work for negative numbers here */ color.x += hue + 0.5f; color.x = fmod(color.x, 1.0f); color.y *= sat; diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index e39c7a4ba6c..db3b8d3f763 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -38,6 +38,21 @@ __device float safe_acosf(float a) return acosf(a); } +__device float compatible_powf(float x, float y) +{ + /* GPU pow doesn't accept negative x, do manual checks here */ + if(x < 0.0f) { + if(fmod(-y, 2.0f) == 0.0f) + return powf(-x, y); + else + return -powf(-x, y); + } + else if(x == 0.0f) + return 0.0f; + + return powf(x, y); +} + __device float safe_powf(float a, float b) { if(b == 0.0f) @@ -47,7 +62,7 @@ __device float safe_powf(float a, float b) if(a < 0.0f && b != (int)b) return 0.0f; - return powf(a, b); + return compatible_powf(a, b); } __device float safe_logf(float a, float b) diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 8ca7dff3970..9f2d3367420 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -20,17 +20,19 @@ CCL_NAMESPACE_BEGIN /* Texture Coordinate Node */ -__device_inline float3 svm_background_offset(KernelGlobals *kg) +__device_inline float3 svm_background_position(KernelGlobals *kg, float3 P) { Transform cameratoworld = kernel_data.cam.cameratoworld; - return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + return camP + P; } __device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P) { if(kernel_data.cam.type != CAMERA_PANORAMA) { if(sd->object == ~0) - P += svm_background_offset(kg); + P = svm_background_position(kg, P); Transform tfm = kernel_data.cam.worldtondc; return transform_perspective(&tfm, P); @@ -78,11 +80,12 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack if(sd->object != ~0) data = transform_point(&tfm, sd->P); else - data = transform_point(&tfm, sd->P + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -135,11 +138,12 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dx); else - data = transform_point(&tfm, sd->P + sd->dP.dx + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dx)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dx); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -195,11 +199,12 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dy); else - data = transform_point(&tfm, sd->P + sd->dP.dy + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dy)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dy); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -278,7 +283,7 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac N = normalize(sd->N + (N - sd->N)*strength); } - stack_store_float3(stack, normal_offset, normalize(N)); + stack_store_float3(stack, normal_offset, N); } __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 308ebd0794a..32c273c1248 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -89,13 +89,12 @@ void Camera::update() Transform ndctoraster = transform_scale(width, height, 1.0f); /* raster to screen */ - Transform screentoraster = ndctoraster; - - screentoraster = ndctoraster * + Transform screentondc = transform_scale(1.0f/(viewplane.right - viewplane.left), 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); + Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); /* screen to camera */ @@ -105,14 +104,24 @@ void Camera::update() screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); else screentocamera = transform_identity(); + + Transform cameratoscreen = transform_inverse(screentocamera); rastertocamera = screentocamera * rastertoscreen; + cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; screentoworld = cameratoworld * screentocamera; rastertoworld = cameratoworld * rastertocamera; ndctoworld = rastertoworld * ndctoraster; - worldtoraster = transform_inverse(rastertoworld); + + /* note we recompose matrices instead of taking inverses of the above, this + * is needed to avoid inverting near degenerate matrices that happen due to + * precision issues with large scenes */ + worldtocamera = transform_inverse(matrix); + worldtoscreen = cameratoscreen * worldtocamera; + worldtondc = screentondc * worldtoscreen; + worldtoraster = ndctoraster * worldtondc; /* differentials */ if(type == CAMERA_ORTHOGRAPHIC) { @@ -160,10 +169,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->rastertoworld = rastertoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; - kcam->worldtoscreen = transform_inverse(screentoworld); + kcam->worldtocamera = worldtocamera; + kcam->worldtoscreen = worldtoscreen; kcam->worldtoraster = worldtoraster; - kcam->worldtondc = transform_inverse(ndctoworld); - kcam->worldtocamera = transform_inverse(cameratoworld); + kcam->worldtondc = worldtondc; /* camera motion */ kcam->have_motion = 0; @@ -181,8 +190,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } else { if(use_motion) { - kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); - kcam->motion.post = transform_inverse(motion.post * rastertocamera); + kcam->motion.pre = cameratoraster * transform_inverse(motion.pre); + kcam->motion.post = cameratoraster * transform_inverse(motion.post); } else { kcam->motion.pre = worldtoraster; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 4c2de7b50b8..9696161180d 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -82,9 +82,15 @@ public: Transform screentoworld; Transform rastertoworld; Transform ndctoworld; - Transform rastertocamera; Transform cameratoworld; + Transform worldtoraster; + Transform worldtoscreen; + Transform worldtondc; + Transform worldtocamera; + + Transform rastertocamera; + Transform cameratoraster;; float3 dx; float3 dy; diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index f136f08dc2c..230a12f9ff2 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -36,6 +36,7 @@ ImageManager::ImageManager() need_update = true; pack_images = false; osl_texture_system = NULL; + animation_frame = 0; tex_num_images = TEX_NUM_IMAGES; tex_num_float_images = TEX_NUM_FLOAT_IMAGES; @@ -67,7 +68,24 @@ void ImageManager::set_extended_image_limits(void) tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START; } -static bool is_float_image(const string& filename) +bool ImageManager::set_animation_frame_update(int frame) +{ + if(frame != animation_frame) { + animation_frame = frame; + + for(size_t slot = 0; slot < images.size(); slot++) + if(images[slot] && images[slot]->animated) + return true; + + for(size_t slot = 0; slot < float_images.size(); slot++) + if(float_images[slot] && float_images[slot]->animated) + return true; + } + + return false; +} + +bool ImageManager::is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); bool is_float = false; @@ -95,7 +113,7 @@ static bool is_float_image(const string& filename) return is_float; } -int ImageManager::add_image(const string& filename, bool& is_float) +int ImageManager::add_image(const string& filename, bool animated, bool& is_float) { Image *img; size_t slot; @@ -133,6 +151,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; float_images[slot] = img; @@ -166,6 +185,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; images[slot] = img; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 485bfc5cbf5..4d177174971 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -51,16 +51,17 @@ public: ImageManager(); ~ImageManager(); - int add_image(const string& filename, bool& is_float); + int add_image(const string& filename, bool animated, bool& is_float); void remove_image(const string& filename); + bool is_float_image(const string& filename); void device_update(Device *device, DeviceScene *dscene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void set_osl_texture_system(void *texture_system); void set_pack_images(bool pack_images_); - void set_extended_image_limits(void); + bool set_animation_frame_update(int frame); bool need_update; @@ -69,11 +70,13 @@ private: int tex_num_float_images; int tex_image_byte_start; thread_mutex device_mutex; + int animation_frame; struct Image { string filename; bool need_load; + bool animated; int users; }; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 82afab4dc1a..48a8565ed98 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -100,6 +100,16 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou } } +void TextureMapping::compile(OSLCompiler &compiler) +{ + if(!skip()) { + Transform tfm = transform_transpose(compute_transform()); + + compiler.parameter("mapping", tfm); + compiler.parameter("use_mapping", 1); + } +} + /* Image Texture */ static ShaderEnum color_space_init() @@ -130,11 +140,12 @@ ImageTextureNode::ImageTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Flat");; projection_blend = 0.0f; + animated = false; add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV); add_output("Color", SHADER_SOCKET_COLOR); @@ -152,7 +163,7 @@ ShaderNode *ImageTextureNode::clone() const ImageTextureNode *node = new ImageTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -163,8 +174,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(is_float == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -220,6 +234,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) void ImageTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); @@ -250,10 +269,11 @@ EnvironmentTextureNode::EnvironmentTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Equirectangular"); + animated = false; add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION); add_output("Color", SHADER_SOCKET_COLOR); @@ -271,7 +291,7 @@ ShaderNode *EnvironmentTextureNode::clone() const EnvironmentTextureNode *node = new EnvironmentTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -282,8 +302,11 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(slot == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -328,7 +351,13 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) void EnvironmentTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); + compiler.parameter("projection", projection); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); else @@ -438,6 +467,8 @@ void SkyTextureNode::compile(SVMCompiler& compiler) void SkyTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter_vector("sun_direction", sun_direction); compiler.parameter("turbidity", turbidity); compiler.add(this, "node_sky_texture"); @@ -501,6 +532,8 @@ void GradientTextureNode::compile(SVMCompiler& compiler) void GradientTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_gradient_texture"); } @@ -559,6 +592,8 @@ void NoiseTextureNode::compile(SVMCompiler& compiler) void NoiseTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_noise_texture"); } @@ -619,6 +654,8 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler) void VoronoiTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Coloring", coloring); compiler.add(this, "node_voronoi_texture"); } @@ -706,6 +743,8 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler) void MusgraveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_musgrave_texture"); @@ -784,6 +823,8 @@ void WaveTextureNode::compile(SVMCompiler& compiler) void WaveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_wave_texture"); @@ -841,6 +882,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler) void MagicTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Depth", depth); compiler.add(this, "node_magic_texture"); } @@ -897,6 +940,8 @@ void CheckerTextureNode::compile(SVMCompiler& compiler) void CheckerTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_checker_texture"); } @@ -985,6 +1030,8 @@ void BrickTextureNode::compile(SVMCompiler& compiler) void BrickTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Offset", offset); compiler.parameter("OffsetFrequency", offset_frequency); compiler.parameter("Squash", squash); @@ -1578,6 +1625,8 @@ void HoldoutNode::compile(OSLCompiler& compiler) AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode("ambient_occlusion") { + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_output("AO", SHADER_SOCKET_CLOSURE); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 27b07769e28..3e89c2286ad 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -36,6 +36,7 @@ public: Transform compute_transform(); bool skip(); void compile(SVMCompiler& compiler, int offset_in, int offset_out); + void compile(OSLCompiler &compiler); float3 translation; float3 rotation; @@ -67,11 +68,12 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; float projection_blend; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; @@ -85,10 +87,11 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 5fbc7932849..c5ecddcfc15 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -81,13 +81,14 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; - OSLCompiler compiler((void*)this, (void*)ss); + OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager); compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); } /* setup shader engine */ og->ss = ss; + og->ts = ts; og->services = services; int background_id = scene->shader_manager->get_shader_id(scene->default_background); og->background_state = og->surface_state[background_id & SHADER_MASK]; @@ -118,6 +119,7 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) /* clear shader engine */ og->use = false; og->ss = NULL; + og->ts = NULL; og->surface_state.clear(); og->volume_state.clear(); @@ -286,10 +288,11 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_) { manager = manager_; shadingsys = shadingsys_; + image_manager = image_manager_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; background = false; @@ -333,7 +336,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output) while((i = sname.find(" ")) != string::npos) sname.replace(i, 1, ""); - /* if output exists with the same name, add "In" suffix */ + /* if input exists with the same name, add "Out" suffix */ foreach(ShaderInput *input, node->inputs) { if (strcmp(input->name, output->name)==0) { sname += "Out"; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index b4b3f59e02a..17934765155 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -83,7 +83,7 @@ protected: class OSLCompiler { public: - OSLCompiler(void *manager, void *shadingsys); + OSLCompiler(void *manager, void *shadingsys, ImageManager *image_manager); void compile(OSLGlobals *og, Shader *shader); void add(ShaderNode *node, const char *name, bool isfilepath = false); @@ -110,6 +110,7 @@ public: ShaderType output_type() { return current_type; } bool background; + ImageManager *image_manager; private: string id(ShaderNode *node); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 41212c2db84..003b722b5a5 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -757,7 +757,7 @@ void Session::update_status_time(bool show_pause, bool show_done) if(preview_time == 0.0 && resolution == 1) preview_time = time_dt(); - double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); + double tile_time = (tile == 0 || sample == 0)? 0.0: (time_dt() - preview_time - paused_time) / sample; /* negative can happen when we pause a bit before rendering, can discard that */ if(preview_time < 0.0) preview_time = 0.0; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index dc249984499..73904eac41d 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -487,7 +487,39 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) } } -void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset) +void SVMCompiler::count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data) +{ + /* here we count the number of times each closure node is used, so that + * the last time we encounter it we can run the actually code with the + * weights from all other places added together */ + + if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { + ShaderInput *cl1in = node->input("Closure1"); + ShaderInput *cl2in = node->input("Closure2"); + + if(cl1in->link) + count_closure_users(cl1in->link->parent, closure_data); + if(cl2in->link) + count_closure_users(cl2in->link->parent, closure_data); + } + else { + MultiClosureData data; + + if(closure_data.find(node) == closure_data.end()) { + data.stack_offset = SVM_STACK_INVALID; + data.users = 1; + } + else { + data = closure_data[node]; + data.users++; + } + + closure_data[node] = data; + } +} + +void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, + map<ShaderNode*, MultiClosureData>& closure_data, uint in_offset) { /* todo: the weaks point here is that unlike the single closure sampling * we will evaluate all nodes even if they are used as input for closures @@ -524,21 +556,37 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don out2_offset = in_offset; } - if(cl1in->link) { - generate_multi_closure(cl1in->link->parent, done, out1_offset); - - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out1_offset); - } + if(cl1in->link) + generate_multi_closure(cl1in->link->parent, done, closure_data, out1_offset); - if(cl2in->link) { - generate_multi_closure(cl2in->link->parent, done, out2_offset); + if(cl2in->link) + generate_multi_closure(cl2in->link->parent, done, closure_data, out2_offset); - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out2_offset); - } + if(in_offset != SVM_STACK_INVALID) + stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset); } else { + MultiClosureData data = closure_data[node]; + + if(data.stack_offset == SVM_STACK_INVALID) { + /* first time using closure, use stack position for weight */ + data.stack_offset = in_offset; + } + else { + /* not first time using, add weights together */ + add_node(NODE_MATH, NODE_MATH_ADD, data.stack_offset, in_offset); + add_node(NODE_MATH, data.stack_offset); + + stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset); + } + + data.users--; + closure_data[node] = data; + + /* still users coming? skip generating closure code */ + if(data.users > 0) + return; + /* execute dependencies for closure */ foreach(ShaderInput *in, node->inputs) { if(!node_skip_input(node, in) && in->link) { @@ -548,7 +596,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don } } - mix_weight_offset = in_offset; + mix_weight_offset = data.stack_offset; /* compile closure itself */ node->compile(*this); @@ -563,6 +611,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don current_shader->has_surface_transparent = true; /* end node is added outside of this */ + + if(data.stack_offset != SVM_STACK_INVALID) + stack_clear_offset(SHADER_SOCKET_FLOAT, data.stack_offset); } } @@ -634,8 +685,12 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty if(generate) { set<ShaderNode*> done; - if(use_multi_closure) - generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + if(use_multi_closure) { + map<ShaderNode*, MultiClosureData> closure_data; + + count_closure_users(clin->link->parent, closure_data); + generate_multi_closure(clin->link->parent, done, closure_data, SVM_STACK_INVALID); + } else generate_closure(clin->link->parent, done); } diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 0db68f400fc..c7b66d97289 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -81,6 +81,7 @@ public: bool background; protected: + /* stack */ struct Stack { Stack() { memset(users, 0, sizeof(users)); } Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); } @@ -123,11 +124,22 @@ protected: bool node_skip_input(ShaderNode *node, ShaderInput *input); + /* single closure */ void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input); void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done); void generate_closure(ShaderNode *node, set<ShaderNode*>& done); - void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset); + /* multi closure */ + struct MultiClosureData { + int stack_offset; + int users; + }; + + void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, + map<ShaderNode*,MultiClosureData>& closure_data, uint in_offset); + void count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data); + + /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); vector<int4> svm_nodes; diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index a0cdf1761ad..6dd1c6c71e8 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -182,6 +182,16 @@ public: bottom == other.bottom && top == other.top); } + float width() + { + return right - left; + } + + float height() + { + return top - bottom; + } + BoundBox2D operator*(float f) const { BoundBox2D result; diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 843764ca9d6..751d22b2f63 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -75,7 +75,7 @@ protected: * Boost implementation is a bit slow, and Mac OS X __thread is not supported * but the pthreads implementation is optimized, so we use these macros. */ -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(_WIN32) #define tls_ptr(type, name) \ pthread_key_t name @@ -90,10 +90,6 @@ protected: #else -#ifdef __WIN32 -#define __thread __declspec(thread) -#endif - #define tls_ptr(type, name) \ __thread type *name #define tls_set(name, value) \ diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 70ee13d96d7..4eee024990f 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -251,6 +251,13 @@ void transform_motion_decompose(MotionTransform *decomp, const MotionTransform * transform_decompose(&decomp->pre, &motion->pre); transform_decompose(&decomp->mid, mid); transform_decompose(&decomp->post, &motion->post); + + /* ensure rotation around shortest angle, negated quaternions are the same + * but this means we don't have to do the check in quat_interpolate */ + if(dot(decomp->mid.x, decomp->post.x) < 0.0f) + decomp->mid.x = -decomp->mid.x; + if(dot(decomp->pre.x, decomp->mid.x) < 0.0f) + decomp->pre.x = -decomp->pre.x; } CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index df525542207..65162ebf4e6 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -39,16 +39,16 @@ typedef struct Transform { #endif } Transform; +/* transform decomposed in rotation/translation/scale. we use the same data + * structure as Transform, and tightly pack decomposition into it. first the + * rotation (4), then translation (3), then 3x3 scale matrix (9) */ + typedef struct MotionTransform { Transform pre; Transform mid; Transform post; } MotionTransform; -/* transform decomposed in rotation/translation/scale. we use the same data - * structure as Transform, and tightly pack decomposition into it. first the - * rotation (4), then translation (3), then 3x3 scale matrix (9) */ - /* Functions */ __device_inline float3 transform_perspective(const Transform *t, const float3 a) @@ -303,13 +303,11 @@ __device_inline Transform transform_clear_scale(const Transform& tfm) __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { + /* note: this does not ensure rotation around shortest angle, q1 and q2 + * are assumed to be matched already in transform_motion_decompose */ float costheta = dot(q1, q2); - /* rotate around shortest angle */ - if(costheta < 0.0f) { - costheta = -costheta; - q1 = -q1; - } + /* possible optimization: it might be possible to precompute theta/qperp */ if(costheta > 0.9995f) { /* linear interpolation in degenerate case */ @@ -318,14 +316,17 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) else { /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); - float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); + float thetap = theta * t; return q1 * cosf(thetap) + qperp * sinf(thetap); } } __device_inline Transform transform_quick_inverse(Transform M) { + /* possible optimization: can we avoid doing this altogether and construct + * the inverse matrix directly from negated translation, transposed rotation, + * scale can be inverted but what about shearing? */ Transform R; float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z); @@ -380,10 +381,17 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp) tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); } +/* Disabled for now, need arc-length parametrization for constant speed motion. + * #define CURVED_MOTION_INTERPOLATE */ + __device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) { + /* possible optimization: is it worth it adding a check to skip scaling? + * it's probably quite uncommon to have scaling objects. or can we skip + * just shearing perhaps? */ Transform decomp; +#ifdef CURVED_MOTION_INTERPOLATE /* 3 point bezier curve interpolation for position */ float3 Ppre = float4_to_float3(motion->pre.y); float3 Pmid = float4_to_float3(motion->mid.y); @@ -395,13 +403,18 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform decomp.y.x = P.x; decomp.y.y = P.y; decomp.y.z = P.z; +#endif /* linear interpolation for rotation and scale */ if(t < 0.5f) { t *= 2.0f; decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); +#ifdef CURVED_MOTION_INTERPOLATE decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; +#else + decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y; +#endif decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; } @@ -409,7 +422,11 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform t = (t - 0.5f)*2.0f; decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); +#ifdef CURVED_MOTION_INTERPOLATE decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; +#else + decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y; +#endif decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; } diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index 4f640253f0f..1e08cb96a95 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -787,7 +787,7 @@ ntlVec3Gfx ntlGeometryObject::getTranslation(double t) { } /*! get active flag time t*/ float ntlGeometryObject::getGeoActive(double t) { - float act = mcGeoActive.get(t); // if <= 0.0 -> off + float act = (mcGeoActive.get(t) >= 1.) ? 1.0 : 0.0; return act; } diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index 0b36f724985..dcc81dbe5cb 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -143,6 +143,7 @@ void ntlWorld::initDefaults() mFirstSim = 1; mSingleStepDebug = false; mFrameCnt = 0; + mSimFrameCnt = 0; mpOpenGLRenderer = NULL; /* create scene storage */ @@ -406,7 +407,6 @@ int ntlWorld::advanceSims(int framenum) } for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); } - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); // time stopped? nothing else to do... if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ @@ -416,6 +416,13 @@ int ntlWorld::advanceSims(int framenum) (*mpSims)[mFirstSim]->checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); } + // Prevent bug [#29186] Object contribute to fluid sim animation start earlier than keyframe + // Was: double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); - DG + double totalTime = 0.0, targetTime = 0.0; + for(size_t i = 0; i < mSimFrameCnt; i++) + totalTime += (*mpSims)[mFirstSim]->getFrameTime(framenum); + targetTime = totalTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); + int gstate = 0; myTime_t advsstart = getTime(); @@ -461,6 +468,8 @@ int ntlWorld::advanceSims(int framenum) sim->prepareVisualization(); } + mSimFrameCnt++; + return 0; } diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h index 3c5958477d4..c207904cf75 100644 --- a/intern/elbeem/intern/ntl_world.h +++ b/intern/elbeem/intern/ntl_world.h @@ -115,6 +115,9 @@ class ntlWorld /*! count no. of frame for viz render */ int mFrameCnt; + + /*! count no. of frame for correct sim time */ + int mSimFrameCnt; }; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 08f982ffd3f..9162b7ce4e0 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -282,9 +282,6 @@ protected: /** Raised window is not yet known by the window manager, so delay application become active event handling */ bool m_needDelayedApplicationBecomeActiveEventProcessing; - /** Mouse buttons state */ - GHOST_TUns32 m_pressedMouseButtons; - /** State of the modifiers. */ GHOST_TUns32 m_modifierMask; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 475ad2bdcb3..16edb4af575 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -551,7 +551,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() char *rstring = NULL; m_modifierMask =0; - m_pressedMouseButtons =0; m_isGestureInProgress = false; m_cursorDelta_x=0; m_cursorDelta_y=0; @@ -577,8 +576,10 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() 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)-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; @@ -848,12 +849,14 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { + UInt32 button_state = GetCurrentEventButtonState(); + buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); - buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); - buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); - buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); - buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); + buttons.set(GHOST_kButtonMaskLeft, button_state & (1 << 0)); + buttons.set(GHOST_kButtonMaskRight, button_state & (1 << 1)); + buttons.set(GHOST_kButtonMaskMiddle, button_state & (1 << 2)); + buttons.set(GHOST_kButtonMaskButton4, button_state & (1 << 3)); + buttons.set(GHOST_kButtonMaskButton5, button_state & (1 << 4)); return GHOST_kSuccess; } @@ -1591,13 +1594,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if ((dx == 0) && (dy == 0)) break; /* Quadratic acceleration */ - dx = dx*(fabs(dx)+0.5); - if (dx<0.0) dx-=0.5; else dx+=0.5; - if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; + dx = dx*(fabs(dx) + 0.5); + if (dx < 0.0) dx -= 0.5; + else dx += 0.5; + if (dx < -deltaMax) dx = -deltaMax; + else if (dx > deltaMax) dx = deltaMax; - dy = dy*(fabs(dy)+0.5); - if (dy<0.0) dy-=0.5; else dy+=0.5; - if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; + dy = dy*(fabs(dy) + 0.5); + if (dy < 0.0) dy -= 0.5; + else dy += 0.5; + if (dy < -deltaMax) dy= -deltaMax; + else if (dy > deltaMax) dy= deltaMax; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); dy = -dy; diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c9953c80a52..2d3cc4f88dc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -256,7 +256,7 @@ createWindow( window = new GHOST_WindowX11(this, m_display, title, left, top, width, height, - state, parentWindow, type, stereoVisual); + state, parentWindow, type, stereoVisual, numOfAASamples); if (window) { /* Both are now handle in GHOST_WindowX11.cpp diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index fa9e00f82a1..820f59def14 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1285,6 +1285,10 @@ activateDrawingContext() #else glXMakeCurrent(m_display, m_window, m_context); #endif + /* Disable AA by default */ + if (m_numOfAASamples > 0) { + glDisable(GL_MULTISAMPLE_ARB); + } return GHOST_kSuccess; } return GHOST_kFailure; diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp index 43d177d0651..75f51f566c9 100644 --- a/intern/iksolver/intern/IK_QJacobianSolver.cpp +++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp @@ -377,7 +377,7 @@ bool IK_QJacobianSolver::Solve( norm = maxnorm; // check for convergence - if (norm < 1e-3) { + if (norm < 1e-3 && iterations > 10) { solved = true; break; } diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt new file mode 100644 index 00000000000..3187639c844 --- /dev/null +++ b/intern/locale/CMakeLists.txt @@ -0,0 +1,45 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Bastien Montagne. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS +) + +set(SRC + boost_locale_wrapper.cpp +) + +if(WITH_INTERNATIONAL) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) + add_definitions(-DWITH_INTERNATIONAL) + add_definitions(${BOOST_DEFINITIONS}) +endif() + +blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/locale/SConscript b/intern/locale/SConscript new file mode 100644 index 00000000000..df745f093ea --- /dev/null +++ b/intern/locale/SConscript @@ -0,0 +1,14 @@ +#!/usr/bin/python + +Import('env') + +sources = env.Glob('*.cpp') + +incs = '.' +defs = [] + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + incs += ' ' + env['BF_BOOST_INC'] + +env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['intern','player'], priority=[10, 185]) diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp new file mode 100644 index 00000000000..939c66bad13 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.cpp @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include <stdio.h> +#include <boost/locale.hpp> + +#include "boost_locale_wrapper.h" + +static std::string messages_path; +static std::string default_domain; + +void bl_locale_init(const char *_messages_path, const char *_default_domain) +{ + // Avoid using ICU backend, we do not need its power and it's rather heavy! + boost::locale::localization_backend_manager lman = boost::locale::localization_backend_manager::global(); +#if defined (_WIN32) + lman.select("winapi"); +#else + lman.select("posix"); +#endif + boost::locale::localization_backend_manager::global(lman); + + messages_path = _messages_path; + default_domain = _default_domain; +} + +void bl_locale_set(const char *locale) +{ + boost::locale::generator gen; + // Specify location of dictionaries. + gen.add_messages_path(messages_path); + gen.add_messages_domain(default_domain); + //gen.set_default_messages_domain(default_domain); + + if (locale && locale[0]) { + std::locale::global(gen(locale)); + } + else { +#if defined (__APPLE__) + // workaround to get osx system locale from user defaults + FILE* fp; + std::string locale_osx = ""; + char result[16]; + int result_len = 0; + + fp = popen("defaults read .GlobalPreferences AppleLocale", "r"); + + if(fp) { + result_len = fread(result, 1, sizeof(result) - 1, fp); + + if(result_len > 0) { + result[result_len-1] = '\0'; // \0 terminate and remove \n + locale_osx = std::string(result) + std::string(".UTF-8"); + } + + pclose(fp); + } + + if(locale_osx == "") + fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n"); + + std::locale::global(gen(locale_osx.c_str())); +#else + std::locale::global(gen("")); +#endif + } + // Note: boost always uses "C" LC_NUMERIC by default! +} + +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid) +{ + // Note: We cannot use short stuff like boost::locale::gettext, because those return + // std::basic_string objects, which c_ptr()-returned char* is no more valid + // once deleted (which happens as soons they are out of scope of this func). + typedef boost::locale::message_format<char> char_message_facet; + try { + std::locale l; + char_message_facet const &facet = std::use_facet<char_message_facet>(l); + char const *r = facet.get(0, msgctxt, msgid); + if(r) + return r; + return msgid; + } + catch(std::exception const &e) { +// std::cout << "boost_locale_pgettext: " << e.what() << " \n"; + return msgid; + } +} + diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h new file mode 100644 index 00000000000..e7956d216f1 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.h @@ -0,0 +1,49 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file locale/boost_locale_wrapper.h + * \ingroup locale + * A thin C wrapper around boost::locale... + */ + +#ifndef __BOOST_LOCALE_WRAPPER_H__ +#define __BOOST_LOCALE_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void bl_locale_init(const char *messages_path, const char *default_domain); +void bl_locale_set(const char *locale); +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOST_LOCALE_WRAPPER_H__ */ diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index cfff5d10e4f..daf66dc05b1 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -247,8 +247,10 @@ private: if (!elem->can_destroy()) continue; - /* by default 0 means higherst priority element */ - int priority = -(queue.size() - i - 1); + /* by default 0 means highest priority element */ + /* casting a size type to int is questionable, + but unlikely to cause problems */ + int priority = -((int)(queue.size()) - i - 1); priority = getItemPriority(elem->get()->get_data(), priority); if (priority < best_match_priority || best_match_elem == NULL) { diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h index 09cf5c95854..dd19aae9db9 100644 --- a/intern/memutil/MEM_SmartPtr.h +++ b/intern/memutil/MEM_SmartPtr.h @@ -170,7 +170,7 @@ public : } /** - * Assignment operator - ownership is transfered from rhs to lhs. + * Assignment operator - ownership is transferred from rhs to lhs. * There is an intenional side-effect of function of transferring * ownership from the const parameter rhs. This is to insure * the 1-1 relationship. diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 49fc44d1e12..2d73d2ff56b 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -48,7 +48,7 @@ using namespace OCIO_NAMESPACE; #endif #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() -#define MEM_DELETE(what, type) if(what) { (what)->~type(); MEM_freeN(what); } (void)0 +#define MEM_DELETE(what, type) if(what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0 static void OCIO_reportError(const char *err) { @@ -421,8 +421,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p) { - p->~OCIO_ConstProcessorRcPtr(); - MEM_freeN(p); + MEM_DELETE(p, ConstProcessorRcPtr); } const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt index 2f15bbb907c..754036de101 100644 --- a/intern/opennl/CMakeLists.txt +++ b/intern/opennl/CMakeLists.txt @@ -28,7 +28,11 @@ remove_strict_flags() # remove debug flag here since this is not a blender maintained library # and debug gives a lot of prints on UV unwrapping. developers can enable if they need to. -remove_definitions(-DDEBUG) +if(MSVC) + remove_definitions(-DDEBUG) +else() + add_definitions(-UDEBUG) +endif() # quiet compiler warnings about undefined defines |