GroundPrimitive not updated/rendered with custom shader

Hi Dev-Team,

I want to use custom shaded geometries draped over terrain and 3d tiles.

I use GroundPrimitive to get geometries clamped to the ground, but the groundprimitives are not triggered to get rendered with provided shader code. (my GPU supports 8-bit Stencil buffering)

It simply works (yellow ellipse) when using Primitive itself, but that’s not clamped to the ground this way. GroundPrimitive just rendered as default red colored ellipse.

Simple Code Example:

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

timeline: false,

shadows: true,

terrainShadows: Cesium.ShadowMode.ENABLED,

terrainProvider: Cesium.createWorldTerrain({

requestVertexNormals : true

})

});

var lon = -122.423;

var lat = 37.7728;

var instance = new Cesium.GeometryInstance({

geometry : new Cesium.EllipseGeometry({

center : Cesium.Cartesian3.fromDegrees(lon, lat),

semiMinorAxis : 120.0,

semiMajorAxis : 150.0,

rotation : 320,

vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT

}),

});

var myAppearance = new Cesium.EllipsoidSurfaceAppearance({

fragmentShaderSource :

‘void main() { \n’+

‘gl_FragColor = vec4(1.0, 1.0, 0.0, 0.5); \n’+

‘} \n’,

});

var ellipse = viewer.scene.primitives.add(new Cesium.GroundPrimitive({

geometryInstances : instance,

shadows : Cesium.ShadowMode.ENABLED,

appearance : myAppearance,

debugShowBoundingVolume : true

}));

var center = Cesium.Cartesian3.fromDegrees(lon, lat);

viewer.camera.lookAt(center, new Cesium.Cartesian3(30.0, 0.0, 4200.0));

Context

At the end I want to have shaded geometries over terrain and 3d tiles based on a light source next to the geometry. Simple case would be to decide whether a fragment is in shadow to the light source or not.

As I need to display multiple geometries from different light sources, using Shadowmap is not an option.

Version is 1.60

Questions

So why are the GroundPrimitives are not triggered to get rendered with custom shader source?

Do I need to load the groundprimitives from a DataSource instead? If so, what’s the reason behind that?

Any other way to achieve what I want?

any help would be appreciated

Many Thanks

Karsten

I think this is because a GroundPrimitive is actually an interface on top of ClassificationPrimitive, which is what handles the clamping to ground. So even though you’re passing an appearance it doesn’t get passed through here:

The other issue is that the clamping computations happen in the fragment shader, so if you completely overwrite the fragment shader with a custom one it would no longer work, so you could need to wrap it in a ShadowVolumeAppearance, which I believe is how the entity system allows you to set a custom texture or color on ground primitives:

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/ShadowVolumeAppearance.js

What kind of application are you working on? If it’s something that can be done from the entity system it’ll likely save you a lot of time (and perhaps it’s something the entity system can be extended to cover this use case?)

Hi Omar,

thanks for quick the reply.

It looks like the appearance is re-applied to the ground primitive on update.

https://github.com/AnalyticalGraphicsInc/cesium/blob/9d1d932dd172e056a8588c28001c18a934e712d2/Source/Scene/GroundPrimitive.js#L730

But still my appearance is not being used with the rendering. I assume it is rejected somewhere deep in the validation process of primitives’ type cascade (as the ground primitive is expected to render fragments on terrain).

As ShadowVolumeAppearance is not an appearance in a sense of cesium Appearance object, it only can be used to provide the shader code which on its part could be used with any cesium Appearance object like EllipseSurfaceAppearance.

Basically, I already have tried something like this while using ShadowMapShader. I requested the shader code from ShadowMapShader (expecting to contain the whole terrain stuff etc.) and passed it to EllipseSurfaceAppearance of the ground primitive, but here it comes to my root problem that the appearance isn’t being used with ground primitive.

When using complete provided ShadowMapShader/ShadowVolumeAppearance shader code, do I need to rely on ground primitive or can I use the generic primitive instead?

What I’m trying to achieve can be seen on the attached picture. I want to have a coverage analysis from multiple light sources, considering 3d tiles and terrain.

Do you have any code example/snippet on how to achieve that with exiting entity objects or else? (apart from manipulating the fragment shader when it comes to decide on color)

Thanks

Karsten

Thanks for the additional context Karsten! We actually have some of this functionality already built into the Analytics SDK (which is built on top of CesiumJS): https://cesium.com/ion-sdk/

At the time of writing, it can visualize coverage from multiple sensors, but the output colors are additive (so an area seen by one sensor but not the other will become red + green). I can give you an update once that case is better supported.

For a first prove of concept we do not need dynamic coverage. Each light source and its coverage will be static. It would be good to know whether such scenario is already somehow possible using CesiumJS and what cesium api to use best.
Later on we could move to the sdk for dynamic coverage and better performance when available.

Thanks
Karsten