【问题标题】:OpenGL square stretches instead of movingOpenGL正方形拉伸而不是移动
【发布时间】:2015-12-27 00:12:05
【问题描述】:

我正在尝试使用 Java 中的 LWJGL3(Open GL 4.1,NVIDIA-10.8.14)创建游戏引擎,但我似乎遇到了一个*小*问题...

当我尝试平移正方形时,它并没有按预期实际移动,而是拉伸。

LWJGL 没有math 类,所以我必须创建自己的 Matrix 和 TransformationMatrix 类。我已将它们合并为一个 sn-p 以减小这篇文章的大小。

我的假设是错误出现在 TransformationMatrix 的 translate() 函数中

public TransformationMatrix translate(Vector3f vector){
    super.m30 += ((super.m00 * vector.getX()) + (super.m10 * vector.getY()) + (super.m20 * vector.getZ()));
    super.m31 += ((super.m01 * vector.getX()) + (super.m11 * vector.getY()) + (super.m21 * vector.getZ()));
    super.m32 += ((super.m02 * vector.getX()) + (super.m12 * vector.getY()) + (super.m22 * vector.getZ()));
    super.m33 += ((super.m03 * vector.getX()) + (super.m13 * vector.getY()) + (super.m23 * vector.getZ()));

    return this;
}

我玩过它,但我无法从中获得任何积极的结果。

public class Matrix4f {

    public float 
        m00, m01, m02, m03,
        m10, m11, m12, m13,
        m20, m21, m22, m23,
        m30, m31, m32, m33;

    public FloatBuffer store(FloatBuffer buffer){
        buffer.put(this.m00);
        buffer.put(this.m10);
        buffer.put(this.m20);
        buffer.put(this.m30);
        buffer.put(this.m01);
        buffer.put(this.m11);
        buffer.put(this.m21);
        buffer.put(this.m31);
        buffer.put(this.m02);
        buffer.put(this.m12);
        buffer.put(this.m22);
        buffer.put(this.m32);
        buffer.put(this.m03);
        buffer.put(this.m13);
        buffer.put(this.m23);
        buffer.put(this.m33);

        return buffer;
    }


    ////////////////////////////
    //                        //
    //  TRANSFORMATION MATRIX //
    //                        //
    ////////////////////////////   


    public class TransformationMatrix extends Matrix4f{

    public TransformationMatrix(Vector3f translation){
        this.setIdentity();
        this.translate(translation);
    }

    public TransformationMatrix setIdentity(){
        super.m00 = 1.0f;
        super.m01 = 0.0f;
        super.m02 = 0.0f;
        super.m03 = 0.0f;
        super.m10 = 0.0f;
        super.m11 = 1.0f;
        super.m12 = 0.0f;
        super.m13 = 0.0f;
        super.m20 = 0.0f;
        super.m21 = 0.0f;
        super.m22 = 1.0f;
        super.m23 = 0.0f;
        super.m30 = 0.0f;
        super.m31 = 0.0f;
        super.m32 = 0.0f;
        super.m33 = 1.0f;

        return this;
    }

    public TransformationMatrix translate(Vector3f vector){
            super.m30 += ((super.m00 * vector.getX()) + (super.m10 * vector.getY()) + (super.m20 * vector.getZ()));
            super.m31 += ((super.m01 * vector.getX()) + (super.m11 * vector.getY()) + (super.m21 * vector.getZ()));
            super.m32 += ((super.m02 * vector.getX()) + (super.m12 * vector.getY()) + (super.m22 * vector.getZ()));
            super.m33 += ((super.m03 * vector.getX()) + (super.m13 * vector.getY()) + (super.m23 * vector.getZ()));

            return this;
    }
}

我的顶点着色器包含

#version 400 core

in vec3 position;
in vec2 texture;
out vec2 texture_coords;
uniform mat4 transformationMatrix;

void main(void){
    gl_Position = transformationMatrix * vec4(position, 1.0);
    texture_coords = texture;
}

片段着色器包含

#version 400 core

//Variables...

void main(void){
    out_color = texture(textureSampler, texture_coords);
} 

使用以下点和索引渲染正方形

//stored in the vertex shader's "position"
float[] positions = {
    -0.5f,0.5f,0.0f,    
    -0.5f,-0.5f,0.0f,   
    0.5f,-0.5f,0.0f,    
    0.5f,0.5f,0.0f,     
};

//bound using
//
//int id = GL15.glGenBuffers();
//GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, id);
//GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, toIntBuffer(indices), GL15.GL_STATIC_DRAW);
int[] indices = {
    0,1,3,  
    3,1,2,
};

//stored in the vertex shader's "texture"
float[] textureCoords = {
    0,0,
    0,1,
    1,1,
    1,0,
};

然后使用TransformationMatrix.translate() 翻译(在上面的gif 中,它正在由<0.0f, 0.01f, 0.0f> 翻译)。正方形是使用

public void render(){
    GL30.glBindVertexArray(modelID);
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);


