Fix WebGL image layer rendering on retina displays

This commit takes the device pixel ratio into account when calculating the matrix used to apply the image to the output canvas.
This commit is contained in:
Éric Lemoine
2015-04-01 10:40:27 +02:00
parent 0789604e88
commit 9ce3bc7f3d
2 changed files with 21 additions and 15 deletions
@@ -102,6 +102,7 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
var gl = this.mapRenderer.getGL(); var gl = this.mapRenderer.getGL();
var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var viewCenter = viewState.center; var viewCenter = viewState.center;
var viewResolution = viewState.resolution; var viewResolution = viewState.resolution;
@@ -131,7 +132,7 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
projection = sourceProjection; projection = sourceProjection;
} }
var image_ = imageSource.getImage(renderedExtent, viewResolution, var image_ = imageSource.getImage(renderedExtent, viewResolution,
frameState.pixelRatio, projection); pixelRatio, projection);
if (!goog.isNull(image_)) { if (!goog.isNull(image_)) {
var loaded = this.loadImage(image_); var loaded = this.loadImage(image_);
if (loaded) { if (loaded) {
@@ -160,7 +161,8 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
var canvas = this.mapRenderer.getContext().getCanvas(); var canvas = this.mapRenderer.getContext().getCanvas();
this.updateProjectionMatrix_(canvas.width, canvas.height, this.updateProjectionMatrix_(canvas.width, canvas.height,
viewCenter, viewResolution, viewRotation, image.getExtent()); pixelRatio, viewCenter, viewResolution, viewRotation,
image.getExtent());
this.hitTransformationMatrix_ = null; this.hitTransformationMatrix_ = null;
// Translate and scale to flip the Y coord. // Translate and scale to flip the Y coord.
@@ -183,6 +185,7 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
/** /**
* @param {number} canvasWidth Canvas width. * @param {number} canvasWidth Canvas width.
* @param {number} canvasHeight Canvas height. * @param {number} canvasHeight Canvas height.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.Coordinate} viewCenter View center. * @param {ol.Coordinate} viewCenter View center.
* @param {number} viewResolution View resolution. * @param {number} viewResolution View resolution.
* @param {number} viewRotation View rotation. * @param {number} viewRotation View rotation.
@@ -190,8 +193,8 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
* @private * @private
*/ */
ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ =
function(canvasWidth, canvasHeight, viewCenter, function(canvasWidth, canvasHeight, pixelRatio,
viewResolution, viewRotation, imageExtent) { viewCenter, viewResolution, viewRotation, imageExtent) {
var canvasExtentWidth = canvasWidth * viewResolution; var canvasExtentWidth = canvasWidth * viewResolution;
var canvasExtentHeight = canvasHeight * viewResolution; var canvasExtentHeight = canvasHeight * viewResolution;
@@ -199,7 +202,8 @@ ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ =
var projectionMatrix = this.projectionMatrix; var projectionMatrix = this.projectionMatrix;
goog.vec.Mat4.makeIdentity(projectionMatrix); goog.vec.Mat4.makeIdentity(projectionMatrix);
goog.vec.Mat4.scale(projectionMatrix, goog.vec.Mat4.scale(projectionMatrix,
2 / canvasExtentWidth, 2 / canvasExtentHeight, 1); pixelRatio * 2 / canvasExtentWidth,
pixelRatio * 2 / canvasExtentHeight, 1);
goog.vec.Mat4.rotateZ(projectionMatrix, -viewRotation); goog.vec.Mat4.rotateZ(projectionMatrix, -viewRotation);
goog.vec.Mat4.translate(projectionMatrix, goog.vec.Mat4.translate(projectionMatrix,
imageExtent[0] - viewCenter[0], imageExtent[0] - viewCenter[0],
@@ -6,6 +6,7 @@ describe('ol.renderer.webgl.ImageLayer', function() {
var renderer; var renderer;
var canvasWidth; var canvasWidth;
var canvasHeight; var canvasHeight;
var pixelRatio;
var viewResolution; var viewResolution;
var viewRotation; var viewRotation;
var viewCenter; var viewCenter;
@@ -27,6 +28,7 @@ describe('ol.renderer.webgl.ImageLayer', function() {
// input params // input params
canvasWidth = 512; canvasWidth = 512;
canvasHeight = 256; canvasHeight = 256;
pixelRatio = 2;
viewResolution = 10; viewResolution = 10;
viewRotation = 0; viewRotation = 0;
viewCenter = [7680, 3840]; viewCenter = [7680, 3840];
@@ -44,7 +46,7 @@ describe('ol.renderer.webgl.ImageLayer', function() {
it('produces a correct matrix', function() { it('produces a correct matrix', function() {
renderer.updateProjectionMatrix_(canvasWidth, canvasHeight, renderer.updateProjectionMatrix_(canvasWidth, canvasHeight,
viewCenter, viewResolution, viewRotation, imageExtent); pixelRatio, viewCenter, viewResolution, viewRotation, imageExtent);
var matrix = renderer.getProjectionMatrix(); var matrix = renderer.getProjectionMatrix();
var input; var input;
@@ -52,27 +54,27 @@ describe('ol.renderer.webgl.ImageLayer', function() {
input = goog.vec.Vec4.createFromValues(-1, -1, 0, 1); input = goog.vec.Vec4.createFromValues(-1, -1, 0, 1);
goog.vec.Mat4.multVec4(matrix, input, output); goog.vec.Mat4.multVec4(matrix, input, output);
expect(output[0]).to.eql(-3); expect(output[0]).to.eql(-6);
expect(output[1]).to.eql(-3); expect(output[1]).to.eql(-6);
input = goog.vec.Vec4.createFromValues(1, -1, 0, 1); input = goog.vec.Vec4.createFromValues(1, -1, 0, 1);
goog.vec.Mat4.multVec4(matrix, input, output); goog.vec.Mat4.multVec4(matrix, input, output);
expect(output[0]).to.eql(1); expect(output[0]).to.eql(2);
expect(output[1]).to.eql(-3); expect(output[1]).to.eql(-6);
input = goog.vec.Vec4.createFromValues(-1, 1, 0, 1); input = goog.vec.Vec4.createFromValues(-1, 1, 0, 1);
goog.vec.Mat4.multVec4(matrix, input, output); goog.vec.Mat4.multVec4(matrix, input, output);
expect(output[0]).to.eql(-3); expect(output[0]).to.eql(-6);
expect(output[1]).to.eql(3); expect(output[1]).to.eql(6);
input = goog.vec.Vec4.createFromValues(1, 1, 0, 1); input = goog.vec.Vec4.createFromValues(1, 1, 0, 1);
goog.vec.Mat4.multVec4(matrix, input, output); goog.vec.Mat4.multVec4(matrix, input, output);
expect(output[0]).to.eql(1); expect(output[0]).to.eql(2);
expect(output[1]).to.eql(3); expect(output[1]).to.eql(6);
input = goog.vec.Vec4.createFromValues(0, 0, 0, 1); input = goog.vec.Vec4.createFromValues(0, 0, 0, 1);
goog.vec.Mat4.multVec4(matrix, input, output); goog.vec.Mat4.multVec4(matrix, input, output);
expect(output[0]).to.eql(-1); expect(output[0]).to.eql(-2);
expect(output[1]).to.eql(0); expect(output[1]).to.eql(0);
}); });
}); });