Cycles: Refraction ray bent depending on geometry density #120362

Closed
opened 2024-04-07 11:47:17 +02:00 by Clément Foucault · 8 comments

System Information
Operating system: macOS-14.2.1-arm64-arm-64bit 64 Bits
Graphics card: Metal API Apple M1 Max 1.2

Blender Version
Broken: version: 4.2.0 Alpha
Worked: (newest version of Blender that worked as expected)

Short description of error
Refraction rays are bent differently depending on geometric density.

The test file has 2 sphere with rather high tesselation, but one is an icosphere which has all faces and angles equal, the other is an UV sphere.

Capture d’écran 2024-04-07 à 11.40.44.png

The more you increase the IOR, the more the rays are bent and produce total internal reflection. But increasing IOR should make the refracted ray closer to the inverted normal just like on the left sphere.

This happens also on Glass BSDF but is quite hidden by the reflection term.

I think it is a Cycles bug since it doesn't appear in EEVEE.

Exact steps for others to reproduce the error

  • Create one icosphere and one uvsphere
  • Set normal smooth
  • Assign same material
  • Create refraction BSDF node and set IOR relatively high (>10)
**System Information** Operating system: macOS-14.2.1-arm64-arm-64bit 64 Bits Graphics card: Metal API Apple M1 Max 1.2 **Blender Version** Broken: version: 4.2.0 Alpha Worked: (newest version of Blender that worked as expected) **Short description of error** Refraction rays are bent differently depending on geometric density. The test file has 2 sphere with rather high tesselation, but one is an icosphere which has all faces and angles equal, the other is an UV sphere. ![Capture d’écran 2024-04-07 à 11.40.44.png](/attachments/078e6b5e-50d7-4dba-ba1f-e2609fb0fc02) The more you increase the IOR, the more the rays are bent and produce total internal reflection. But increasing IOR should make the refracted ray closer to the inverted normal just like on the left sphere. This happens also on Glass BSDF but is quite hidden by the reflection term. I think it is a Cycles bug since it doesn't appear in EEVEE. **Exact steps for others to reproduce the error** - Create one icosphere and one uvsphere - Set normal smooth - Assign same material - Create refraction BSDF node and set IOR relatively high (>10)
Clément Foucault added the
Priority
Normal
Type
Report
Status
Needs Triage
labels 2024-04-07 11:47:18 +02:00
Member

Using the test file, I can confirm the same results as you.

However, I'm just wondering if this is expected. The UV sphere isn't a perfect sphere, even showing distortions at the poles of the sphere. And maybe the extremely high IOR just highlights the fact the UV sphere isn't perfectly spherical.

The icosphere isn't perfectly spherical either, but it's a much closer approximation than the UV sphere.

Increasing the geometric density of the UV sphere and applying a Cast to Sphere modifier helps resolve the rendering differences between the UV Sphere and Ico Sphere.

I think it is a Cycles bug since it doesn't appear in EEVEE.

If I recall correctly, EEVEE doesn't do multiple refaction events (E.G. Refraction entering the object, then refraction exiting the object). And this issue only shows up in Cycles if both refaction events occur.

Using the test file, I can confirm the same results as you. However, I'm just wondering if this is expected. The UV sphere isn't a perfect sphere, even showing distortions at the poles of the sphere. And maybe the extremely high IOR just highlights the fact the UV sphere isn't perfectly spherical. The icosphere isn't perfectly spherical either, but it's a much closer approximation than the UV sphere. Increasing the geometric density of the UV sphere and applying a `Cast to Sphere` modifier helps resolve the rendering differences between the UV Sphere and Ico Sphere. > I think it is a Cycles bug since it doesn't appear in EEVEE. If I recall correctly, EEVEE doesn't do multiple refaction events (E.G. Refraction entering the object, then refraction exiting the object). And this issue only shows up in Cycles if both refaction events occur.

If someone want, here is patch with other way to construct Icosphere in geometry nodes (spherically interpolated points of triangle, instead of projection them onto sphere), maybe this could be needed to you to check this in render: #116982.

