为什么不是我的OpenGL坐标系轴[-1; 1]?

时间:2017-02-27 16:03:37

标签: java android opengl-es opengl-es-2.0

我正在进入open gl es 2.0(在android上)并且我很困惑,因为我在this video(在1:11:05)听到坐标系显示的范围是-1在所有3个轴中为1,但它们在my project (https://github.com/SimonLammer/Android-GlEs20CameraOverlay/tree/without-camera-preview/app/src/main/java/simonlammer/htlleonding/ac/at/openglcameraoverlay)

中的范围从-2到2

如果我使用坐标((-1 | -1 | 0),(0 | 1 | 0),(1 | 0 | 0)),我得到的三角形只有我预期的一半大是:

triangle: ((-1|-1|0), (0|1|0), (1|0|0))

我的假设是坐标系以某种方式缩放不正确,因为如果我将坐标加倍为((-2 | -2 | 0),(0 | 2 | 0),(2 | 0 | 0)) ,我从一开始就得到了我的期望:

triangle: ((-2|-2|0), (0|2|0), (2|0|0))

为什么会发生这种情况以及如何修复它,以便在使用第一组坐标((-1 | -1 | 0)时,我在整个屏幕上缩放三角形(如第二张图片); 0 | 1 | 0),(1 | 0 | 0))?

代码:

活动XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="simonlammer.htlleonding.ac.at.openglcameraoverlay.MainActivity">

        <simonlammer.htlleonding.ac.at.openglcameraoverlay.GlOverlay
            android:id="@+id/overlay"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

</RelativeLayout>

MainActivity:

public class MainActivity extends AppCompatActivity {
    private GlOverlay glOverlay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        glOverlay = (GlOverlay) findViewById(R.id.overlay);
    }

    @Override
    protected void onPause() {
        glOverlay.onPause();
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        glOverlay.onResume();
    }
}

GlOverlay:

public class GlOverlay extends GLSurfaceView {
    private GlEs20Renderer renderer;

    public GlOverlay(Context context) {
        super(context);
        init();
    }

    public GlOverlay(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        this.renderer = new GlEs20Renderer();
        this.setEGLContextClientVersion(2);
        this.setRenderer(renderer);
        this.setRenderMode(RENDERMODE_CONTINUOUSLY);
    }
}

GlEs20Renderer:

public class GlEs20Renderer implements GLSurfaceView.Renderer {
    private static final int COORDS_PER_VERTEX = 4;
    private final float[] triangleCoords = {
            -1.0f, -1.0f, 0.0f, 1.0f,
            0.0f,  1.0f, 0.0f, 1.0f,
            1.0f,  0.0f, 0.0f, 1.0f
    };
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per float
    private FloatBuffer vertexBuffer;

    private boolean setup = false;
    private int program = -1;

    private void setup() {
        vertexBuffer = ByteBuffer.allocateDirect(triangleCoords.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        String vertexShaderSource =
                "attribute vec4 vPosition;" +
                "uniform vec4 vTranslate;" +
                "void main() {" +
                "  gl_Position = vPosition + vTranslate;" +
                "}";

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


        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                vertexShaderSource);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderSource);

        // create empty OpenGL ES Program
        program = GLES20.glCreateProgram();

        // add the vertex shader to program
        GLES20.glAttachShader(program, vertexShader);

        // add the fragment shader to program
        GLES20.glAttachShader(program, fragmentShader);

        // creates OpenGL ES program executables
        GLES20.glLinkProgram(program);
    }

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

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

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

        return shader;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    }

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

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        if (!setup) {
            setup();
            setup = true;
        }

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        // Add program to OpenGL ES environment
        GLES20.glUseProgram(program);

        // get handle to vertex shader's vPosition member
        int mPositionHandle = GLES20.glGetAttribLocation(program, "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
        int mColorHandle = GLES20.glGetUniformLocation(program, "vColor");

        // Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, new float[] {0.5f, 0.0f, 0.0f, 1.0f}, 0);

        // move
        GLES20.glUniform4fv(GLES20.glGetUniformLocation(program, "vTranslate"), 1, new float[] {0f, 0f, 0f, 1f}, 0);

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

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

1 个答案:

答案 0 :(得分:1)

问题来自翻译向量以及齐次坐标的工作原理。简而言之,裁剪后你的位置会被他们的w分量分开。如果您现在有一个职位A = [x,y,z,1]并添加了一个翻译[0,0,0,1],则结果为[x,y,z,2],并且在透视分割[x/2,y/2,z/2,1]之后。

要解决您的问题,请将翻译向量的第4个分量设置为0,或者只使用三维平移向量。