Projeksiyon ve kamera görünümleri uygulama

OpenGL ES ortamında, projeksiyon ve kamera görünümleri, çizilen nesneleri, fiziksel nesneleri gözlerinizle görme şeklinize daha çok benzeyen bir şekilde görüntülemenizi sağlar. Bu fiziksel görüntüleme simülasyonu, çizilen nesne koordinatlarının matematiksel dönüşümleriyle yapılır:

  • Projeksiyon - Bu dönüştürme, çizilen nesnelerin koordinatlarını gösterildikleri GLSurfaceView genişliğine ve yüksekliğine göre ayarlar. Bu hesaplama yapılmadığında, OpenGL ES tarafından çizilen nesneler, görünüm penceresinin eşit olmayan oranlarıyla çarpıtılır. Bir projeksiyon dönüşümü genellikle yalnızca OpenGL görünümünün oranları oluşturucunuzun onSurfaceChanged() yönteminde oluşturulduğunda veya değiştirildiğinde hesaplanmalıdır. OpenGL ES projeksiyonları ve koordinat eşlemesi hakkında daha fazla bilgi için Çizilen nesneler için koordinatları eşleme bölümüne bakın.
  • Kamera Görünümü - Bu dönüştürme, çizilen nesnelerin koordinatlarını sanal kamera konumuna göre ayarlar. OpenGL ES'nin gerçek bir kamera nesnesi tanımlamadığını, bunun yerine çizilen nesnelerin görüntüsünü dönüştürerek bir kamerayı simüle eden yardımcı yöntemler sunduğunu unutmamak önemlidir. Kamera görünümü dönüşümü, GLSurfaceView oluşturduğunuzda yalnızca bir kez hesaplanabilir veya kullanıcı işlemlerine ya da uygulamanızın işlevine bağlı olarak dinamik olarak değiştirilebilir.

Bu derste, nasıl projeksiyon ve kamera görünümü oluşturacağınız ve bunu GLSurfaceView dosyanızda çizilen şekillere nasıl uygulayacağınız açıklanmaktadır.

Projeksiyon tanımlama

Projeksiyon dönüşümü verileri, GLSurfaceView.Renderer sınıfınızın onSurfaceChanged() yönteminde hesaplanır. Aşağıdaki örnek kod, GLSurfaceView yüksekliğini ve genişliğini alır ve Matrix.frustumM() yöntemini kullanarak Matrix projeksiyon dönüşümünü doldurmak için kullanır:

Kotlin

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private val vPMatrix = FloatArray(16)
private val projectionMatrix = FloatArray(16)
private val viewMatrix = FloatArray(16)

override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) {
    GLES20.glViewport(0, 0, width, height)

    val ratio: Float = width.toFloat() / height.toFloat()

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

Java

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

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

Bu kod bir projeksiyon matrisini doldurur. mProjectionMatrix daha sonra, bir sonraki bölümde gösterilen onDrawFrame() yöntemindeki bir kamera görünümü dönüşümüyle birleştirebilirsiniz.

Not: Çizim nesnelerinize yalnızca bir projeksiyon dönüşümü uygulamak genellikle çok boş bir ekranla sonuçlanır. Genel olarak, bir şeyin ekranda görünmesi için kamera görünümü dönüşümü de uygulamanız gerekir.

Kamera görünümü tanımlama

Oluşturucunuzda çizim sürecinin bir parçası olarak kamera görünümü dönüşümü ekleyerek çizdiğiniz nesneleri dönüştürme işlemini tamamlayın. Aşağıdaki örnek kodda, kamera görünümü dönüşümü Matrix.setLookAtM() yöntemi kullanılarak hesaplanır ve ardından daha önce hesaplanan projeksiyon matrisi ile birleştirilir. Daha sonra, birleştirilmiş dönüşüm matrisleri çizilen şekle geçirilir.

Kotlin

override fun onDrawFrame(unused: GL10) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0)

    // Draw shape
    triangle.draw(vPMatrix)

Java

@Override
public void onDrawFrame(GL10 unused) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

    // Draw shape
    triangle.draw(vPMatrix);
}

Projeksiyon ve kamera dönüşümleri uygulayın

Önizleme bölümlerinde gösterilen birleşik projeksiyon ve kamera görünümü dönüştürme matrisini kullanmak için önce, önceden Triangle sınıfında tanımlanan tepe gölgelendiricisine bir matris değişkeni ekleyin:

Kotlin

class Triangle {

    private val 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;" +
            "}"

    // Use to access and set the view transformation
    private var vPMatrixHandle: Int = 0

    ...
}

Java

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;" +
        "}";

    // Use to access and set the view transformation
    private int vPMatrixHandle;

    ...
}

Ardından, birleştirilmiş dönüşüm matrisini kabul etmek için grafik nesnelerinizin draw() yöntemini değiştirin ve şekle uygulayın:

Kotlin

fun draw(mvpMatrix: FloatArray) { // pass in the calculated transformation matrix

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

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0)

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

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(positionHandle)
}

Java

public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
    ...

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

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0);

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

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

Projeksiyon ve kamera görünümü dönüşümlerini doğru bir şekilde hesaplayıp uyguladıktan sonra, grafik nesneleriniz doğru oranlarda çizilir ve şöyle görünmelidir:

Şekil 1. Projeksiyon ve kamera görünümü uygulanmış üçgen.

Artık şekillerinizi doğru oranlarda görüntüleyen bir uygulamanıza sahip olduğunuza göre şekillerinize hareket eklemenin zamanı geldi.