java - 在带有着色器的 opengl es 中围绕自身旋转矩形

标签 java android opengl-es rotation shader

我是 opengl es 的新手。现在我正在尝试制作一个简单的场景,其中不同大小的矩形只是落下并绕着它们自己的轴旋转。

(说明我想要什么) enter image description here

我创建了矩形类,为它创建了着色器助手,还创建了一个简单的顶点和 fragment 着色器(只是通过 vec4 着色,没什么特别的,我不会发布代码)。

好吧,所有这些东西看起来像这样:

矩形对象

 public class RectObject{
    private static final int POSITION_COMPONENT_COUNT = 2;
    private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
    private static final int STRIDE = (POSITION_COMPONENT_COUNT 
        + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;

    private final VertexArray vertexArray;

    public RectObject(float x, float y, float size){
        float[] newCoordinates = {
                x, y, 0.5f, 0.5f, 
                (x-size), (y-size),0f, 1.0f,  
                (x+size), (y-size),1f, 1.0f, 
                (size + x), (size + y),1f, 0.1f, 
                (x-size), (size + y),0f, 0.1f, 
                (x-size), (y-size), - 0f, 1.0f 
        };

        vertexArray = new VertexArray(newCoordinates);
    }

    public void bindData(RectShaderProgram textureProgram) {

        vertexArray.setVertexAttribPointer(
            0, 
            textureProgram.getPositionAttributeLocation(), 
            POSITION_COMPONENT_COUNT,
            STRIDE);
    }

    public void draw(RectShaderProgram shader, float velocity) { 
        glUniform4f(shader.getMoveLocation(), 0.0f, velocity, 0.0f, 0.0f);
        glUniform1f(shader.getTimerLocation(),  (float)(System.nanoTime()/10000000000.0f));
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
    }

}

顶点着色器:

attribute vec4 a_Position;
uniform vec4 u_Move;
uniform mat4 u_Matrix;
uniform float timer;

void main()
{
    mat4 rotation = mat4(
     cos(timer), -sin(timer), 0.0, 0.0,
     sin( timer), cos(timer), 0.0, 0.0,
     0.0,  0.0, 1.0, 0.0,
     0.0,  0.0, 0.0, 1.0 );

    gl_Position = u_Matrix * rotation* ((a_Position /*+ u_Move*/)) ;  
}

着色器助手

public class RectShaderProgram extends ShaderProgram{

private final int uMatrixLocation;
private final int uMoveLocation;
private final int TimerLocation;
// Attribute locations
private final int aPositionLocation;

public RectShaderProgram(Context context ) {
    super(context, R.raw.rect_vertex_shader,
            R.raw.rect_fragment_shader);
    // TODO Auto-generated constructor stub
       // Retrieve uniform locations for the shader program.

    // Retrieve attribute locations for the shader program.
    aPositionLocation = glGetAttribLocation(program, A_POSITION);
    uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
    uMoveLocation= glGetUniformLocation(program, U_MOVE);
    TimerLocation = glGetUniformLocation(program, TIMER);
}

public void setUniforms(float[] matrix) {
    glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);

}

public int getPositionAttributeLocation() {
    return aPositionLocation;
}
public int getMoveLocation() {
    return uMoveLocation;
}
public int getTimerLocation() {
    return TimerLocation;
}


}

但问题是整个场景都在旋转!

我有什么 enter image description here

那么,如何以正确的方式制作呢? 这是渲染器类

 public class ProjectRenderer implements Renderer{

    private final float[] projectionMatrix = new float[16];
    private final float[] modelMatrix = new float[16];

    private int uMatrixLocation;

    private Background wall;
    //private RectObject myobject, myobject2;
    private TextureShaderProgram textureProgram;
    private ColorShaderProgram colorProgram;  
    private RectShaderProgram rectProgram;  
    private int texture;
    private float velocity, time;
    private ArrayList<RectObject> rlist = new ArrayList<RectObject>();

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        glClearColor(0.0f,0.0f,0.0f,0.0f);
        velocity = 0.1f;
        wall = new Background();
        //myobject = new RectObject(0.1f,0.1f, 0.1f);
        //myobject2 = new RectObject(0.2f,0.4f, 0.1f);
         Random rand = new Random();
        for (int i = 0; i < 15; i++){
            rlist.add(new RectObject( (float)0.2*rand.nextInt(15)-1, (float)0.2*rand.nextInt(15)-1, (float)0.1*rand.nextInt(3)));
        }


           textureProgram = new TextureShaderProgram(context);
           colorProgram = new ColorShaderProgram(context);        
           rectProgram = new RectShaderProgram(context);
           texture = TextureHelper.loadTexture(context, R.drawable.sas);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO Auto-generated method stub
        glViewport(0, 0, width, height);
        // Construct the projection matrix
        MatrixHelper.perspectiveM(projectionMatrix,45,(float)width
                /(float)height,1f,10f);
        // Make the modelMatrix identity matrix
        setIdentityM(modelMatrix,0);
        // Add offset of 2.5 in direction of z axle
        translateM(modelMatrix,0,0f,0f,-2.0f);
        // Rotation by 60 degrees in direction of x axle
        //rotateM(modelMatrix,0,-60f,1f,0f,0f);
        // Projection matrix * model matrix 
        final float[] temp=new float[16];
        multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0);
        System.arraycopy(temp,0,projectionMatrix,0,temp.length);


    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         // Draw the table.
        textureProgram.useProgram();
        textureProgram.setUniforms(projectionMatrix, texture);
        wall.bindData(textureProgram);
        wall.draw();

        velocity = velocity - 0.005f;

        rectProgram.useProgram();
        rectProgram.setUniforms(projectionMatrix);
        for(Iterator<RectObject> i = rlist.iterator(); i.hasNext(); ) {
            RectObject item = i.next();
            item.bindData(rectProgram);
            item.draw(rectProgram, velocity);

        }
    }

    public ProjectRenderer(Context context){
        this.context = context;

    }