If someone want, here is patch with other way to construct Icosphere in geometry nodes (spherically interpolated points of triangle, instead of projection them onto sphere), maybe this could be needed to you to check this in render: #116982.
Author
Member

If I recall correctly, EEVEE doesn't do multiple refaction events (E.G. Refraction entering the object, then refraction exiting the object). And this issue only shows up in Cycles if both refaction events occur.

This was tested during the implementation of 2 transmission events approximation for EEVEE-Next #120329. I model the inside of the object as a sphere so it matches perfectly the case when the model is indeed a sphere. And in this test case, the result where consistent between the 2 spheres in EEVEE-Next.

Increasing the geometric density of the UV sphere and applying a Cast to Sphere modifier helps resolve the rendering differences between the UV Sphere and Ico Sphere.

It does, but what it does is that it reduces the difference between the polygons since all polygon are now smaller.

But I'm starting to wonder if that's just a limitation of the normal interpolation at the poles of the UV sphere. But it seems weird that it also affects the normals far away from the pole, near the equator.

Also it produce this singularity when looking at the pole:

Capture d’écran 2024-04-07 à 14.23.44.png

Given that the refracted image is flipped near the pole, I suspect the refraction ray is not on the expected side of the normal which refracts it the wrong direction during the second even. So it might also be a precision issue (since the expected outgoing direction when taking the limit of ior going to infinity should converge to the incomming direction of the first transmission event).

So feel free to label it as known issue / won't fix. But this can appear in quite a lot of model.

> If I recall correctly, EEVEE doesn't do multiple refaction events (E.G. Refraction entering the object, then refraction exiting the object). And this issue only shows up in Cycles if both refaction events occur. This was tested during the implementation of 2 transmission events approximation for EEVEE-Next #120329. I model the inside of the object as a sphere so it matches perfectly the case when the model is indeed a sphere. And in this test case, the result where consistent between the 2 spheres in EEVEE-Next. > Increasing the geometric density of the UV sphere and applying a Cast to Sphere modifier helps resolve the rendering differences between the UV Sphere and Ico Sphere. It does, but what it does is that it reduces the difference between the polygons since all polygon are now smaller. But I'm starting to wonder if that's just a limitation of the normal interpolation at the poles of the UV sphere. But it seems weird that it also affects the normals far away from the pole, near the equator. Also it produce this singularity when looking at the pole: ![Capture d’écran 2024-04-07 à 14.23.44.png](/attachments/e18e4913-0c94-468f-8f4b-4ac2b77eae9d) Given that the refracted image is flipped near the pole, I suspect the refraction ray is not on the expected side of the normal which refracts it the wrong direction during the second even. So it might also be a precision issue (since the expected outgoing direction when taking the limit of ior going to infinity should converge to the incomming direction of the first transmission event). So feel free to label it as known issue / won't fix. But this can appear in quite a lot of model.
Member

There's more going on here. There might be some issue with how geometry/normals are uploaded to Cycles. I will confirm this report at the moment.


I bring up that there might be some issue with how geometry/normals are uploaded to Cycles because of the weird behaviour that's observed when working with geometry nodes.

If you generate a UV sphere with geometry nodes, there are no issues. But as soon as you apply the geometry nodes that generated that sphere, the issue comes back. I'm doubtful it's an issue with geometry nodes or the application of it, so it's likely some issue in Cycles that needs investigation.

You can see this in the video attached below.

There's more going on here. There might be some issue with how geometry/normals are uploaded to Cycles. I will confirm this report at the moment. --- I bring up that there might be some issue with how geometry/normals are uploaded to Cycles because of the weird behaviour that's observed when working with geometry nodes. If you generate a UV sphere with geometry nodes, there are no issues. But as soon as you apply the geometry nodes that generated that sphere, the issue comes back. I'm doubtful it's an issue with geometry nodes or the application of it, so it's likely some issue in Cycles that needs investigation. You can see this in the video attached below.
Alaska added
Status
Confirmed
Module
Render & Cycles
and removed
Status
Needs Triage
labels 2024-04-07 15:43:12 +02:00
Member

