Android改变OpenGL坐标系

3

好的,我找到了这个线程,这就是我需要做的。然而,我没有使用GL10而是使用GLES20glOrthof不是GLES20 API的一部分。

我想要做的是将坐标系的范围从[-1, 1]更改为[0,1]。这是正常的系统。

Normal Coord System

我想要更改它,使它变成下面这样。

enter image description here

屏幕中心是0.5f, 0.5f,左下角是0f,0f等。它只有2D。

private final String vertexShaderCode = 
    "uniform mat4 uMVPMatrix;" +  
    "attribute vec4 aPosition;" +   
    "attribute vec2 aTexCoordinate;" +  
    "varying vec2 vTexCoordinate;" +
    "void main() {" +
    "  gl_Position = uMVPMatrix * aPosition;" +
    "  vTexCoordinate = aTexCoordinate;" +
    "}";

这是我的渲染器类

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

import com.matt.world.World;


public class OpenGLRenderer implements GLSurfaceView.Renderer {

    private static final String TAG = "OpenGLRenderer";             // Tag for the logcat error message

    private final float[] mMVPMatrix = new float[16];               // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];
    private final float[] mTranslationMatrix = new float[16];

    private World mWorld;                                           // World object
    private long mStartTime;                                        // Start time

    public volatile float mPlayerInputX;                            // Variable to receive player coordinate input
    public volatile float mPlayerInputY;                            // Variable to receive player coordinate input
    public volatile boolean mFireWeapon = false;                    // Variable to handle player fire commands
    public volatile boolean mToggleShield = false;                  // Variable to handle player shield toggle
    public volatile boolean mToggleLaser = false;                   // Variable to handle player laser toggle

    @Override
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {   // Called once when the surface is created

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                // Set the background frame color
        GLES20.glEnable(GLES20.GL_TEXTURE_2D);                      // Enable textures
        mWorld = new World(this);                                   // Initialize World object
    }

    @Override
    public void onDrawFrame(GL10 unused) {                          // Called every frame
        float[] scratch = new float[16];                            // Container for matrix manipulations
        float decimal = 1000000000.0f;                              // Divisor to move the decimal point for delta time

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |                 // Draw background color
                GLES20.GL_DEPTH_BUFFER_BIT);

        Matrix.setLookAtM(mViewMatrix,                              // Set the camera position (View matrix)
                0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        Matrix.multiplyMM(mMVPMatrix,                               // Calculate the projection and view transformation
                0, mProjectionMatrix, 0, mViewMatrix, 0);

        float deltaTime = (System.nanoTime()-mStartTime)/decimal;   // Calculate delta time
        mStartTime = System.nanoTime();                             // Get the time now for next frame calculations
        mWorld.update(mMVPMatrix, deltaTime);                       // Update World
        mWorld.draw();                                              // Draw World
    }

    @Override
    public void onSurfaceChanged(GL10 unused, int width, int height) {

        GLES20.glViewport(0,0, width, height);                       // Adjust the viewport based on geometry changes,


        float ratio = (float) height / width;                       // such as screen rotation

        Matrix.setIdentityM(mProjectionMatrix, 0);                  // Set this matrix to the identity matrix

        Matrix.frustumM(mProjectionMatrix,                          // this projection matrix is applied to object coordinates
                0,-ratio, ratio, 0, 1, 3, 7);                       // in the onDrawFrame() method*/

        mStartTime = System.nanoTime();                             // keep record of what the current time is
    }

    public static int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type);                   // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
                                                                    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        GLES20.glShaderSource(shader, shaderCode);                  // add the source code to the shader and
        GLES20.glCompileShader(shader);                             // compile it
        return shader;
    }

    public static void checkGlError(String glOperation) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, glOperation + ": glError " + error);
            throw new RuntimeException(glOperation + ": glError " + error);
        }
    }

}
1个回答

1
< p > Ortho仍然需要使用矩阵。因此,在您的着色器中,您将使用一个矩阵作为uniform,该矩阵乘以输入位置。

一般情况下,您无法改变坐标系统。OpenGL使用归一化坐标,因此无论您做什么,缓冲区的中心始终为0,边界从左到右和从底部到顶部为[-1,1],深度也是如此当使用深度缓冲区时。

因此,正交矩阵所做的是将您的输入坐标缩放到OpenGL内部坐标系统,并且这是即使ES1也执行的过程,但不同之处在于矩阵已经为您生成,并且所有坐标都在固定管道中为您乘以。


这是我的着色器,你建议我在哪里进行更改? - chewpoclypse
哪些更改?您是否遇到其他问题?矩阵似乎在那里,如果它连接正确,它应该可以工作。 - Matic Oblak
我想要做的是调整渲染表面。基本上,我试图将渲染表面翻译为左0下0上1右1,然后设置视口为0,0,屏幕宽度, 屏幕高度。如果这不太清楚,抱歉。 - chewpoclypse
是的。但是您已经在着色器中拥有了矩阵,因此需要在绘图管道中生成正交矩阵。MVP矩阵表示MVP,其中这些是模型、视图和投影矩阵。至少在渲染器中,您应该将所有3个矩阵分别保存,并将它们乘以MVP并将其发送到着色器。然后,投影矩阵应该对应于正交(或三维视锥体),并且应在表面更改时创建。其余部分可能是单位矩阵,但可以表示:视图-相机;模型-空间中的对象。 - Matic Oblak
好的,我已经添加了我的Renderer类,请您告诉我需要进行哪些调整?我意识到我正在使用frustrum,但当我改用ortho时却没有任何变化。 - chewpoclypse
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接