[webgl] How to move a texture smoothly?

Hi,
I tried webgl. I have a square with a texture on it. All worked fine until I added some user interaction. If I simply translate the modelview matrix and get some unbeautiful result. When I’m in translation I can see the texture in his current position and in his last position. I get a stripe on my screen. Frames per sec about 60, I use requestAnimFrame().

here is my drawScene function. I modified code from www.learningwebgl.com/blog/?p=507 .


    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

        mat4.identity(mvMatrix);

        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);


        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, neheTexture);
        gl.uniform1i(shaderProgram.samplerUniform, 0);


        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
        setMatrixUniforms();
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }

    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }

user can only modify centerX, centerY, zoom.

so code could be shorter (or?)


    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

        mat4.identity(mvMatrix);

        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);
        setMatrixUniforms();
    
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }

but still looks ugly.

Do i miss some magic?
Is there an other way to translate the texture? like glMatrixMode(GL_TEXTURE) , glTranslatef() in normal OpenGL (bindBuffer and copy tex coords dont work as well)

full file:
(move with up/down, left/right, zoom with page up/down, different textures 0-9)


<html>

<head>
<title>flicker</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">


<script type="text/javascript">
//from src="glMatrix-0.9.5.min.js"
glMatrixArrayType=typeof Float32Array!="undefined"?Float32Array:typeof WebGLFloatArray!="undefined"?WebGLFloatArray:Array;
var mat4={};
mat4.create=function(a){var b=new glMatrixArrayType(16);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15]}return b};
mat4.frustum=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f};
mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;return mat4.frustum(-b,b,-a,a,c,d,e)};
mat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};
mat4.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a};
mat4.translate=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[12]=a[0]*d+a[4]*e+a[8]*b+a[12];a[13]=a[1]*d+a[5]*e+a[9]*b+a[13];a[14]=a[2]*d+a[6]*e+a[10]*b+a[14];a[15]=a[3]*d+a[7]*e+a[11]*b+a[15];return a}var g=a[0],f=a[1],h=a[2],i=a[3],j=a[4],k=a[5],l=a[6],o=a[7],m=a[8],n=a[9],p=a[10],r=a[11];c[0]=g;c[1]=f;c[2]=h;c[3]=i;c[4]=j;c[5]=k;c[6]=l;c[7]=o;c[8]=m;c[9]=n;c[10]=p;c[11]=r;c[12]=g*d+j*e+m*b+a[12];c[13]=f*d+k*e+n*b+a[13];c[14]=h*d+l*e+p*b+a[14];c[15]=i*d+o*e+r*b+a[15];return c};
</script>

<script type="text/javascript">
//from src src="webgl-utils.js"

/**

 * Provides requestAnimationFrame in a cross browser way.

 */

window.requestAnimFrame = (function() {

  return window.requestAnimationFrame ||

         window.webkitRequestAnimationFrame ||

         window.mozRequestAnimationFrame ||

         window.oRequestAnimationFrame ||

         window.msRequestAnimationFrame ||

         function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {

           window.setTimeout(callback, 1000/60);

         };

})();
</script>



<script id="shader-fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec2 vTextureCoord;

    uniform sampler2D uSampler;

    void main(void) {
        gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
    }
</script>

<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec2 aTextureCoord;

    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    varying vec2 vTextureCoord;


    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        vTextureCoord = aTextureCoord;
    }
</script>