Further investigation into the issue above. The only difference between the "Geometry nodes UV sphere" and the "Applied Geometry Nodes UV sphere" when rendered with Cycles appears to be the smoothed normals. The geometry is fine (Geometry position and Geometric/True Normals are identical between the two).

This occurs because of differences in the vertex normals between the two meshes. (Cycles uses the vertex normals to calculate the smooth face normals. The Geometric/True are calculated based on vertex position, which is unchanged). Here is a list of the vertex normals from "Geometry nodes UV sphere" and the "Applied Geometry Nodes UV sphere" to demonstrate the difference. (The UV sphere consists of 4 segments and 3 rings)

Note: Many numbers have been shorten/simplified to make them easier to read.

Vertex index Geometry Nodes UV Sphere Applied Geometry Nodes UV sphere
1 0.0, 0.0, 1.0 0.0, 0.0, 1.0
2 0.0, 0.87, 0.5 0.0, 0.91, 0.42
3 -0.87, 0.0, 0.5 -0.91, 0.0, 0.42
4 0.0, -0.87, 0.5 0.0, -0.91, 0.42
5 0.87, 0.0, 0.5 0.91, 0.0, 0.42
6 0.0, 0.87, -0.5 0.0, 0.91, -0.42
7 -0.87, 0.0, -0.5 -0.91, 0.0, -0.42
8 0.0, -0.87, -0.5 0.0, -0.91, -0.42
9 0.87, 0.0, -0.5 0.91, 0.0, -0.42
10 0.0, 0.0, -1.0 0.0, 0.0, -1.0

It's not clear to me why they're different, but I don't believe the difference is caused by Cycles. Because Cycles gets the vertex normals from the "Vertex Normal Attribute" which I believe is populated with data provided by Blender. And EEVEE has the same issue of having different normals depending on which UV Sphere it's using. Although the issue isn't as visually obvious as it is in Cycles.

To be perfectly honest, I don't know how to work my way back from Cycles requesting the "Vertex Normal Attribute" to where the Vertex Normal Attribute comes from to figure out why they're different due to my inexperience in this area of code (Cycles upload, and basically everything outside of Cycles). So this is about as far as I can go. Hopefully the information helps someone else out in figuring the cause.


Just in case it helps anyway. Cycles computes the smooth face normals in the function triangle_smooth_normal and motion_triangle_smooth_normal (I am ignoring the motion triangle one at the moment).

triangle_smooth_normal computes the smooth normals based on the vertex normals and the UV co-ordinate of the point on the triangle the current ray just hit. The vertex normals are obtained from an array called tri_vnormal which is filled out with information during the Cycles sync/upload process in void Mesh::pack_normals(packed_float3 *vnormal)

