CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.75k stars 3.46k forks source link

Supply both slope and aspect to shader in radians #7409

Open spencerparkin opened 5 years ago

spencerparkin commented 5 years ago

The czm_materialInput.slope parameter should be in radians. To fix this, simply return the arc-cosine of the currently computed slope. Also, there should be a czm_materialInput.aspect parameter supplied to the shader that is also in radians. Zero radians should mean East, pi/2 radians should mean North, pi radians should mean West, and 3pi/2 radians should mean South.

I have forked the cesium repo and am trying to get a pull-request together for this new feature. The math is not hard given the needed inputs for the calculation. The challenge is getting those inputs.

Can anyone concur that this is a good idea? I really need aspect along with slope in a Cesium-based project I am currently working on.

spencerparkin commented 5 years ago

Here is my feature branch:

https://github.com/spencerparkin/cesium/tree/slope-and-aspect

I really think that it would be useful to add aspect information.

hpinkos commented 5 years ago

This sounds great @spencerparkin! Looking forward to your pull request =)

Good catch with the slope fix. Can you open a separate pull request for that? That way we can get that fix in without having to wait for aspect.

For reference, @jasonbeverage added slope in #5919

jasonbeverage commented 5 years ago

Hi @spencerparkin!

I'm not sure if changing the slope to be in radians instead of normalized between 0 to 1 really buys you anything since it's currently just used for a texture lookup which maps nicely to 0 to 1. With your change it's going to be adding an additional acos computation for each vert in the vertex shader only then to convert it back to a value between 0 and 1 here: https://github.com/spencerparkin/cesium/commit/ce39cda3336b4ed00d696f04089f13a2159d9f47#diff-6297e80982885125ce2cd29093404aceR6.

I believe the aspect you're talking about is similar to the curvature that we compute in osgearth using this code: https://github.com/gwaldron/osgearth/blob/master/src/osgEarth/HeightFieldUtils.cpp#L748-L752 The curvature is encoded alongside a normal map in osgearth.

osgearth uses regularly spaces heightfields so we can precompute the curvature by looping over the entire heightfield. This might not be as simple in Cesium to do at runtime as it's using a TIN for it's meshes, it might be cool to add the curvature as an extension to the quantized mesh format and compute it at tile generation time instead.

spencerparkin commented 5 years ago

The current slope calculation is in [0,1], but it is not a linear scale. You need the arc-cosine to get a uniform linear scale between flat and vertical. If you need me to explain this in greater detail, I can try. I've also often been of the mind that GPUs are fast enough that an extra trig operation shouldn't be worrisome, but maybe we still have to be frugal about that kind of stuff? One other arc-cosine will be needed for the aspect calculation. Maybe we could provide slope and aspect only in a material derivative of the built-in terrain material. This keeps the base terrain material lean and mean while allowing for a heavier terrain material option.

Getting the aspect will only require knowing where true east is in the tangent space of the vertex. From there it is a straight-forward calculation involving that, the terrain normal, and the ellipsoid normal.

I'll take it as far as I can, then try to split it out into separate pull requests if we still think it's a good idea.

I'll have to study the osgearth stuff...I'm completely unfamiliar with that. In any case, it doesn't make sense to me to provide slope, but not aspect in the material input. They kind of go together.

spencerparkin commented 5 years ago

Okay, here is my latest commit that gives you an idea of the proposed modifications to the GlobeVS.glsl file.

https://github.com/spencerparkin/cesium/commit/8452c23535c63735646cf8c45f5d138bcaf70eb6

Thanks for any time you spend looking at it.

It has occurred to me that if all the uniform and other globals are available to me in my fabric, then maybe I don't need to try to get a new feature into Cesium. I can just calculate slope and aspect in my own custom shader.

All that remains in the code above is to calculate due east in the tangent space at the vertex (in model space). This can be done with a simple cross product if we know where the north pole of the globe is at in model coordinates. I presume that it's something like (0,1,0).

spencerparkin commented 5 years ago

@jasonbeverage, no I don't think it's like curvature. It's simply the direction (e.g. north-east) a ski slope is facing, for example.

Once I get to a point where I can test and verify my changes, I'll open a pull request. One of the sand-castle demos will do nicely, and I have already added a test-case to it.

One argument for keeping the arc-cosine in the vertex shader is to prevent a need for it in the fragment shader where it will have to be performed more often.