I am able to zoom a texture easily in this fiddle , but unable to pan properly.
Here's Code snippet for shaders :
var vertexShader = createVertexShader([
'attribute vec3 attrVertexPos;',
'attribute vec2 attrTextureCoord;',
'varying highp vec2 vTextureCoord;',
'uniform float zoomFactor;',
'uniform vec2 panCoord;',
'void main(void) {',
'\tgl_Position = vec4(attrVertexPos.xy + panCoord.xy, 0, zoomFactor);',
'\tvTextureCoord = attrTextureCoord;',
'}'
].join('\n'));
//create and compile Fragment Shader
var fragmentShader = createFragmentShader([
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
'precision highp float;',
'#else',
'precision mediump float;',
'#endif',
'varying highp vec2 vTextureCoord;',
'uniform sampler2D uImage;',
'void main(void) {',
'\tgl_FragColor = texture2D(uImage, vTextureCoord);',
'}'
].join('\n'));
Javascript code:
document.getElementById('canvas').onmousedown = function(e) {
if(startX === undefined) {
startX = e.clientX;
startY = e.clientY;
} else {
startX = lastX;
startY = lastY;
}
isMouseDown = true;
};
document.getElementById('canvas').onmouseup = function() {
isMouseDown = false;
previousTranslation[0] = xVal/100*zoomFactor;
previousTranslation[1] = yVal/100*zoomFactor;
};
document.getElementById('canvas').onmouseout = function() {
isMouseDown = false;
};
document.getElementById('canvas').onmousemove = function(e) {
if (isMouseDown) {
xVal = (lastX-startX)/canvas.width*100;
yVal = (startY-lastY)/canvas.height*100;
console.log(xVal/100*2.0 + ',' +yVal/100*2.0);
gl.uniform2fv(pan, new Float32Array([previousTranslation[0] + xVal/100*zoomFactor, previousTranslation[1] + yVal/100*zoomFactor]));
}
};
I think there is something that could be done on the javascript side as shader looks fine . Any suggestions?
The error happens because you try to write a vec4 into a float, which is not going to work out. The multiplication of a float with a vec4 results in a vec4, thus you have something like this:
gl_Position.x = aVertexPosition.x * u_CosB - aVertexPosition.y * u_SinB
float = float * vec4 - float * vec4
Edit
If this is really about panning (moving the object), then I don't exactly understand why there are sin and cos terms involved. In addition: Why is the x coordinate modified depending on the y coordinate? This would only be required if there is some rotation ongoing (which is not pan). In the end, the object is not visible at all, because you set the y-coordinate for all vertices to 0, which means they are collapsed to a line.
So to just implement panning, the code could look somehow like this:
//Contains offset in normalized device coordinates along x and y direction
uniform vec2 pan;
attribute vec4 aVertexPosition;
void main()
{
gl_Position = vec4(aVertexPosition.xy + pan.xy, 0, 1.0);
}
Edit 2
The way how you calculate the pan in onmousemove
is wrong. You have to calculate the distance to the mouse down position (not sure what you are calculating now):
document.getElementById('canvas').onmousemove = function(e) {
if (isMouseDown) {
var xVal = (lastX - e.clientX)/canvas.width;
var yVal = (lastY - e.clientY)/canvas.height;
gl.uniform2fv(pan, new Float32Array([xVal, yVal]));
}
};
When you need it faster/slower multiply xVal
and yVal
with a constant factor. And it might be that you have to invert one of the directions when the pan goes in the wrong one.
Edit 3
The mousedown function now doesn't make much sense? Why should it behave differently after the first click? The only code there should be:
document.getElementById('canvas').onmousedown = function(e) {
startX = e.clientX;
startY = e.clientY;
isMouseDown = true;
};
Additionally, when calling the mouse-up function the second time, you override the value of previousTranslation
instead of adding the current translation to it. Correct:
document.getElementById('canvas').onmouseup = function() {
isMouseDown = false;
if (previousTranslation[0] == undefined)
{
previousTranslation[0] = 0.0;
previousTranslation[1] = 0.0;
}
previousTranslation[0] += xVal/100*zoomFactor;
previousTranslation[1] += yVal/100*zoomFactor;
};