Page MenuHome

The "Vector Rotate" shader node behaves differently in Cycles and Eevee
Closed, ResolvedPublic

Description

System Information
Operating system: Windows-10-10.0.19041-SP0 64 Bits
Graphics card: GeForce GTX 1660 Ti/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 457.63

Blender Version
Broken: version: 2.93.0 Beta, branch: master, commit date: 2021-04-16 16:41, hash: rBb2a0f6927508

Short description of error
When passing in a (0, 0, 0) vector as the rotation axis of a Vector Rotate node in Axis Angle mode, the return vector is different in Cycles and Eevee. In Eevee, the original vector is returned with no rotation applied. In Cycles, an empty vector of (0, 0, 0) is returned.

User Story
I was attempting to create a shader involving rotation of a coordinate on an axis based on the z component of a face's normal. In Eevee, everything worked fine, but in Cycles, the parts of my meshed that were vertical (zero z component of normal) broke. After some testing I discovered the inconsistency I pointed out above.
Either of these behaviors would be valid if it was consistent, but the inconsistency caused me a great deal of confusion. I would prefer for the Eevee behavior to present for both, as I find it to be more useful.

Exact steps for others to reproduce the error
From the default startup file, apply a material to the cube.
Go into the shader editor for that material.
plug a vector rotate node into the material output.
set the vector rotate's axis to (0, 0, 0).
plug object coordinates into the vector input of the rotate node. (this is not directly related to the bug, it just makes it much easier to see what's going on)
Switch between Cycles and Eevee render engines to observe the changes.

Event Timeline

The code appears to be ok. I wonder if it is a precision issue?
Cycles normalises the Axis before passing the variable. OSL normalises the Axis in the rotate function.

Cycles svm:
result = (len_squared(axis) != 0.0f) ?
                   rotate_around_axis(vector - center, axis, angle) + center :
                   vector;
Cycles osl:
VectorOut = (length(Axis) != 0.0) ? rotate(VectorIn - Center, a, point(0.0), Axis) + Center :
                                          VectorIn;
Eevee:
vec = (length(axis) != 0.0) ?
           rotate_around_axis(vector_in - center, normalize(axis), angle * invert) + center :
           vector_in;
Philipp Oeser (lichtwerk) changed the task status from Needs Triage to Confirmed.May 7 2021, 3:54 PM

Wondering how much sense it makes to rotate around a zero axis?

Reading the code @Charlie Jolly (charlie) posted it looks like Cycles should just return the in vector in this case?
Instead, this asserts for me (this is why I'll confirm for now):

kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
1   raise                                                                                                                                                                                        0x7ffff77c39d5 
2   abort                                                                                                                                                                                        0x7ffff77ac8a4 
3   __assert_fail_base.cold                                                                                                                                                                      0x7ffff77ac789 
4   __assert_fail                                                                                                                                                                                0x7ffff77bc026 
5   ccl::path_radiance_clamp_and_sum                                                                                                                                    kernel_accumulate.h 670  0x7286849      
6   ccl::kernel_write_result                                                                                                                                            kernel_passes.h     348  0x7286849      
7   ccl::kernel_path_trace                                                                                                                                              kernel_path.h       705  0x7286849      
8   ccl::kernel_cpu_avx2_path_trace                                                                                                                                     kernel_cpu_impl.h   96   0x72d0c7f      
9   ccl::CPUDevice::render                                                                                                                                              device_cpu.cpp      969  0x5f14dba      
10  ccl::CPUDevice::thread_render                                                                                                                                       device_cpu.cpp      1299 0x5f165a3      
11  ccl::CPUDevice::thread_run                                                                                                                                          device_cpu.cpp      576  0x5f1361d      
12  ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}::operator()() const                                                                                        device_cpu.cpp      1459 0x5f16e78      
13  std::__invoke_impl<void, ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}&>(std::__invoke_other, ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}&) invoke.h            60   0x5f23976      
14  std::__invoke_r<void, ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}&>(ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}&)                         invoke.h            110  0x5f2151e      
15  std::_Function_handler<void (), ccl::CPUDevice::task_add(ccl::DeviceTask&)::{lambda()#1}>::_M_invoke(std::_Any_data const&)                                         std_function.h      291  0x5f1ee4c      
16  std::function<void ()>::operator()() const                                                                                                                          std_function.h      622  0x553a67c      
17  tbb::internal::function_task<std::function<void ()>>::execute()                                                                                                     task.h              1059 0xd12f85a      
18  tbb::internal::custom_scheduler<tbb::internal::IntelSchedulerTraits>::process_bypass_loop(tbb::internal::context_guard_helper<false>&, tbb::task *, long)                                    0x3bb1d75      
19  tbb::internal::custom_scheduler<tbb::internal::IntelSchedulerTraits>::local_wait_for_all(tbb::task&, tbb::task *)                                                                            0x3bb202b      
20  tbb::internal::arena::process(tbb::internal::generic_scheduler&)                                                                                                                             0x3ba0c27      
... <More>