java - 使用 Java 或 C# 在 Y 轴上进行 Open GL 翻译

标签 java c# opengl opengl-es opengl-es-2.0

我是 OpenGL 新手,我有一个为我的 SurfaceView 创建的三角形,该三角形依次显示在我的屏幕上。我已经能够添加旋转来使我的三角形旋转,但这不是我需要的。我一直在深入研究 OpenGL,并阅读了“变换”和“翻译”,我相信这对于向三角形添加垂直运动是正确的,但是以我目前的理解,我无法实现这一点。

示例:

三角形在屏幕顶部创建,并沿 Y 轴向下移动到屏幕底部。

这个平移是有角度的,但是它显示了我的意思,我只想在 y 轴上移动。

enter image description here

我的渲染如下:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    //Project Matrix
    private float mMatrix[] = new float[16];
    private Triangle mTriangle;

    private final float[] mMVPMatrix = new float[16];
    private final float[] mModelMatrix = new float[16];
    private float[] mTempMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];

    // Called once to set up the view's opengl es environment
    public void onSurfaceCreated(GL10 unused, EGLConfig config){

    //Set the background frame color
    GLES30.glClearColor(208.0f,208.0f,208.0f,1.0f);

    mTriangle= new Triangle();
}

// Called for each redraw of the view
public void onDrawFrame(GL10 gl){
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    //Redraw background color
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

    // Apply transformation, start with translation
    Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix
    Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left
    // Create a rotation transformation for the triangle
    long time = SystemClock.uptimeMillis() % 4000L;
    float mAngle = 0.090f * ((int) time);
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);

    Matrix.orthoM(mMatrix, 0, -1, 1, -1, 1, -1, 1);

    // Combine Rotation and Translation matrices
    mTempMatrix = mModelMatrix.clone();
    Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);

    // Combine the model matrix with the projection and camera view
    mTempMatrix = mMVPMatrix.clone();
    Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0);

    mTriangle.draw(mMatrix);

}

// Called if the geometry of the view changes (example is when the screen orientation changes from landscape to portrait
public void onSurfaceChanged(GL10 unused, int width, int height){
    // Called if the geometry of the viewport changes
    GLES30.glViewport(0, 0, width, height);
}

public static int loadShader(int type, String shaderCode){

    // create a vertex shader type (GLES30.GL_VERTEX_SHADER)
    // or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
    int shader = GLES30.glCreateShader(type);

    // add the source code to the shader and compile it
    GLES30.glShaderSource(shader, shaderCode);
    GLES30.glCompileShader(shader);

    return shader;
}
}

我有一个三角形,如下所示:

public class Triangle {

    private final String vertexShaderCode =
    // This matrix member variable provides a hook to manipulate
    // the coordinates of the objects that use this vertex shader
    "uniform mat4 uMVPMatrix;" +
    "attribute vec4 vPosition;" +
     "void main() {" +
     // the matrix must be included as a modifier of gl_Position
     // Note that the uMVPMatrix factor *must be first* in order
     // for the matrix multiplication product to be correct.
     "  gl_Position = uMVPMatrix * vPosition;" +
     "}";

    private final String fragmentShaderCode =
      "precision mediump float;" +
      "uniform vec4 vColor;" +
      "void main() {" +
      "  gl_FragColor = vColor;" +
      "}";

    private final FloatBuffer vertexBuffer;
    private final int mProgram;
    private int mPositionHandle;
    private int mColorHandle;
    private int mMVPMatrixHandle;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {
    // in counterclockwise order:
    0.0f,  0.622008459f, 0.0f,   // top
    -0.5f, -0.311004243f, 0.0f,   // bottom left
    0.5f, -0.311004243f, 0.0f    // bottom right
};

private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };

/**
 * Sets up the drawing object data for use in an OpenGL ES context.
 */
