CustomShader that moves vertices of imported object

I’m trying to implement a CustomShader with a vertex shader that would let me “wobble” the individual vertices on an imported GLB object.

As an example of what I mean, if you go to Three.js’ editor and click Examples > Shaders, it’ll call up a crazy rainbow geometric thing. Click “Play” in the menu and it’ll start wobbling. Look at it wobble!

The relevant OpenGL shader can be viewed/edited by clicking on the Isosahedron 1 object in the Scene, then clicking the GEOMETRY tab, then clicking SCRIPT > EDIT. There is this function that sets a uniform called time:

function update( event ) {

	this.material.uniforms.time.value = event.time / 500.0;

}

And then if you click MATERIAL > VERT it has the function that changes the position of the vertexes as a function of time:

uniform float time;
varying vec3 vPosition;
void main() {
	vPosition = position;
	vPosition.x += sin( time + vPosition.z * 4.0 ) / 4.0;
	vPosition.y += cos( time + vPosition.z * 4.0 ) / 4.0;
	gl_Position = projectionMatrix * modelViewMatrix * vec4( vPosition, 1.0 );
}

Which is pretty neat in its simplicity – it grabs each vertex, alters its x and y positions as a function of the z position and time, and then sends that back to the output.

I’ve done a lot of Googling relating to CustomShader and vertexShaderText but found almost no documentation as to what objects exist to be called by it. The relevant doc page gives some tantalizing hints, but I’ve found nothing explaining much of this. What can one access in vsInput? What is vsOutput.positionMC looking for? (What’s the MC stand for?) Etc. etc.

If someone could give me a little hint, or point me in the right direction, I’d be super thrilled.

The use case for this: I am creating a cloud from a GLB model in a Cesium environment, and I’d like its vertices to sort of wobble convincingly. This seems like something that is a perfect fit for a vertex shader. I’ve been able to do this very nicely with the Three.js editor, but I can’t seem to figure out how to implement a similar function in Cesium.

Thanks so much. I am aware that CustomShader is marked as “experimental” and my hopes for documentation should be accordingly low! :slight_smile:

Hi,

just to make sure, did you already find the Custom Shader Guide? :slight_smile:

It’s a more or less extensive write up about all the structs etc. that are usable in custom shaders.

One thing I can answer directly:
I am pretty sure positionMC stands for position model coordinates.
You can find that here: cesium/Documentation/CustomShaderGuide at main · CesiumGS/cesium · GitHub

What I often did in the last months was to additionally search the Cesium source (and sometimes I even printed the finished shader code to console by adding some console.log() to the Cesium source running locally). This is a bit cumbersome, but as you said, I guess that documentation will hopefully be enhanced in the future. There are also some interesting builtin functions/variables that event existed before the new custom shader functionality and that were never documented. Maybe this will also change now, that we are able to easily add shader code.

So, this is not really an extensive answer for your problem, but unfortunately I don’t have enough time right now to properly create something more sophisticated, sorry!
However, maybe this already helps you to go into the right direction a bit.

An addition to my previous answer:
I just remembered that there is also an official sandcastle demo of manipulation of vertices in the shader.
This will probably help you a bit more:

In the top-left of the viewer you find a dropdown. The last entry (“Animated Point Cloud”) is a demo of manipulation of some point cloud points in the vertex shader. You can find the corresponding code on the left.
This should also work with models that are not points clouds (on the vertices of that model).

This is all ENORMOUSLY helpful. Thank you. I did not see that guide or those Sandcastles, which were PERFECT.

Here’s a very simpified Sandcastle for the sort of thing I was trying to do, for anyone’s future reference.

1 Like

Hi @Nucleon, welcome to the forum!

First of all, glad to see you found the documentation (thanks @UniquePanda for pointing it out!). I tried your Sandcastle, it looks really neat!

Just to follow up about a couple points:

  • While writing this “wobble” vertex shader, one corner case to watch out for: a little bit of expanding the vertices is fine, but too much (straying outside the original bounding sphere) may result in clipping artifacts depending on the camera view. However, it’s always safe to move the vertices closer together/within the original bounds. So if you ever run into issues with this, one idea is to make the initial positions in the GLB more spread out and then wobble inwards.
  • In response to @UniquePanda’s point about viewing the full shader, there’s a couple ways to do this without needing console.log():
    • In the September release, if a shader has compile errors it will now be logged to the console (see Fix debugShaders output when shaders fail to compile by jjhembd · Pull Request #10629 · CesiumGS/cesium · GitHub)
    • There are WebGL debugging tools (such as the SpectorJS browser extension) that let you see the final shader for each draw call.
    • Note that in both cases, the full shader includes many private API details that are subject to change. Nevertheless, sometimes it’s helpful to see the full context of the shader (CustomShader is just one part of a larger shading pipeline)

Best,
Peter

2 Likes

Thanks, Peter! So far I have not run into the bounding sphere issue, but it may just be I am not moving them far enough to matter (my vertex movements are much more subtle, at the moment, than even the one I put in the sandcastle, which I exaggerated for effect).

I am still playing with the shaders and will probably have more questions about them in the future! But being pointed towards the correct documentation has helped a lot, as well as having some examples to iterate on. Ultimately I would like to try and implement something like the cloud effect here (ignore the wildly rotating spikeball — which most of that shader code is dedicated to constructing — and just note how with a little bit of noise it blurs the edges in an interesting way, and that it is doing all of that work with what looks like just three functions), though I am not sure that is possible with Cesium. But I’m willing to bang my head against it for a little bit to see!

I don’t have a great sense of what the limits are to how Cesium implements shaders, and given how little I understand them by themselves, and so making the jump from some of those crazy Shadertoy ones to something I can use seems perhaps a bit beyond me. The spikeball one one seemed comparatively simple, because it is really just acting upon an object, and using very few functions (especially if you use the “old” noise function in it), rather than some of them that are doing very scene-intensive calculations and using lots of external noise generators and so on, like this amazing one that just breaks my brain when I try to make sense of everything it is doing.

There seems to be not that many examples out there of clever uses of vertex shaders for Cesium at the moment, but it is impressive what can be done!