We develop complex WebGL powered application and offer our users an ability to save screenshot of the current scene. While this feature works as expected in Chrome and Firefox, we are facing several issues in safari.
Please take a look at the following code. As you can see, we use toDataURL() method of CanvasElement to make screenshots. While this code works as expected in other browsers, it produces wrong images in safari (at least for WebGL canvases).
You can easily reproduce the issue yourself by openning this file or running the attached code snippet in safari and other browsers.
Are we doing something wrong? Is there workaround for this issue?
Thank you.
UPD: Specially for those who say it is related to preserveDrawingBuffer i changed to attached code snippet to show that even with preserveDrawingBuffer set to true it still behaves wrong in safari.
<script type="text/javascript" src="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/webgl/resources/webgl-utils.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() {
gl_FragColor = vec4(0,1,0,1); // green
}
</script>
<div>
<canvas id="canvas1" width="300" height="300"></canvas>
<img id="img1"/>
</div>
<div>
<canvas id="canvas2" width="300" height="300"></canvas>
<img id="img2"/>
</div>
<div>
<canvas id="canvas3" width="300" height="300"></canvas>
<img id="img3"/>
</div>
<div>
<canvas id="canvas4" width="300" height="300"></canvas>
<img id="img4"/>
</div>
<div>
<canvas id="canvas5" width="300" height="300"></canvas>
<img id="img5"/>
</div>
<div>
<canvas id="canvas6" width="300" height="300"></canvas>
<img id="img6"/>
</div>
<script type="text/javascript">
function test(canvas, img, premultipliedAlpha, alpha, preserveDrawingBuffer) {
var gl = canvas.getContext("experimental-webgl", {
premultipliedAlpha: premultipliedAlpha,
alpha: alpha,
preserveDrawingBuffer: preserveDrawingBuffer
});
var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, [vertexShader, fragmentShader]);
gl.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, -1.0,
1.0, 1.0]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 5);
img.src = canvas.toDataURL();
}
window.onload = function() {
test(document.getElementById("canvas1"), document.getElementById("img1"), true, true, false);
test(document.getElementById("canvas2"), document.getElementById("img2"), false, true, false);
test(document.getElementById("canvas3"), document.getElementById("img3"), false, false, false);
test(document.getElementById("canvas4"), document.getElementById("img4"), true, true, true);
test(document.getElementById("canvas5"), document.getElementById("img5"), false, true, true);
test(document.getElementById("canvas6"), document.getElementById("img6"), false, false, true);
};
</script>