在宽画布中使用 webGL 旋转图像

问题描述 投票:0回答:1

我正在开发一个网络应用程序,它将能够进行一些图像转换,其中之一是图像旋转,问题是:只要画布是正方形(宽度=高度),一切都可以,但除此之外,图像像所附的屏幕截图一样变得倾斜。 我尝试使用这些方程根据旋转角度改变缩放比例

const scalingY = 1 + (aspectRatio - 1) * Math.pow(Math.sin(angelInRadian/2), 1);

const scalingX = (1/aspectRatio) +  (1-(1/aspectRatio)) * Math.pow(Math.cos(angelInRadian), 1);

但是图像在旋转过程中仍然倾斜

const scalingY = 1 + (aspectRatio - 1) * Math.pow(Math.sin(angelInRadian/2), 1);

const scalingX = (1/aspectRatio) +  (1-(1/aspectRatio)) * Math.pow(Math.cos(angelInRadian), 1)
const aspectRatioCompensation = new Float32Array([
                 1, 0, 0, 0,
                 0, 1, 0, 0,
                 0, 0, 1, 0,
                 0, 0, 0, 1
                            ]);
//const aspectRatioCompensation = new Float32Array([
                 scalingX, 0, 0, 0,
                 0, scalingY, 0, 0,
                 0, 0, 1, 0,
                 0, 0, 0, 1
                            ]);

const cosTheta = Math.cos(angelInRadian);
const sinTheta = Math.sin(angelInRadian);
const rotationMatrix = new Float32Array([
               cosTheta, -sinTheta, 0, 0,
               sinTheta, cosTheta,  0, 0,
                   0,         0,    1, 0,
                   0,         0,    0, 1
                            ]);

// Combine the aspect ratio adjustment and rotation
const combinedMatrix = mat4.create();

mat4.multiply(combinedMatrix, aspectRatioCompensation, rotationMatrix );

the image while rotation angle is 0 deg

the image while rotation angle is ~ 45 deg

顶点着色器:

                attribute vec4 a_position;
            attribute vec2 a_texCoord;
            varying vec2 v_position;
            varying vec2 v_texCoord;

            void main() {
                gl_Position = a_position;
                v_position = a_position.xy;
                v_texCoord = a_texCoord;
            }

片段着色器:

precision mediump float;
            varying vec2 v_texCoord;
            uniform sampler2D u_texture;
            uniform vec4 u_color;
            uniform int u_renderMode; // 0 for texture, 1 for shape


            void main() {
                    if (u_renderMode == 0) {
                        gl_FragColor = texture2D(u_texture, v_texCoord);
                    } else if (u_renderMode == 1) {
                        gl_FragColor = u_color;
                    }
            }

gl 设置(此函数是负责屏幕更新的类的一部分):

    updateScreen() {

        const { gl, program, positionBuffer, texCoordBuffer } = this;

        gl.useProgram(program);


        // Bind the position buffer for this layer
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        const positionLocation = gl.getAttribLocation(program!, 'a_position');
        gl.enableVertexAttribArray(positionLocation);
        gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

        // Bind the texCoord buffer for this layer
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
        const texCoordLocation = gl.getAttribLocation(program!, 'a_texCoord');
        gl.enableVertexAttribArray(texCoordLocation);
        gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

        const error = gl.getError();

        if (error !== gl.NO_ERROR) {
            console.error('WebGL error:', error);
        }

        // Enable blending
        //TODO: need more understanding of the blending functions
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

        const hitTestLayer = globalState.get('hitTestLayer');

        this.model?.documents.activeDocument!.layers.forEach((layer: any) => {

            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, layer.positionCoordArray, gl.STATIC_DRAW);

            gl.bindTexture(gl.TEXTURE_2D, layer.texture);

            const textureLocation = gl.getUniformLocation(program!, 'u_texture');

            gl.uniform1i(textureLocation, 0);

            layer.shapes.performDrawingCalls(gl, program!, 0)

            const pixels = new Uint8Array(4);

            gl.readPixels(5, 5, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

        })

        gl.useProgram(null);


    }

enter image description here

webgl matrix-multiplication image-rotation gl-matrix
1个回答
0
投票

问题在于,与沿 Y 轴选择 NDC 中的任何坐标相比,沿 X 轴选择 NDC 中的任何坐标都会导致距原点的距离不同。出现这种差异的原因是,无论轴的实际长度如何,NDC 的范围都是从 -1 到 1。为了解决这个问题,我决定将 X 轴缩小 1/aspectRatio

,然后旋转,最后按aspectRatio放大X轴。这种方法对我有用。

 mat4.scale(finalTransformationMatrix, initialTransformationMatrix, [1/aspectRatio, 1, 1])

mat4.rotateZ(finalTransformationMatrix, finalTransformationMatrix, -angelInRadian)

mat4.scale(finalTransformationMatrix, finalTransformationMatrix, [ aspectRatio, 1, 1])

© www.soinside.com 2019 - 2024. All rights reserved.