<script type="text/javascript">

    var gl;

    function initGL(canvas) {
        try {
            gl = canvas.getContext("experimental-webgl");
			canvas.width = window.innerWidth;

			canvas.height = window.innerHeight;

            gl.viewportWidth = canvas.width;

            gl.viewportHeight = canvas.height;


        } catch (e) {
        }
        if (!gl) {
            alert("Could not initialise WebGL, sorry :-(");
        }
    }


    function getShader(gl, id) {
        var shaderScript = document.getElementById(id);
        if (!shaderScript) {
            return null;
        }

        var str = "";
        var k = shaderScript.firstChild;
        while (k) {
            if (k.nodeType == 3) {
                str += k.textContent;
            }
            k = k.nextSibling;
        }

        var shader;
        if (shaderScript.type == "x-shader/x-fragment") {
            shader = gl.createShader(gl.FRAGMENT_SHADER);
        } else if (shaderScript.type == "x-shader/x-vertex") {
            shader = gl.createShader(gl.VERTEX_SHADER);
        } else {
            return null;
        }

        gl.shaderSource(shader, str);
        gl.compileShader(shader);

        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert(gl.getShaderInfoLog(shader));
            return null;
        }

        return shader;
    }


    var shaderProgram;

    function initShaders() {
        var fragmentShader = getShader(gl, "shader-fs");
        var vertexShader = getShader(gl, "shader-vs");

        shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);

        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert("Could not initialise shaders");
        }

        gl.useProgram(shaderProgram);

        shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
        gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

        shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
        gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);

        shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
        shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    }


    function handleLoadedTexture(texture, data) {
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.bindTexture(gl.TEXTURE_2D, null);
    }

    var neheTexture;
	textureSize = 512;
	var pixels = new Uint8Array(4*textureSize*textureSize)
	var pixelsWhite = new Uint8Array(4*textureSize*textureSize)
	var pixelsBlack = new Uint8Array(4*textureSize*textureSize)


    function initTexture() {

		for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (!(((i/4)%2)+Math.floor((i/4/textureSize)%2)))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

		}

		//nehhh = gl.createTexture();


		neheTexture = gl.createTexture();

		gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );

		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);

		gl.bindTexture(gl.TEXTURE_2D, null);

		for (var i=0;i<4*textureSize*textureSize;i+=4){	
				pixelsWhite[i] =   255 
				pixelsWhite[i+1] = 255 
				pixelsWhite[i+2] = 255 
				pixelsWhite[i+3] = 255
				pixelsBlack[i] =   0 
				pixelsBlack[i+1] = 0 
				pixelsBlack[i+2] = 0 
				pixelsBlack[i+3] = 255


		}



    }

    var mvMatrix = mat4.create();
    var mvMatrixStack = [];
    var pMatrix = mat4.create();

    function mvPushMatrix() {
        var copy = mat4.create();
        mat4.set(mvMatrix, copy);
        mvMatrixStack.push(copy);
    }

    function mvPopMatrix() {
        if (mvMatrixStack.length == 0) {
            throw "Invalid popMatrix!";
        }
        mvMatrix = mvMatrixStack.pop();
    }


    function setMatrixUniforms() {
        gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
    }


    var cubeVertexPositionBuffer;
    var cubeVertexTextureCoordBuffer;
    var cubeVertexIndexBuffer;

    function initBuffers() {
        cubeVertexPositionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        vertices = [
            // Front face
            -1.0, -1.0,  0.0,
             1.0, -1.0,  0.0,
             1.0,  1.0,  0.0,
            -1.0,  1.0,  0.0,

        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        cubeVertexPositionBuffer.itemSize = 3;
        cubeVertexPositionBuffer.numItems = 24;

        cubeVertexTextureCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        var textureCoords = [
          // Front face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,


        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
        cubeVertexTextureCoordBuffer.itemSize = 2;
        cubeVertexTextureCoordBuffer.numItems = 8;

        cubeVertexIndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
        var cubeVertexIndices = [
            0, 1, 2,      0, 2, 3,    // Front face

        ];
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
        cubeVertexIndexBuffer.itemSize = 1;
        cubeVertexIndexBuffer.numItems = 6;
    }

	var zoom = 0.42;
	var dirX = 0;
	var dirY = 0;
	var centerX =0;
	var centerY =0;

	var currentlyPressedKeys = {};

    function handleKeyDown(event) {

        currentlyPressedKeys[event.keyCode] = true;

    }





    function handleKeyUp(event) {

        currentlyPressedKeys[event.keyCode] = false;    }







    function handleKeys() {


        if (currentlyPressedKeys[33]) {

            // Page Up

            zoom *= 0.99;

        }

        if (currentlyPressedKeys[34]) {

            // Page Down

            zoom *= 1.0/0.99;

        }

        if (currentlyPressedKeys[37]) {

            // Left cursor key

            dirX=-1.0

        }else if (currentlyPressedKeys[39]) {

            // Right cursor key

            dirX=1.0

        }else{

		    dirX=0.0

		}





        if (currentlyPressedKeys[38]) {

            // Up cursor key

            dirY=1.0

        }else if (currentlyPressedKeys[40]) {

            // Down cursor key

            dirY=-1.0

        }else{

		    dirY=0.0

		}

		if(currentlyPressedKeys[49]) {
			//white in black
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (!(((i/4)%2)+Math.floor((i/4/textureSize)%2)))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[50]) {
			//balck & white chess
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = (((i/4)%2)^((i/4/textureSize)%2))*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}

		if(currentlyPressedKeys[51]) {
			//x lines black or white
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = ((i/4)%2)*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[52]) {
			//y lines black or white
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw = Math.floor((i/4/textureSize)%2) *255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[53]) {
			//bw diagonal
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var bORw =     (  (i/8)%4 ^ ((i/8/textureSize)%4)   )*255
				pixels[i] =   bORw 
				pixels[i+1] = bORw 
				pixels[i+2] = bORw 
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}

		if(currentlyPressedKeys[54]) {
			//grey random 
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				var value = Math.random()*255
				pixels[i] =   value
				pixels[i+1] = value
				pixels[i+2] = value
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[55]) {
			//all random 
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   Math.random()*255
				pixels[i+1] = Math.random()*255
				pixels[i+2] = Math.random()*255
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[56]) {
			//random typed math 1
			var value = new Date().getTime()*1e-3
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   0
				pixels[i+1] = (value+ i*i/textureSize/4)*255
				pixels[i+2] = 0
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[57]) {
			//random typed math 2
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   ( Math.sin(i/textureSize*2*3.14)+1)*127* (( Math.sin(i/textureSize*2*3.14)+Math.tan(i))>1)
				pixels[i+1] = 0
				pixels[i+2] = 0
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}
		if(currentlyPressedKeys[48]) {
			//random typed math 3
			var value = 4*textureSize*textureSize
			for (var i=0;i<4*textureSize*textureSize;i+=4){
				pixels[i] =   0
				pixels[i+1] = 0
				pixels[i+2] = (value%i)
				pixels[i+3] = 255

			}
			gl.bindTexture(gl.TEXTURE_2D, neheTexture);	

			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize,textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels );
		}



	}

    function drawScene() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

        mat4.identity(mvMatrix);

        mat4.translate(mvMatrix, [-centerX, -centerY, -zoom]);
		setMatrixUniforms();

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
        gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);


        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, neheTexture);
        gl.uniform1i(shaderProgram.samplerUniform, 0);


        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);        
        gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }


    var lastTime = 0;

    function animate() {
        var timeNow = new Date().getTime();
        if (lastTime != 0) {
            var elapsed = timeNow - lastTime;
			var speed = zoom*0.42
			centerX += elapsed/1000*dirX*speed
			centerY += elapsed/1000*dirY*speed

        }
        lastTime = timeNow;
    }


    function tick() {
        requestAnimFrame(tick);
		handleKeys();
		
        drawScene();
		animate();


    }


    function webGLStart() {
        var canvas = document.getElementById("flicker");

        initGL(canvas);
        initShaders();
        initBuffers();
        initTexture();

        gl.clearColor(0.0, 0.3, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);

        document.onkeydown = handleKeyDown;

        document.onkeyup = handleKeyUp;




        tick();
    }


