Skip to content
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

Extend GroundPrimitive shadow volume based on screen space error #4751

Merged
merged 20 commits into from
Jan 6, 2017

Conversation

hpinkos
Copy link
Contributor

@hpinkos hpinkos commented Dec 13, 2016

Fixes #4326
Fixes #4161

This extends the bottom of the shadow volume below the terrain based on the screen space error. The shadow volume is updated in the ShadowVolume vertex shader.

  • Ground primitives geometry types compute a extrudeDirection attribute. The extudeDirection is a normalized vector pointing in the direction in which the position should be moved in the vertex shader.
    • Positions at the top of the shadow volume will have extrudeDirection === Cartesian3.ZERO because only the bottom positions need to be moved
  • Added czm_geometricToleranceOverDistance to AutomaticUniforms
  • Added pixelSizePerMeter and maximumScreenSpaceError to UniformState
    • scene.globe.maximumScreenSpaceError get piped through to UniformState via the frameState. Not sure if that's the best way to do this.
  • Added u_globeMinimumAltitude to GroundPrimitive.uniforms.
    • I set this to 33000.0, which is a magic number I found with testing. I'm not sure what this value should actually be.
    • I made this a positive number so I don't have to abs it later when i find the min between this value and the value computed using the screen space error.

TODO

  • Fix debugShowShadowVolume so it displays the shadow volume after the positions have been updated in the shader
  • octencode extrudeDirection attribute
  • Update CHANGES.md

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Ground primitives geometry types compute a extrudeDirection attribute.

Let's octencode this. See AttributeCompression.js.

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

I set this to 33000.0, which is a magic number I found with testing. I'm not sure what this value should actually be.

This should come from the terrain provider, but we can hard code it to the right min for Earth for now. @bagnell do you have it handy from STK?

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Positions at the top of the shadow volume will have extrudeDirection === Cartesian3.ZERO because only the bottom positions need to be moved

@lilleyse @bagnell do you guys have any ideas on how to avoid this wasted memory without introducing another draw call per volume?

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Update CHANGES.md.

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Positions at the top of the shadow volume will have extrudeDirection === Cartesian3.ZERO because only the bottom positions need to be moved

@lilleyse @bagnell do you guys have any ideas on how to avoid this wasted memory without introducing another draw call per volume?

Related idea: at one point, I just tried to normalize the WGS84 position, to avoid storing an extra attribute, and it was very noticeably wrong at places like Mount Saint Helens. However, perhaps there is another way to compute a better approximation, but still not perfect.

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Also with that same example, the corridor and circle disappear when zoomed out.

bv

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

@hpinkos did you try using GroundPrimitive.debugShowShadowVolume to verify that the volumes are as low as they need to be (so it renders correctly), but not much lower (to avoid fillrate)?