    //position begins at <0, 0, 0>, and is incremented by <0, 0.01f, 0>
    //every frame in the above gif
    TransformationMatrix matrix = new TransformationMatrix(
            position
    );

    //load the transformation matrix to the vertex shader
    FloatBuffer buffer = matrix.store(BufferUtils.createFloatBuffer(16));
    buffer.flip();
    //location being the location of the "transformationMatrix" in the
    //vertex shader
    GL20.glUniformMatrix4fv(location, false, buffer);

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID));
    //vertexCount is indices.length (6)
    GL11.glDrawElements(GL11.GL_TRIANGLES, vertexCount, GL11.GL_UNSIGNED_INT, 0); 

    GL20.glDisableVertexAttribArray(1);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

到目前为止,我已经尝试过使用TransformationMatrix.translate(),并且我已经两次、三次和四次检查我是否拥有correct code in these classes

我注意到的一件事是,将translate() 方法更改为添加到m03m13m23 而不是m30m31m32 分别使正方形开始翻译放大,缩小,然后开始向下翻译

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

在渲染每一帧之前调用

【问题讨论】:

  • 确保您的矩阵存储布局符合您的预期。您还没有展示如何将矩阵上传到 GL,但您在着色器中使用矩阵 * 向量顺序,因此在默认情况下使用 GL_FALSE 作为glUniformMatrixtranspose 参数,矩阵应该按列主要顺序排列。您的矩阵成员名称中的可疑之处在于您似乎使用了“mColumnRow”,而经典的数学符号是“mRowColumn”。
  • @derhass,哈哈; local_to_world * local_position 是我的错误;切换了订单,它现在可以工作了。谢谢!

标签: java opengl lwjgl opengl-4


【解决方案1】:

更多的是与您的矩阵有关。请记住,3D 平移应该是其 x、y 和 z 值中第一行的第四列。您不止一次地输入每个值,这当然会改变翻译。您使转换过于复杂;您需要做的就是获取第 4 列、第 1 行、第 2 行和第 3 行矩阵的位置,然后分别根据 x、y 和 z 值递增它们的值。使用你的矩阵:

    m00, m01, m02, m03,
    m10, m11, m12, m13,
    m20, m21, m22, m23,
    m30, m31, m32, m33;

m03m13m23 将分别是您希望翻译 xyz 值的位置。要在 x 中翻译 100、在 y 中翻译 200、在 z 中翻译 300,您可以这样做:

    1.0, 0.0, 0.0, 100,
    0.0, 1.0, 0.0, 200,
    0.0, 0.0, 1.0, 300,
    0.0, 0.0, 0.0, 1.0;

你的translation 函数在做什么,我不知道。看起来您正在创建一个转换矩阵并将其乘以当前,这使您的代码非常不可读。事实上,这不是必需的,因为您的代码已经返回了一个矩阵,这意味着这种用法:

playerPosition = translate(playerPosition);

我没有发现您的渲染代码和着色器有任何问题。因此,它必须与您的矩阵有关。这只是确定你的专业的一个案例。请记住,OpenGL 读取所有主要列。因此,这意味着 OpenGL 将读取 m00 然后 m10 然后 m20 等等。它会根据这些值创建自己的矩阵。

【讨论】:

  • 是的,问题在于值存储在错误的列中。在加载转换矩阵时,我将GL20.glUniform4fvtranspose 参数更改为true(在最后一个代码sn-p 中),所以现在看起来像GL20.glUniformMatrix4fv(location, true, buffer)。谢谢!
  • @Jojodmo 尽管我很欣赏这个解决方案,但创建矩阵的方式并不实用。通过使矩阵更主要是列,您可以节省一些 CPU 资源。此外,为您使用 OpenGL 转置矩阵也会消耗一些 GPU 能力。无论如何,这些都是你在制作游戏引擎时要考虑的事情。我祝愿一切顺利。将我的答案标记为已解决,我很高兴能帮上忙!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-21
  • 2011-12-23
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多