</script>


</head>


<body onload="webGLStart();" marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
    <canvas id="flicker" style="border: none;" width="800" height="600"></canvas>
</body>

</html>

hi,

can you post a screenshot or video ?
or link …
i don´t understand the problem …

cu
uwi

You can implement a texture matrix in the vertex shader the same way that you implement projection and model-view matrices, i.e. pass a matrix to the vertex shader then use it to transform the texture coordinate, e.g.


uniform mat4 uTMatrix;

void main(void) {
    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    vTextureCoord = (uTMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;
}

If you only need to translate the texture, there’s no need to use an entire matrix; you can just pass a vector, e.g.:


uniform vec2 uTextureOffset;

void main(void) {
    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    vTextureCoord = aTextureCoord + uTextureOffset;
}

hi, thanks for your answers. I will try GClements suggestion.
uwi2k2: i cant make a screenshot from it, it shows the fully drawn texture. The full file code above is a valid html file. You can copy and paste it (cant find upload function here and not allowed to post links).
as an example, i modifyed a screenshot (how it looks like in real time, translation in x-dim)(uesed texture ist black line, white line, black, white, b, w,…):
www.imageshack.us/scaled/landing/833/4kj.png

I did a 2nd test with normal open gl. It looks fine on fullscreen but in window mode there are sometimes also stripes. I used nehe.gamedev. net/tutorial/texture_mapping /12038/ and modified it:

…forum dont allow me to insert full code here…
so only my edits:


GLfloat	centerX=0;				
GLfloat	centerY=0;				
GLfloat	zoom=0.42;		


int LoadGLTextures()									// Load Bitmaps And Convert To Textures
{

	glGenTextures(1, &texture[0]);
	glBindTexture(GL_TEXTURE_2D, texture[0]);

	const int size = 512;

	byte data[size*size*3];

	for(int i=0; i < size*size*3; i++){
		//data[i]=(((i/3)%2)^((i/3/size)%2))*255;
		data[i]=(((i/3)%2))*255;
	}


	glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

	// Typical Texture Generation Using Data From The Bitmap	
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

	return true;										// Return Success
}

int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
	glLoadIdentity();									// Reset The View
	glTranslatef(-centerX , -centerY,-zoom);


	glBindTexture(GL_TEXTURE_2D, texture[0]);

	glBegin(GL_QUADS);
		// Front Face
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  0.0f);
	glEnd();


	return TRUE;										// Keep Going
}
//.... in WinMain
			float speed = 0.003;

			if (keys[VK_LEFT]){
				centerX -=speed;
			}
			if (keys[VK_RIGHT]){
				centerX +=speed;
			}
			if (keys[VK_UP ]){
				centerY +=speed;
			}
			if (keys[VK_DOWN]){
				centerY -=speed;
			}
			if (keys[VK_SUBTRACT ]){
				zoom *= 1.0/0.99;
			}
			if (keys[VK_ADD]){
				zoom *= 0.99;
			}