* @alias czm_geometricToleranceOverDistance
* @glslUniform
*/
czm_geometricToleranceOverDistance : new AutomaticUniform({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Distance -> Meter


var fov = camera.frustum.fov;
var viewport = this._viewport;
if (viewport.width > viewport.height * camera.frustum.aspectRatio) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this check work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just a straight port. Did I misinterpreted something? Here's the original source:

    if ((double)mainViewport[3] > ((double)mainViewport[2] * p3dScene->pixelAspect))
    {
        pixelSizePerDistance = tan(0.5 * p3dScene->view.m_pCamera->FieldOfView()) * 2.0 / (double)mainViewport[3];
    }
    else
    {
        pixelSizePerDistance = tan(0.5 * p3dScene->view.m_pCamera->FieldOfView()) * 2.0 / (double)mainViewport[2];
    }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure mainViewport[3] is width? In Cesium, the array would be [x, y, width, height].

Are you sure pixelAspect ratio is width / height like aspectRatio?

Perhaps ask Greg to double check these.

Right now, I think the if statements reads like "if (width > (height * (width / height))", which is "if (width > width)"

float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverDistance * length(position.xyz));

//extrudeDirection is zero for the top layer
position = position + vec4(extrudeDirection.xyz * delta, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 0.0, mixing integers and floats didn't use to compile on some WebGL implementations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extrudeDirection is a vec3 so we can remove the .xyz .

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

What do you think about cleaning up the geometry types by adding adding a temporary BOTTOM (or whatever) attribute then running the Geometry through a generic function that removes that attribute and adds the extruded normal? It would come at a potential small performance and GC cost but could be worth it.

@bagnell what do you think about this for vector tiles? Seems like we don't need to store the extruded direction in the payload. We could even separate out the bottom cap vertices so the BOTTOM attribute is implicit over the wire.

I feel like we should do some fill rate tests before getting into all this. This should make a huge difference for horizon and 45 degree views depending on how well early-z does (even with early-z the rasterization load is very high).

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 14, 2016

Just those comments for now.

@hpinkos this will be a much appreciated fix!

@hpinkos
Copy link
Contributor Author

hpinkos commented Dec 19, 2016

Here is a visualization of the shadow volume. The blue is the old volume and the red is the new one. It just extends a little bit below what we were doing previously

large polygon:
image

small rectangle:
image

@hpinkos
Copy link
Contributor Author

hpinkos commented Dec 19, 2016

@pjcozzi I believe I addressed your comments and fixed the problems you found with some of the geometries.

I haven't done the octencodeing yet because I'm waiting to see if we want to change the extrudeDirection attribute

@bagnell bagnell mentioned this pull request Jan 4, 2017
2 tasks
@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 4, 2017

Fix debugShowShadowVolume so it displays the shadow volume after the positions have been updated in the shader

Added in 2d50df1.

This restriction was removed:

Must be true on creation for the volumes to be created before the geometry is released or releaseGeometryInstances must be false

But the polygon is no longer drawn when the volume is drawn.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 4, 2017

I haven't done the octencodeing yet because I'm waiting to see if we want to change the extrudeDirection attribute

Let's just move forward so we don't stall this. We can optimize later if we come up with a good idea.

size: 1,
datatype: WebGLConstants.FLOAT,
getValue: function(uniformState) {
return uniformState.pixelSizePerMeter * uniformState.maximumScreenSpaceError;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is constant per frame, right? Precompute and store in UniformState.

* @type {Number}
* @default 2
*/
maximumScreenSpaceError: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two getters may not be needed after the about change.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 4, 2017

Just those comments.

@hpinkos
Copy link
Contributor Author

hpinkos commented Jan 4, 2017

@pjcozzi this is ready for another look. I fix the issues you pointed out and I added octencode for the new attribute. And I updated CHANGES.md

@bagnell
Copy link
Contributor

bagnell commented Jan 4, 2017

Oct-encoding is fine for lighting because the error isn't noticeable but it may be noticeable for geometry extruded with these normals. Have you seen this at all?

@hpinkos
Copy link
Contributor Author

hpinkos commented Jan 4, 2017

I didn't see any noticeable errors, but I'll look more closely to make sure

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 4, 2017

Oct-encoding is fine for lighting because the error isn't noticeable but it may be noticeable for geometry extruded with these normals

How many bits are we using? It should be OK if we use enough....more than lighting. For example, normals for rotation of instances in i3dm use 32: https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/TileFormats/Instanced3DModel#oct-encoded-normal-vectors

The paper has exact error bounds.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 5, 2017

Bump:

Oct-encoding is fine for lighting because the error isn't noticeable but it may be noticeable for geometry extruded with these normals
How many bits are we using? It should be OK if we use enough....more than lighting. For example, normals for rotation of instances in i3dm use 32: https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/TileFormats/Instanced3DModel#oct-encoded-normal-vectors

The paper has exact error bounds.

@bagnell
Copy link
Contributor

bagnell commented Jan 5, 2017

It uses AttributeCompression.octEncodeFloat which is oct16P in the paper (the same we use for lighting). If you want to use higher precision, take a look at octEncodeInRange.

@hpinkos
Copy link
Contributor Author

hpinkos commented Jan 5, 2017

Thanks @bagnell, @pjcozzi, I'll update it to use 32

@hpinkos
Copy link
Contributor Author

hpinkos commented Jan 5, 2017

@pjcozzi @bagnell ready

* @param {float} range The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
* @returns {vec3} The decoded and normalized vector
*/
vec3 czm_octDecode(vec2 encoded, float range)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be pleasantly surprised if JSDoc handles function overloads, but it's not an issue now.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 5, 2017

Do you get these artifacts? If so, do you also get them without normal compression?

ok2

If these are due to normal compression, is there anything we can do about it? Are we sure the code is right? Is there a more precise (48 bits?) version from the paper we can try?

@hpinkos
Copy link
Contributor Author

hpinkos commented Jan 6, 2017

@pjcozzi no I don't see that on my machine. That's happening after the 32P update?

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 6, 2017

I don't get this on Windows. Will test Mac/Intel now, hopefully the artifact is in master.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 6, 2017

Good news, it is in master. See #4820

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 6, 2017

OK, this is good!

Please reply to all the forum threads. People will be thrilled!

@pjcozzi pjcozzi merged commit 7253588 into master Jan 6, 2017
@pjcozzi pjcozzi deleted the ground-primitive-sse branch January 6, 2017 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants