Scene Image Rotation on Canvas Animation

I found this article here on codrops: https://tympanus.net/codrops/2019/05/22/creating-grid-to-fullscreen-animations-with-three-js/

The script works fine as it is but I have an issue when I start to rotate images I’d like to have by design. The initial paint happening on the canvas element is not reflecting the rotation of the image.

I set up a fiddle, showing the issue on the image in the middle.

https://jsfiddle.net/w3cu974s/

An attempt I tried to make was to set a rotation to the texture but it did not even rotate the image.

const smallTexture = new THREE.Texture(imageSet.small.image);
            smallTexture.generateMipmaps = false;
            smallTexture.wrapS = smallTexture.wrapT = THREE.ClampToEdgeWrapping;
            smallTexture.minFilter = THREE.LinearFilter;
            smallTexture.needsUpdate = true;
            smallTexture.rotation = 45;

This file https://github.com/Anemolo/GridToFullscreenAnimations/blob/884fe4fbb1192a1013cccc51e580b4c14f9df480/js/GridToFullscreenEffect.js is showing the code handling the scene and panes.

It would be great if someone could point me into the right direction where I can pass the image rotation to three.js scene.

Any help would be appreciated.

Best

/cc

Unfortunately, the image becomes black after the click. It seems you hit the cross-origin policy so using them as textures is not allowed. There is actually an error message in the console:

The image element contains cross-origin data, and may not be loaded.

In any event, a modulation of Texture.rotation will change the respective uv transformation matrix. However, it seems this matrix is not used in the custom shader code. You normally want to do something like this in the vertex shader:

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

uvTransform us a uniform of type mat3.

Hi,

thanks for coming back to me. Yes, the cross origin is blocking the image but the black canvas also shows the missing rotation.

I’m very new to three.js, to be honest this is the first time I use it and I’m totally overwhelmed and lost in all the possible options etc. So my assumption that the initial paint is based on the texture is correct?

Means according to the docs I need to set

smallTexture.matrixAutoUpdate = false;

and then define a new matrix by using

// smallTexture.setUvTransform ();
// smallTexture.updateMatrix();

const smallTexture = new THREE.Texture(imageSet.small.image);
smallTexture.generateMipmaps = false;
smallTexture.wrapS = smallTexture.wrapT = THREE.ClampToEdgeWrapping;
smallTexture.minFilter = THREE.LinearFilter;
smallTexture.needsUpdate = true;
smallTexture.matrixAutoUpdate = false;
smallTexture.matrix.setUvTransform(0,0,0,0,2,0,0);
smallTexture.updateMatrix();

Which currently throws an error: smallTexture.updateMatrix is not a function.

I grabbed this from here: https://threejs.org/docs/#manual/en/introduction/Matrix-transformations

There should be no need to manually compute the uv transformation matrix. Setting Texture.rotation is absolutely sufficient.

It seems the actual problem is that the custom shader code of the Codrops article does not respect this matrix in the vertex shader.

Hi,

ah ok. You are referring to this code part:

function generateShaders(activation, transform) ....

However, I’m not sure about the mentioned

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

I already defined uvTransform:

var vertexUniforms = `
uniform float uProgress;
uniform vec2 uScaleToViewSize;
uniform vec2 uPlaneCenter;
uniform vec2 uMeshScale;
uniform vec2 uMouse;
uniform vec2 uViewSize;
uniform float uClosestCorner;
uniform mat3 uvTransform;

// Option Uniforms
uniform float uSeed;
uniform vec4 uBeizerControls;
uniform float uSyncLatestStart;
uniform float uActivationParts;
uniform bool uProgressByParts;
varying vec2 vUv;
varying vec2 scale; 
varying float vProgress;`;

and then we have this part:

void main(){

  vec3 pos = position.xyz;
  vec2 newUV = uv;

  float activation = getActivation(uv);

  // Everything ends at the same time
  float startAt = activation * uSyncLatestStart;
  float vertexProgress = smoothstep(startAt,1.,uProgress);

  if(uProgressByParts){
    // Vertex end by parts
    float activationPart = 1./uActivationParts;
    float activationPartDuration = 1./(uActivationParts+1.);

    float progressStart = (activation / activationPart) * activationPartDuration;
    float progressEnd = min(progressStart + activationPartDuration,1.);
    vertexProgress = linearStep(progressStart,progressEnd,uProgress);
  }
    vec3 transformedPos = pos;
    vec2 transformedUV = uv;
    ${transform ? transform : ""}
    pos = transformedPos;
    newUV = transformedUV; 

    // Scale
    // uScaleToViewSize
    scale = vec2(
      1. + uScaleToViewSize * vertexProgress
    );
    
    // Since we are moving the mesh not the geometry the geometry is in the center        
    vec2 flippedPos = vec2(
      (- pos.x) ,
      (- pos.y ) 
    );
   
    pos.xy *= scale;

    // Move to center
    // Mesh moves it into position. Shader moves it to the center
    pos.y += -uPlaneCenter.y * vertexProgress;
    pos.x += -uPlaneCenter.x * vertexProgress;

    // Move slightly to the front
    // pos.z += vertexProgress;        
    pos.z += float(0);        
    
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.);
    vProgress = vertexProgress;
    vUv = newUV;
    
}

and now I’m stuck.Is this something you can help me with. Of course for a small beer :slight_smile:

As a side note ( not sure if you are responsible or if you can forward it)

When browsing this page here: three.js docs

Clicking on THREE.Matrix4 leads to three.js docs instead of three.js docs

@Mugen87

any chance that you can take a deeper look into it for a small tipp? I’m stuck at the moment and on a tight deadline.

I already have a lot of work on my desk right now so I hope somebody else of the community can have a look.