最佳答案

情况是您将矩形的坐标存储在世界坐标中。换句话说,您将平移变换应用于顶点并将它们存储在变换后的位置。因此,如果具有一个全局原点的单个帧,则表示所有矩形。

旋转矩阵以围绕原点旋转给定点的方式转换给定点的坐标。要围绕空间中的任意轴旋转一个点,需要一些更复杂的数学运算。因此,通常每个对象都用适当的局部坐标系表示,允许相对于对象的局部原点执行一些变换(即旋转、缩放)。这个本地原点,有时称为枢轴点,通常位于对象的中心。

任何运动都可以表示为两种不同类型运动的组合:平移运动和旋转运动。任意运动的分解方式有无数种,因此选择最方便的一种是合理的。选择局部(固定到对象)框架时应考虑到它在全局框架中的原点(枢轴点)位置不会受到旋转变换的影响。

因此,综上所述,您应该重写RectObject 的构造函数,如下所示:

public RectObject(float x, float y, float size){
    float[] newCoordinates = {
            0, 0, 0.5f, 0.5f, 
            -size, -size, 0f, 1.0f,  
            size, -size, 1f, 1.0f, 
            size, size, 1f, 0.1f, 
            -size, size, 0f, 0.1f, 
            -size, -size, - 0f, 1.0f 
    };

    vertexArray = new VertexArray(newCoordinates);
}

原点将位于矩形(准确地说是正方形)的中心。

此外,我建议您不要直接将大小应用于矩形的顶点,而是将其作为统一参数传递给顶点着色器并作为缩放变换应用。因此,您可以对所有矩形使用相同的顶点数组。对于这种情况,顶点的坐标应该按照单位大小的矩形构造。

如何将变换传递给顶点着色器?通常它是由作为统一参数传递的变换矩阵完成的。该变换矩阵通常是所有中间变换(例如平移、旋转和缩放)相乘的结果。因此,您的顶点着色器应更改如下:

attribute vec2 a_Position;
uniform mat4 u_Matrix;

void main()
{
    gl_Position = u_Matrix * vec4(a_Position, vec2(0.0, 1.0));  
}

请注意,您已将 a_Position 属性定义为二元 vector ,因此您必须将其用作二元 vector 。在上面的着色器中,使用 a_Position 属性构建了一个四分量 vector 。

另请注意,如果您要使用 uv 坐标,则需要将它们添加到顶点着色器中。

您需要计算 u_Matrix 矩阵作为投影、平移和旋转矩阵相乘的结果。这些矩阵的构造取决于您使用的数学库。阅读this , thisthis了解如何执行此操作的总体思路。

一般来说,对于您的情况,转换矩阵可以计算如下:

                                           Translation         Rotation
|                |     |            |     | 1  0  0  0 |     | cos(alpha)  -sin(alpha)  0  0 |
| Transformation |  =  | Projection |  X  | 0  1  0  0 |  X  | sin(alpha)   cos(alpha)  0  0 |
| matrix         |     | matrix     |     | 0  0  1  0 |     | 0            0           1  0 |
|                |     |            |     | x  y  0  1 |     | 0            0           0  1 |

地点:

  • x, y - 矩形的位置
  • alpha - 旋转角度

关于java - 在带有着色器的 opengl es 中围绕自身旋转矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26563484/

相关文章:

java - REST API : org. springframework.beans.factory.UnsatisfiedDependencyException:

java - Jetty 服务器总是使用处理程序返回 404

java - 在 AWS Lambda (java) 中使用环境变量更改 Log4j 级别

java - OpenGl ES on android微调光线拾取代码

java - Oracle 10g 在日期中接受 5 位数年份

java - 警报对话框 not_showing

android - 如何为 SearchView 转换 CustomEditText 而不是 EditText?

android - Youtube Iframe 中的黑屏(Android 应用程序)

java - 如何检查 3D 对象是否与 OpenGL ES 2 中的射线相交 - Android

java - 如何创建接受值数组的类构造函数?