Further investigation into the issue above. The only difference between the "Geometry nodes UV sphere" and the "Applied Geometry Nodes UV sphere" when rendered with Cycles appears to be the smoothed normals. The geometry is fine (Geometry position and Geometric/True Normals are identical between the two). This occurs because of differences in the vertex normals between the two meshes. (Cycles uses the vertex normals to calculate the smooth face normals. The Geometric/True are calculated based on vertex position, which is unchanged). Here is a list of the vertex normals from "Geometry nodes UV sphere" and the "Applied Geometry Nodes UV sphere" to demonstrate the difference. (The UV sphere consists of 4 segments and 3 rings) Note: Many numbers have been shorten/simplified to make them easier to read. |Vertex index|Geometry Nodes UV Sphere|Applied Geometry Nodes UV sphere| |-|-|-| |1|0.0, 0.0, 1.0|0.0, 0.0, 1.0| |2|0.0, 0.87, 0.5|0.0, 0.91, 0.42| |3|-0.87, 0.0, 0.5|-0.91, 0.0, 0.42| |4|0.0, -0.87, 0.5|0.0, -0.91, 0.42| |5|0.87, 0.0, 0.5|0.91, 0.0, 0.42| |6|0.0, 0.87, -0.5|0.0, 0.91, -0.42| |7|-0.87, 0.0, -0.5|-0.91, 0.0, -0.42| |8|0.0, -0.87, -0.5|0.0, -0.91, -0.42| |9|0.87, 0.0, -0.5|0.91, 0.0, -0.42| |10|0.0, 0.0, -1.0|0.0, 0.0, -1.0| It's not clear to me why they're different, but I don't believe the difference is caused by Cycles. Because Cycles gets the vertex normals from the "Vertex Normal Attribute" which I believe is populated with data provided by Blender. And EEVEE has the same issue of having different normals depending on which UV Sphere it's using. Although the issue isn't as visually obvious as it is in Cycles. To be perfectly honest, I don't know how to work my way back from Cycles requesting the "Vertex Normal Attribute" to where the Vertex Normal Attribute comes from to figure out why they're different due to my inexperience in this area of code (Cycles upload, and basically everything outside of Cycles). So this is about as far as I can go. Hopefully the information helps someone else out in figuring the cause. --- Just in case it helps anyway. Cycles computes the smooth face normals in the function `triangle_smooth_normal` and `motion_triangle_smooth_normal` (I am ignoring the motion triangle one at the moment). `triangle_smooth_normal` computes the smooth normals based on the vertex normals and the UV co-ordinate of the point on the triangle the current ray just hit. The vertex normals are obtained from an array called `tri_vnormal` which is filled out with information during the Cycles sync/upload process in `void Mesh::pack_normals(packed_float3 *vnormal)`
Member

I am changing this report to a "modelling issue". Please correct it if it's wrong.

My reasoning is this: There is a issue with "distorted" normals on some objects (E.G. Non-geometry nodes UV Spheres). This distortion comes from the mesh, not the render engine from my understanding. And issues with meshes are handled by the modelling module.

I am changing this report to a "modelling issue". Please correct it if it's wrong. My reasoning is this: There is a issue with "distorted" normals on some objects (E.G. Non-geometry nodes UV Spheres). This distortion comes from the mesh, not the render engine from my understanding. And issues with meshes are handled by the modelling module.
Alaska added
Module
Modeling
and removed
Module
Render & Cycles
labels 2024-04-08 06:21:43 +02:00
Member

I agree this is an issue with modeling, namely how the normals are computed.

With general meshes, the vertex normals are computed via adjacent face normals in normals_calc_verts(); with geometry node UV sphere, the vertex normals are computed purely from the vertex positions in calculate_sphere_vertex_data(), which is more accurate. The two methods produce different normals, usually the difference shouldn't have a big impact, but in your test scene with such a high IOR, even an incoming angle of 0.0041 rad would result in TIR, also your UV sphere doesn't have a high level of subdivision, hence the difference in rendering.

I do not know if it's a common practice to compute vertex normals as we do in normals_calc_verts().

I agree this is an issue with modeling, namely how the normals are computed. With general meshes, the vertex normals are computed via adjacent face normals in `normals_calc_verts()`; with geometry node UV sphere, the vertex normals are computed purely from the vertex positions in `calculate_sphere_vertex_data()`, which is more accurate. The two methods produce different normals, usually the difference shouldn't have a big impact, but in your test scene with such a high IOR, even an incoming angle of 0.0041 rad would result in TIR, also your UV sphere doesn't have a high level of subdivision, hence the difference in rendering. I do not know if it's a common practice to compute vertex normals as we do in `normals_calc_verts()`.
Author
Member

Thanks for this in depth insight.

I don't think there is a clear fix to this fundamental precision issue of computing the normal for arbitrary meshes.

Considering this as known issue.

Thanks for this in depth insight. I don't think there is a clear fix to this fundamental precision issue of computing the normal for arbitrary meshes. Considering this as known issue.
Blender Bot added
Status
Archived
and removed
Status
Confirmed
labels 2024-04-09 00:30:13 +02:00
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#120362
No description provided.