//...

But that cant be a bug of normal open gl, or?

EDIT:
GClements suggestion also does not work. still stripes on screen

If you’re talking about the tearing, that’s often unavoidable when running in a window. It’s a consequence of the raster scan, i.e. the screen being transferred to the monitor over the course of a frame, rather than instantaneously. If the window is updated after part of the screen has been transferred to the monitor, the top part of the window will be showing the old frame while the bottom part will be showing the new frame, resulting in a tear.

The solution is “vsync”, but it’s often outside of the program’s control. It’s more likely to work full screen than in a window. The in-window case may depend upon the OS (e.g. on Windows, enabling or disabling Aero may have an effect). For WebGL, it’s likely to depend upon the browser; apparently, it’s a recent addition on Firefox while Chrome has had support for a while.

You’re already using requestAnimationFrame, but beyond that it’s probably not something which you can control through your code.

thx for your answer,
I already thought about the frame is drawing while updating. I already tried with a global vsync activation. It has no effect. Furthermore the human eye should not see this at 60fps. But I did not thought about synchronic asynchronous frame drawing, like rotating tires on streets. So if there is a constant time difference between global and window update (or constant frequency difference at tire rotation and human eye update rate ) it draws the same percentage from old data at every frame.

Aero avoids this. So it work now! Thanks again! I had the classic windows 98 theme without Aero. But the new theme is more ugly than tearing :(. And it should work on each system.

do you know the name? is it active by default?

I found this link from searching for “webgl vsync”.

damn, this need active Aero themes as precondition. :frowning:

sad

but thank you again for your help