-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Support Texture3D and add Volume Cloud SandBox Sample #12611
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
Conversation
Thank you for the pull request, @Hiwen! ✅ We can confirm we have a CLA on file for you. |
Looks awesome @Hiwen! I noticed this pull request is marked as a draft. Is it ready for review? |
It's almost ready. After I transplanted the volumetric clouds from Three.js, I noticed some differences in color, and I want to improve it further. But so far, no breakthrough has been found. Maybe we can improve it together. |
@ggetz I solved the Color Problem, and added params control UI. It's ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Hiwen, it's very exciting to start supporting 3D textures!
The Sandcastle works well for me. I took a first pass through the code and left some comments. Please let me know if my feedback makes sense.
|
||
it("PixelDatatype.FLOAT correspond to WebGLConstants.RGBA32F", function () { | ||
if (!context.webgl2) { | ||
console.warn("Skipping tests for WebGL1."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these warnings are needed (also in Texture3DSpec
). See BufferSpec
, MultiSampleFramebufferSpec
, etc. We can silently skip the test if WebGL2 is not supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. It's done.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`. | ||
* @return {number} The interpolated value. | ||
*/ | ||
function lerp(x, y, t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we simply use Cesium.Math.lerp
instead? That way the person reading the code can get to the important part sooner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done.
"use strict"; | ||
//Sandcastle_Begin | ||
|
||
//ImprovedNoise from Three.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How much of this example is from Three.js? We want to make sure to credit them for the idea, and for whatever else comes from their repo. Perhaps we can add a link to the Three.js example in a comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's necessary! And it's done.
@@ -34,4 +46,97 @@ describe("Core/PixelFormat", function () { | |||
); | |||
expect(flipped).toBe(dataBuffer); | |||
}); | |||
|
|||
it("PixelDatatype.FLOAT correspond to WebGLConstants.RGBA32F", function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spec is checking more than just RGBA32F
. I think it makes sense to check them all in one block. Maybe we can edit the description to make it more clear. Something like:
"Returns the correct internal formats for PixelDatatype.FLOAT"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's much better! And it's done.
console.warn("Skipping tests for WebGL1."); | ||
return; | ||
} | ||
const interFormatR8 = PixelFormat.toInternalFormat( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nitpick: the Coding Guide recommends to avoid abbreviations. Also this one is 32-bit. Would internalFormatR32
be a better name here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I fixed this.
console.warn("texture3D.flipY is not supported."); | ||
} | ||
|
||
// gl.texStorage3D( textureTarget, 1, 33321, width, height, depth ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that texStorage3D is preferred. We didn't use texStorage2D
because we wanted everything to work in WebGL1. But Texture3D
assumes WebGL2 is supported. Can we switch to texStorage3D
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that Three.js writes data through gl.texStorage3D. I didn't know why at that time, but now I understand!
Switch to texStorage3D is an excellent idea, and I did it.
mipWidth = nextMipSize(mipWidth); | ||
mipHeight = nextMipSize(mipHeight); | ||
mipDepth = nextMipSize(mipDepth); | ||
gl.texImage2D( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be texImage3D
? Or switch to texStorage3D
(see previous comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I fixed it.
sizeInBytes: { | ||
get: function () { | ||
if (this._hasMipmap) { | ||
return Math.floor((this._sizeInBytes * 4) / 3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For 3D, the formula should be this._sizeInBytes * 8 / 7
.
It's a geometric series, where the ratio is the relative size of the next mipmap: 1/4 for 2D, 1/8 for 3D.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! I didn't notice this problem before.
} | ||
|
||
// WebGL 2 depth texture3D only support nearest filtering. See section 3.8.13 OpenGL ES 3 spec | ||
if (context.webgl2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
context.webgl2
is always true for a 3D texture, so we don't need to check it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right.
); | ||
} | ||
|
||
if (this._width > 1 && !CesiumMath.isPowerOfTwo(this._width)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this class assumes WebGL2, power-of-two sizes are not required. I think we can skip all 3 of these checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, power-of-two sizes are not mandatory to use WebGL2.
But I think we can keep a warning to warn developers that power-of-two values have better performance.
At the same time, avoid the situation where generateMipmap may truncate some mip levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do power-of-two sizes have better performance? I haven't been able to find a reference for this. Machines that support WebGL2 should be able to handle these sizes at the hardware level.
If we have evidence that there will be a performance impact, then
- We should add a warning for 2D textures too--
Texture.js
currently doesn't warn anything as long as the context is WebGL2. - It would be better to use
oneTimeWarning
to alert the user once, without filling up the console with too many duplicate messages.
@jjhembd Thank you so much for your meticulous review! The suggestions you put forward are both professional and practical, and I have benefited a great deal from them. To be honest, I didn't realize there were so many areas that needed improvement before. These valuable feedbacks are of great value to me. Once I have arranged my time, I will definitely implement and make the modifications item by item. Thank you sincerely again for your guidance and assistance! |
@jjhembd Thanks for reviewing and I fixed all the issues you raised. I hope you can review it again when you have time. This is really helpful to me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Hiwen for these updates! I think this is really close. I pushed an update with some minor formatting tweaks.
I just have one remaining question about power of two sizes.
); | ||
} | ||
|
||
if (this._width > 1 && !CesiumMath.isPowerOfTwo(this._width)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do power-of-two sizes have better performance? I haven't been able to find a reference for this. Machines that support WebGL2 should be able to handle these sizes at the hardware level.
If we have evidence that there will be a performance impact, then
- We should add a warning for 2D textures too--
Texture.js
currently doesn't warn anything as long as the context is WebGL2. - It would be better to use
oneTimeWarning
to alert the user once, without filling up the console with too many duplicate messages.
@jjhembd Thanks for review. Maybe I'm overthinking it. Currently, there is no direct evidence indicating that a non-power-of-two value will have any negative impact on the rendering effect. Let's remove these few unclear warnings. But I did a test. In GLSL, I used And for 100 x 100 x 100 3D Texture However, I'm still not sure what negative impacts this will have on rendering. Maybe there will be a slight jolt when switching levels? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Hiwen for the explanation! I see what you mean about truncation of mipmaps. I think in this case, it makes sense to leave the implementation details up to the browser or the user's operating system.
The authors of the WebGL2 spec apparently thought arbitrary dimensions wouldn't be a problem. As mentioned on a related thread for a different spec, if a GPU manufacturer was concerned about performance, they probably would have objected to the spec change. But they all agreed with the change, so any problems must have been already taken care of on the hardware or driver.
Thanks again for all your work on this! It's a big step forward for the code. I'm looking forward to further improvements we can implement, building on this new Texture3D
class.
Thanks again @jjhembd. This PR was a wonderful journey for me. |
thx for the work, can you put the sandcastle into : https://sandcastle.cesium.com/ i don't see volume cloud example |
It is in the "Development" section, which is not shown by default (not even when "All" is selected). You can select it manually, via (It should/could probably be moved to a different, more visible section in the next release. That cloud looks pretty cool...) |
I will do it |
Description
I extended the support for 3D Texture and ported the volumetric cloud example from Three.js to the sandbox. 3D Texture is widely used in volume rendering. With the support for 3D Texture, it will provide a basic support for this type of work.
Issue number and link
#12550
Testing plan
I added a sandbox example of volumetric clouds and improved the unit tests.
How to view sandbox examples:
Run
npm run release
Run
npm start
Navigate to
http://localhost:8080/Apps/Sandcastle/index.html?src=development%2FVolumeCloud.html
Author checklist
CONTRIBUTORS.md
CHANGES.md
with a short summary of my change