public Triangle() {
    // initialize vertex byte buffer for shape coordinates
    ByteBuffer bb = ByteBuffer.allocateDirect(
    // (number of coordinate values * 4 bytes per float)
    triangleCoords.length * 4);
    // use the device hardware's native byte order
    bb.order(ByteOrder.nativeOrder());

    // create a floating point buffer from the ByteBuffer
    vertexBuffer = bb.asFloatBuffer();
    // add the coordinates to the FloatBuffer
    vertexBuffer.put(triangleCoords);
    // set the buffer to read the first coordinate
    vertexBuffer.position(0);

    // prepare shaders and OpenGL program
    int vertexShader = MyGLRenderer.loadShader(
      GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = MyGLRenderer.loadShader(
      GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
    GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
    GLES20.glLinkProgram(mProgram);                  // create OpenGL program executables

}

/**
 * Encapsulates the OpenGL ES instructions for drawing this shape.
 *
 * @param mvpMatrix - The Model View Project matrix in which to draw
 * this shape.
 */
public void draw(float[] mvpMatrix) {
    // Add program to OpenGL environment
    GLES20.glUseProgram(mProgram);

    // get handle to vertex shader's vPosition member
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(
      mPositionHandle, COORDS_PER_VERTEX,
      GLES20.GL_FLOAT, false,
      vertexStride, vertexBuffer);

    // get handle to fragment shader's vColor member
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

    // Set color for drawing the triangle
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);

    // get handle to shape's transformation matrix
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

}

我的表面 View 如下:

public class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context, AttributeSet attrs){
    super(context, attrs);

    //Create an OpenGl 3.0 context
    setEGLContextClientVersion(3);

    mRenderer = new MyGLRenderer();

    //Set the Renderer for drawing on the GLSurfaceView
    setRenderer(mRenderer);
}

}

我正在寻找一个简单的示例/答案/URL,可以完成在 y 轴上移动绘制的三角形(我假设使用翻译)。

我已阅读并尝试实现以下链接(某种程度上超出了我目前的理解)。

  1. http://www.swiftless.com/tutorials/opengl/rotation.html
  2. http://www.songho.ca/opengl/gl_transform.html
  3. https://open.gl/transformations
  4. http://www.informit.com/articles/article.aspx?p=2111395&seqNum=3
  5. http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

以及其他一些来源,但这些似乎是我找到的最好的来源。

最佳答案

是的,这将是一个翻译。非常简单,只需修改Triangledraw()方法中的mvpMatrix即可。

但是,跟踪三角形的位置以使其移动非常重要。您可以将私有(private)成员添加到类似于此的类中:

private Point mPosition;

请记住,该代码中的 Point 是一个简单的点/vector 类,我假设您有,因为我很确定这是在 Android 上?查看this class .

然后,您需要增加每帧三角形的 y 位置。您可以在 draw() 中执行此操作,但我会添加另一种移动方法。

mPosition.y += 0.01;

注意:我看到您有一个 MVP 矩阵作为 draw 的参数。现在,由于这是 2D 且正交的,所以它并不那么重要,但请考虑将旋转从 onDrawFrame() 函数移动到 Triangle.draw(),因为 M 代表模型,通常是每个模型/三角形。通常,您只需将 VP( View 和投影)传递给 Triangle.draw() 方法。检查this出来。

最后,您将在 Triangle.draw() 方法中将 mvp 矩阵平移三角形的位置。因此,在将矩阵传递给着色器之前(在 GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 之前),对其进行翻译:

Matrix.translateM(mvpMatrix, mPosition.x, mPosition.y);
// Or whatever translate method you have, I am not sure

关于java - 使用 Java 或 C# 在 Y 轴上进行 Open GL 翻译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35810971/

相关文章:

java - 如何填充接口(interface)列表?

c# - MvcRazorToPdf - 图像不渲染,MVC4

c# - 关闭winform但继续在任务栏运行

c++ - 有没有办法更改现有GLFW窗口的MSAA样本数量?

c++ - glPush/PopMatrix() 和 glRotatef() 似乎是单独移动对象,而不是 glPush/PopMatrix() 中包含的所有对象

opengl - 如何将 OpenGL 纹理转换为 CUDA 纹理?

java - 将 java.lang.Object 作为参数传递

java - 在 Spring boot Transaction 中以只读方式执行 RxJava observable?

java - 将 JSONObject 获取到字符串数组值时出现问题

c# - 从第一列不包含的数据表中删除行(一些字符串)