顶点着色器旋转ThreeJS对象

时间:2020-03-06 17:00:52

标签: three.js shader vertex-shader

我想绕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;
}

该对象,但是未旋转。它显示在正确的位置,它是黄色的,因此片段着色器正在工作。是我构造矩阵错误,还是在顶点着色器中滥用了矩阵?

1 个答案:

答案 0 :(得分:3)

似乎您没有正确设置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即可达到相同的结果。