-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplex noise in the Spatial shader has an incorrect result #77325
Comments
Shadertoy code runs in WebGL, while Godot shader code runs in native GLSL (on Vulkan or OpenGL). This means some differences are expected, especially with regards to floating-point precision. |
I considered that but differences in floating point precision should not produce such stark differences in output. The splotches fall well outside the [-1, 1] range and even getting outside the [-10, 10] range, an order of magnitude difference from what's expected. But there's no reason to speculate, I ran the same shader code in a custom Vulkan app and the result matches with the shadertoy result. Though I am using a different GPU right now (RX 6800) so when I get home I'll test it with my GTX 1080 to rule out it being an NVIDIA driver bug (possibly related to #67150). |
I found that substituting generated GLSL
|
Yes float constants in the shader language are parsed as floats, not doubles or string constants, should be the source of the problem godot/servers/rendering/shader_language.h Lines 481 to 488 in 71ee65d
|
@celyk Thanks for the workaround, that's really helpful! Inspecting native shader code seems very useful, where is the option to do that? So surely this is a bug and should be marked as such right? |
@David-DiGioia I don't think it's a bug, I think it's the GLSL spec not being very clear |
From the spec floats are single precision, not sure where things go weird but it shouldn't by just rounding the values, though there is some situations with constants that might get different results when compiled due to instruction combining, could be improved by adding our own constant folding to shader compiler |
@Zireael07 I disagree. The GLSL spec says
and the Godot documentation says that highp is the default precision level. Then the precision of n_ is highp and is defined by the IEEE 754 standard for 32-bit floating-point numbers, and according to this standard 0.142857142857 has the hex representation 0x3e124925 which do not match. Then it is Godot that is rounding the number and losing precision, not a limitation of 32 bit floats. And technicalities aside, it's a very poor user experience to paste GLSL code and get a different result in Godot than everywhere else that runs that code. |
Then that is the issue here, needs a fix somewhere for printing floating point numbers, will look into it
Now this is a technicality issue, we can't do more than follow the specification |
This is not an issue of following the specification though, this is an issue with Godot's process of converting the Godot shader into GLSL. The process as I understand it is:
This process of converting back and forth between decimal and binary loses precision and is made worse by the fact Godot's function to print the float is truncating it at 6 decimal places. Ideally Godot would just store the string "0.142857142857" and paste this into GLSL as is. But if not this then at least Godot should be printing maximum precision of the float it has stored. |
What I'm saying is that the technicalities are what matters, as I said there is an issue and I've identified it and will look into a fix for it, relating generally to the representation of floats The reason for this is that Now just storing the string might not make sense or work, as it is not just a translator but does various other things afik The issue is that the way floats are formatted is built in and kind of core and needs a bit of a larger approach and discussion |
Godot version
4.0.3 stable
System information
Windows 10, gtx 1080, driver version 531.79 Vulkan backend.
Issue description
I am implementing 3d simplex noise in a spatial shader using this implementation https://github.com/ashima/webgl-noise/blob/master/src/noise3Dgrad.glsl
In shadertoy the implementation produces the expected result:
But using almost identical code in a Godot shader (only modified to give functions unique names since Godot doesn't support shader function overloading) produces an incorrect result with splotches of the noise falling well outside the [-1, 1] range it is suppose to be in, some even falling outside [-10, 10]:
Stepping through the shader code in shadertoy and Godot, the values begin to diverge at the line
Steps to reproduce
Create a new 3D scene, add a MeshInstance3D node as a child of the root. Give mesh instance node a new PlaneMesh (or any other mesh) and under Surface Material Override, add a new material by selecting New ShaderMaterial.
Open the text editor of the shader material and paste the following shader:
To see the shadertoy comparison, go to https://www.shadertoy.com/new and paste the following code:
Minimal reproduction project
shader_bug.zip
The text was updated successfully, but these errors were encountered: