用于旋转 ThreeJS 对象的顶点着色器

Vertex shader to rotate a ThreeJS object

我想围绕 y 轴旋转网格,我使用此代码生成网格:

const coinMaterial = new THREE.ShaderMaterial({
    uniforms: { 
        rotationMatrix: { type: 'mat4', value: SHADERS.COIN_ROTATION_MATRIX }
    },
    wireframe: false,
    side: THREE.DoubleSide,
    vertexShader: SHADERS.coinRotationShader(), 
    fragmentShader: SHADERS.coinFragmentShader()
});
const coinGeometry = new THREE.TorusGeometry(5, 2, 8, 30);
const coinMesh = new THREE.Mesh(coinGeometry, coinMaterial);

在这里您可以看到生成旋转矩阵的 SHADERS 模块和着色器:

export function coinRotationShader() { //vertex shader 
    return "                                \
    uniform mat4 rotationMatrix;            \
    void main() {                           \
        vec4 rotatedPosition = rotationMatrix * vec4(position, 1.0); \
        gl_Position = projectionMatrix * modelViewMatrix * rotatedPosition; \
    } \
    ";
}

export function coinFragmentShader() { //just applies yellow color
    return "                        \
    void main() {                   \
        gl_FragColor = vec4(0.8, 0.8, 0, 1.0);   \
    }                               \
    ";
}

const ROTATION_ANGLE = (2*Math.PI) / 60.0; //angle of rotation

export const COIN_ROTATION_MATRIX = createCoinRotationMatrix();

function createCoinRotationMatrix() { //rotates around Y axis
    const rotationMatrix = new THREE.Matrix4();
    rotationMatrix.makeRotationY(ROTATION_ANGLE);
    return rotationMatrix;
}

然而,该物体不旋转。它出现在正确的位置,并且是黄色的,所以片段着色器正在工作。是我构建的矩阵有误,还是在顶点着色器中误用了它?

您似乎没有正确设置 rotationMatrix。请记住,Matrix4.makeRotationY() 的参数是以弧度(而不是度数)定义的。以下面的代码为基础试一试。平面绕y轴旋转45度。

function coinRotationShader() { //vertex shader 
    return `                                
    uniform mat4 rotationMatrix;            
    void main() {                           
        vec4 rotatedPosition = rotationMatrix * vec4(position, 1.0);
        gl_Position = projectionMatrix * modelViewMatrix * rotatedPosition;
    }
    `;
}

function coinFragmentShader() { //just applies yellow color
    return `
    void main() {
        gl_FragColor = vec4(0.8, 0.8, 0, 1.0);
    }
    `;
}

function createCoinRotationMatrix() { //rotates around Y axis
    const rotationMatrix = new THREE.Matrix4();
    rotationMatrix.makeRotationY( Math.PI * 0.25 );
    return rotationMatrix;
}

//

let camera, scene, renderer;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 5;

    scene = new THREE.Scene();

    const coinMaterial = new THREE.ShaderMaterial({
        uniforms: { 
            rotationMatrix: { value: createCoinRotationMatrix() }
        },
        vertexShader: coinRotationShader(), 
        fragmentShader: coinFragmentShader()
    });
    const coinGeometry = new THREE.PlaneBufferGeometry();
    const coinMesh = new THREE.Mesh(coinGeometry, coinMaterial);
    
    scene.add( coinMesh );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );
    renderer.render( scene, camera );

}
body {
 margin: 0;
}
canvas {
 display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.114/build/three.js"></script>

请注意,只需调制 Object3D.rotation.

即可获得相同的结果