Skip to content

Commit

Permalink
Merge pull request #714 from AnalyticalGraphicsInc/reprojectInVertexS…
Browse files Browse the repository at this point in the history
…hader

Reproject imagery in the vertex shader instead of FS.
  • Loading branch information
shunter committed Apr 30, 2013
2 parents 9df235a + aa49715 commit 200d332
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Beta Releases
* Improved rendering performance by minimizing WebGL state calls.
* Fixed an error in Web Worker creation when loading Cesium.js from a different origin.
* Fixed `EllipsoidPrimitive` picking and picking objects with materials that have transparent parts.
* Fixed imagery smearing artifacts on mobile devices and other devices without high-precision fragment shaders.

### b15 - 2013-04-01

Expand Down
31 changes: 28 additions & 3 deletions Source/Scene/ImageryLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ define([
'./TileProviderError',
'./ImageryState',
'./TileImagery',
'./TerrainProvider',
'./TexturePool',
'../ThirdParty/when',
'../Shaders/ReprojectWebMercatorFS',
Expand Down Expand Up @@ -51,6 +52,7 @@ define([
TileProviderError,
ImageryState,
TileImagery,
TerrainProvider,
TexturePool,
when,
ReprojectWebMercatorFS,
Expand Down Expand Up @@ -778,14 +780,37 @@ define([
reproject.framebuffer = context.createFramebuffer();
reproject.framebuffer.destroyAttachments = false;

// We need a vertex array with close to one vertex per output texel because we're doing
// the reprojection by computing texture coordinates in the vertex shader.
// If we computed Web Mercator texture coordinate per-fragment instead, we could get away with only
// four vertices. Problem is: fragment shaders have limited precision on many mobile devices,
// leading to all kinds of smearing artifacts. Current browsers (Chrome 26 for example)
// do not correctly report the available fragment shader precision, so we can't have different
// paths for devices with or without high precision fragment shaders, even if we want to.

var positions = new Array(256 * 256 * 2);
var index = 0;
for (var j = 0; j < 256; ++j) {
var y = j / 255.0;
for (var i = 0; i < 256; ++i) {
var x = i / 255.0;
positions[index++] = x;
positions[index++] = y;
}
}

var reprojectMesh = {
attributes : {
position : {
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
values : positions
}
}
},
indexLists : [{
primitiveType : PrimitiveType.TRIANGLES,
values : TerrainProvider.getRegularGridIndices(256, 256)
}]
};

var reprojectAttribInds = {
Expand Down Expand Up @@ -870,7 +895,7 @@ define([
framebuffer : reproject.framebuffer,
shaderProgram : reproject.shaderProgram,
renderState : reproject.renderState,
primitiveType : PrimitiveType.TRIANGLE_FAN,
primitiveType : PrimitiveType.TRIANGLES,
vertexArray : reproject.vertexArray,
uniformMap : uniformMap
});
Expand Down
20 changes: 1 addition & 19 deletions Source/Shaders/ReprojectWebMercatorFS.glsl
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
uniform sampler2D u_texture;

uniform float u_northLatitude;
uniform float u_southLatitude;
uniform float u_southMercatorYHigh;
uniform float u_southMercatorYLow;
uniform float u_oneOverMercatorHeight;

varying vec2 v_textureCoordinates;

void main()
{
// The clamp below works around an apparent bug in Chrome Canary v23.0.1241.0
// where the fragment shader sees textures coordinates < 0.0 and > 1.0 for the
// fragments on the edges of tiles even though the vertex shader is outputting
// coordinates strictly in the 0-1 range.
vec2 geographicUV = clamp(v_textureCoordinates, 0.0, 1.0);
vec2 webMercatorUV = geographicUV;

float currentLatitude = mix(u_southLatitude, u_northLatitude, geographicUV.y);
float fraction = czm_latitudeToWebMercatorFraction(currentLatitude, u_southMercatorYLow, u_southMercatorYHigh, u_oneOverMercatorHeight);

webMercatorUV = vec2(geographicUV.x, fraction);

gl_FragColor = texture2D(u_texture, webMercatorUV);
gl_FragColor = texture2D(u_texture, v_textureCoordinates);
}
10 changes: 9 additions & 1 deletion Source/Shaders/ReprojectWebMercatorVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ attribute vec4 position;

uniform vec2 u_textureDimensions;

uniform float u_northLatitude;
uniform float u_southLatitude;
uniform float u_southMercatorYHigh;
uniform float u_southMercatorYLow;
uniform float u_oneOverMercatorHeight;

varying vec2 v_textureCoordinates;

void main()
{
v_textureCoordinates = position.xy;
float currentLatitude = mix(u_southLatitude, u_northLatitude, position.y);
float fraction = czm_latitudeToWebMercatorFraction(currentLatitude, u_southMercatorYLow, u_southMercatorYHigh, u_oneOverMercatorHeight);
v_textureCoordinates = vec2(position.x, fraction);
gl_Position = czm_viewportOrthographic * (position * vec4(u_textureDimensions, 1.0, 1.0));
}

0 comments on commit 200d332

Please sign in to comment.