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

Remove dependence on WEBGL_color_buffer_float for EDL #6801

Merged
merged 3 commits into from
Jul 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Change Log
* Fixed a bug where 3D Tilesets using the `region` bounding volume don't get transformed when the tileset's `modelMatrix` changes. [6755](https://github.com/AnalyticalGraphicsInc/cesium/pull/6755)
* Fixed `PolygonGeometry` and `EllipseGeometry` tangent and bitangent attributes when a texture rotation is used [#6788](https://github.com/AnalyticalGraphicsInc/cesium/pull/6788)
* Fixed an issue where tiles were missing in VR mode. [#6612](https://github.com/AnalyticalGraphicsInc/cesium/issues/6612)
* Fixed a bug that caused eye dome lighting for point clouds to fail in Safari on macOS and Edge on Windows by removing the dependency on floating point color textures. [#6792](https://github.com/AnalyticalGraphicsInc/cesium/issues/6792)

### 1.47 - 2018-07-02

Expand Down
70 changes: 27 additions & 43 deletions Source/Scene/PointCloudEyeDomeLighting.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ define([

/**
* Eye dome lighting. Does not support points with per-point translucency, but does allow translucent styling against the globe.
* Requires support for EXT_frag_depth, OES_texture_float, and WEBGL_draw_buffers extensions in WebGL 1.0.
* Requires support for EXT_frag_depth and WEBGL_draw_buffers extensions in WebGL 1.0.
*
* @private
*/
function PointCloudEyeDomeLighting() {
this._framebuffer = undefined;
this._colorTexture = undefined; // color gbuffer
this._ecAndLogDepthTexture = undefined; // depth gbuffer
this._colorGBuffer = undefined; // color gbuffer
this._depthGBuffer = undefined; // depth gbuffer
this._depthTexture = undefined; // needed to write depth so camera based on depth works
this._drawCommand = undefined;
this._clearCommand = undefined;
Expand All @@ -77,14 +77,14 @@ define([
return;
}

processor._colorTexture.destroy();
processor._ecAndLogDepthTexture.destroy();
processor._colorGBuffer.destroy();
processor._depthGBuffer.destroy();
processor._depthTexture.destroy();
framebuffer.destroy();

processor._framebuffer = undefined;
processor._colorTexture = undefined;
processor._ecAndLogDepthTexture = undefined;
processor._colorGBuffer = undefined;
processor._depthGBuffer = undefined;
processor._depthTexture = undefined;
processor._drawCommand = undefined;
processor._clearCommand = undefined;
Expand All @@ -94,22 +94,21 @@ define([
var screenWidth = context.drawingBufferWidth;
var screenHeight = context.drawingBufferHeight;

var colorTexture = new Texture({
var colorGBuffer = new Texture({
context : context,
width : screenWidth,
height : screenHeight,
pixelFormat : PixelFormat.RGBA,
// Firefox as of 57.02 throws FRAMEBUFFER_UNSUPPORTED 0x8CDD if this doesn't match what's in ecTexture
pixelDatatype : FeatureDetection.isFirefox() ? PixelDatatype.FLOAT : PixelDatatype.UNSIGNED_BYTE,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
sampler : createSampler()
});

var ecTexture = new Texture({
var depthGBuffer = new Texture({
context : context,
width : screenWidth,
height : screenHeight,
pixelFormat : PixelFormat.RGBA,
pixelDatatype : PixelDatatype.FLOAT,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
sampler : createSampler()
});

Expand All @@ -125,14 +124,14 @@ define([
processor._framebuffer = new Framebuffer({
context : context,
colorTextures : [
colorTexture,
ecTexture
colorGBuffer,
depthGBuffer
],
depthTexture : depthTexture,
destroyAttachments : false
});
processor._colorTexture = colorTexture;
processor._ecAndLogDepthTexture = ecTexture;
processor._colorGBuffer = colorGBuffer;
processor._depthGBuffer = depthGBuffer;
processor._depthTexture = depthTexture;
}

Expand All @@ -142,11 +141,11 @@ define([
var blendFS = PointCloudEyeDomeLightingShader;

var blendUniformMap = {
u_pointCloud_colorTexture : function() {
return processor._colorTexture;
u_pointCloud_colorGBuffer : function() {
return processor._colorGBuffer;
},
u_pointCloud_ecAndLogDepthTexture : function() {
return processor._ecAndLogDepthTexture;
u_pointCloud_depthGBuffer : function() {
return processor._depthGBuffer;
},
u_distancesAndEdlStrength : function() {
distancesAndEdlStrengthScratch.x = processor._radius / context.drawingBufferWidth;
Expand Down Expand Up @@ -184,13 +183,13 @@ define([
function createResources(processor, context) {
var screenWidth = context.drawingBufferWidth;
var screenHeight = context.drawingBufferHeight;
var colorTexture = processor._colorTexture;
var colorGBuffer = processor._colorGBuffer;
var nowDirty = false;
var resized = defined(colorTexture) &&
((colorTexture.width !== screenWidth) ||
(colorTexture.height !== screenHeight));
var resized = defined(colorGBuffer) &&
((colorGBuffer.width !== screenWidth) ||
(colorGBuffer.height !== screenHeight));

if (!defined(colorTexture) || resized) {
if (!defined(colorGBuffer) || resized) {
destroyFramebuffer(processor);
createFramebuffer(processor, context);
createCommands(processor, context);
Expand All @@ -200,7 +199,7 @@ define([
}

function isSupported(context) {
return context.floatingPointTexture && context.drawBuffers && context.fragmentDepth;
return context.drawBuffers && context.fragmentDepth;
}

PointCloudEyeDomeLighting.isSupported = isSupported;
Expand All @@ -210,39 +209,24 @@ define([
if (!defined(shader)) {
var attributeLocations = shaderProgram._attributeLocations;

var vs = shaderProgram.vertexShaderSource.clone();
var fs = shaderProgram.fragmentShaderSource.clone();

vs.sources = vs.sources.map(function(source) {
source = ShaderSource.replaceMain(source, 'czm_point_cloud_post_process_main');
return source;
});

fs.sources = fs.sources.map(function(source) {
source = ShaderSource.replaceMain(source, 'czm_point_cloud_post_process_main');
source = source.replace(/gl_FragColor/g, 'gl_FragData[0]');
return source;
});

vs.sources.push(
'varying vec3 v_positionEC; \n' +
'void main() \n' +
'{ \n' +
' czm_point_cloud_post_process_main(); \n' +
' v_positionEC = (czm_inverseProjection * gl_Position).xyz; \n' +
'}');
fs.sources.unshift('#extension GL_EXT_draw_buffers : enable \n');
fs.sources.push(
'varying vec3 v_positionEC; \n' +
'void main() \n' +
'{ \n' +
' czm_point_cloud_post_process_main(); \n' +
// Write log base 2 depth to alpha for EDL
' gl_FragData[1] = vec4(v_positionEC, log2(-v_positionEC.z)); \n' +
' gl_FragData[1] = czm_packDepth(gl_FragCoord.z); \n' +
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to still use a varying instead of gl_FragCoord.z, since apparently on some platforms this has the same precision problems as depth textures, but I couldn't get it to work for some reason... the EDL effect happened, but it seemed like the depth value was wrong in some places.

However! I've only observed the precision problem on newer iPads, and the iPad lacks other necessary extensions, so in practice it shouldn't make a difference to just use gl_FragCoord.z. It's also cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

'}');

shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', {
vertexShaderSource : vs,
vertexShaderSource : shaderProgram.vertexShaderSource,
fragmentShaderSource : fs,
attributeLocations : attributeLocations
});
Expand Down
41 changes: 22 additions & 19 deletions Source/Shaders/PostProcessStages/PointCloudEyeDomeLighting.glsl
Original file line number Diff line number Diff line change
@@ -1,52 +1,55 @@
#extension GL_EXT_frag_depth : enable

uniform sampler2D u_pointCloud_colorTexture;
uniform sampler2D u_pointCloud_ecAndLogDepthTexture;
uniform sampler2D u_pointCloud_colorGBuffer;
uniform sampler2D u_pointCloud_depthGBuffer;
uniform vec3 u_distancesAndEdlStrength;
varying vec2 v_textureCoordinates;

vec2 neighborContribution(float log2Depth, vec2 padding)
{
vec2 depthAndLog2Depth = texture2D(u_pointCloud_ecAndLogDepthTexture, v_textureCoordinates + padding).zw;
if (depthAndLog2Depth.x == 0.0) // 0.0 is the clear value for the gbuffer
{
return vec2(0.0); // throw out this sample
}
else
{
return vec2(max(0.0, log2Depth - depthAndLog2Depth.y), 1.0);
float depthOrLogDepth = czm_unpackDepth(texture2D(u_pointCloud_depthGBuffer, v_textureCoordinates + padding));
if (depthOrLogDepth == 0.0) { // 0.0 is the clear value for the gbuffer
return vec2(0.0);
}
vec4 eyeCoordinate = czm_windowToEyeCoordinates(v_textureCoordinates + padding, depthOrLogDepth);
return vec2(max(0.0, log2Depth - log2(-eyeCoordinate.z / eyeCoordinate.w)), 1.0);
}

void main()
{
vec4 ecAlphaDepth = texture2D(u_pointCloud_ecAndLogDepthTexture, v_textureCoordinates);
if (length(ecAlphaDepth.xyz) < czm_epsilon7)
float depthOrLogDepth = czm_unpackDepth(texture2D(u_pointCloud_depthGBuffer, v_textureCoordinates));

vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depthOrLogDepth);
eyeCoordinate /= eyeCoordinate.w;

float log2Depth = log2(-eyeCoordinate.z);

if (length(eyeCoordinate.xyz) < czm_epsilon7)
{
discard;
}

vec4 color = texture2D(u_pointCloud_colorTexture, v_textureCoordinates);
vec4 color = texture2D(u_pointCloud_colorGBuffer, v_textureCoordinates);

// sample from neighbors up, down, left, right
float distX = u_distancesAndEdlStrength.x;
float distY = u_distancesAndEdlStrength.y;

vec2 responseAndCount = vec2(0.0);

responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(0, distY));
responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(distX, 0));
responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(0, -distY));
responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(-distX, 0));
responseAndCount += neighborContribution(log2Depth, vec2(0, distY));
responseAndCount += neighborContribution(log2Depth, vec2(distX, 0));
responseAndCount += neighborContribution(log2Depth, vec2(0, -distY));
responseAndCount += neighborContribution(log2Depth, vec2(-distX, 0));

float response = responseAndCount.x / responseAndCount.y;
float shade = exp(-response * 300.0 * u_distancesAndEdlStrength.z);
color.rgb *= shade;
gl_FragColor = vec4(color);

#ifdef LOG_DEPTH
czm_writeLogDepth(1.0 + (czm_projection * vec4(ecAlphaDepth.xyz, 1.0)).w);
czm_writeLogDepth(1.0 + (czm_projection * vec4(eyeCoordinate.xyz, 1.0)).w);
#else
gl_FragDepthEXT = czm_eyeToWindowCoordinates(vec4(ecAlphaDepth.xyz, 1.0)).z;
gl_FragDepthEXT = czm_eyeToWindowCoordinates(vec4(eyeCoordinate.xyz, 1.0)).z;
#endif
}