ใช้มุมมองการฉายภาพและกล้อง

ในสภาพแวดล้อม OpenGL ES มุมมองการฉายภาพและกล้องจะช่วยให้คุณแสดงวัตถุที่วาดใน ให้คล้ายกับการมองวัตถุทางกายภาพด้วยตาของคุณมากขึ้น การจำลองของ การดูทางกายภาพจะทำโดยใช้การแปลงทางคณิตศาสตร์ของพิกัดวัตถุที่วาด:

  • การฉายภาพ - การแปลงนี้จะปรับพิกัดของวัตถุที่วาดตาม ความกว้างและความสูงของ GLSurfaceView ในตำแหน่งที่แสดง ไม่มี การคำนวณนี้ทำให้วัตถุที่วาดด้วย OpenGL ES จะเอียงตามสัดส่วนของมุมมองที่ไม่เท่ากัน โดยทั่วไปแล้ว การเปลี่ยนรูปแบบการคาดการณ์จะต้องคำนวณเมื่อสัดส่วนของ มุมมอง OpenGL สร้างหรือเปลี่ยนแปลงในเมธอด onSurfaceChanged() ของโหมดแสดงภาพ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการคาดการณ์ OpenGL ES และ การทำแผนที่พิกัด, ดู พิกัดแผนที่สำหรับการวาด ออบเจ็กต์
  • มุมมองกล้องถ่ายรูป - การแปลงนี้จะปรับพิกัดของวัตถุที่วาดตาม ตำแหน่งของกล้องเสมือน โปรดทราบว่า OpenGL ES ไม่ได้กำหนดกล้องจริง แต่มอบวิธีการด้านประโยชน์ใช้สอย ซึ่งจำลองกล้องด้วยการแปลงการแสดงผลของ วัตถุที่วาดไว้ การแปลงมุมมองกล้องอาจคำนวณได้เพียงครั้งเดียวเมื่อคุณสร้าง GLSurfaceView หรืออาจเปลี่ยนแปลงแบบไดนามิกตามการกระทำของผู้ใช้หรือ ฟังก์ชันของแอปพลิเคชัน

บทเรียนนี้จะอธิบายวิธีสร้างมุมมองการฉายภาพและมุมมองกล้องและนำไปใช้กับรูปร่างที่วาด GLSurfaceView

กำหนดการฉายภาพ

ข้อมูลสำหรับการเปลี่ยนรูปแบบการคาดการณ์จะคำนวณใน onSurfaceChanged() ของชั้นเรียน GLSurfaceView.Renderer โค้ดตัวอย่างต่อไปนี้ จะใช้ความสูงและความกว้างของ GLSurfaceView และใช้เพื่อสร้าง การเปลี่ยนรูปแบบการคาดการณ์ Matrix โดยใช้เมธอด Matrix.frustumM():

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);
}

โค้ดนี้จะสร้างเมทริกซ์การฉายภาพ mProjectionMatrix ซึ่งคุณสามารถรวมเข้าด้วยกันได้ พร้อมการแปลงโฉมมุมมองกล้องในเมธอด onDrawFrame() ซึ่งจะแสดงในส่วนถัดไป

หมายเหตุ: เพียงแค่ใช้การเปลี่ยนรูปแบบการฉายภาพกับ วัตถุที่วาดมักจะทำให้หน้าจอว่างเปล่ามาก โดยทั่วไปคุณต้องใช้กล้อง ดูการเปลี่ยนรูปแบบเพื่อให้สิ่งต่างๆ แสดงบนหน้าจอ

กำหนดมุมมองกล้อง

เปลี่ยนรูปแบบวัตถุที่วาดให้เสร็จสมบูรณ์โดยการเพิ่มการแปลงโฉมมุมมองกล้องเป็น ของกระบวนการวาดภาพ ในโปรแกรมแสดงภาพของคุณ ในโค้ดตัวอย่างต่อไปนี้ มุมมองกล้อง การเปลี่ยนรูปแบบคํานวณโดยใช้Matrix.setLookAtM() แล้วนำไปรวมกับเมทริกซ์การฉายภาพที่คำนวณไว้ก่อนหน้า ทั้ง 2 ฝ่าย เมทริกซ์การเปลี่ยนรูปแบบจะส่งไปยังรูปร่างที่วาด

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);
}

ใช้การฉายภาพและการเปลี่ยนรูปแบบของกล้อง

เพื่อที่จะใช้เมทริกซ์การเปลี่ยนรูปแบบการฉายภาพและมุมมองกล้องแบบรวมที่แสดงใน สำหรับตัวอย่างส่วนแสดงตัวอย่าง ก่อนอื่นให้เพิ่มตัวแปรเมทริกซ์ลงใน vertex Shadow ที่กำหนดไว้ก่อนหน้านี้ ในชั้นเรียน Triangle:

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;

    ...
}

ถัดไป ให้แก้ไขเมธอด draw() ของออบเจ็กต์กราฟิกเพื่อยอมรับการรวม เมทริกซ์การเปลี่ยนรูปแบบแล้วใช้กับรูปร่าง

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);
}

เมื่อคุณคำนวณและใช้การเปลี่ยนรูปแบบการฉายภาพและมุมมองกล้องอย่างถูกต้องแล้ว วัตถุกราฟิกของคุณถูกวาดในสัดส่วนที่ถูกต้องและควรมีลักษณะเช่นนี้:

รูปที่ 1 สามเหลี่ยมที่วาดโดยใช้การฉายภาพและมุมมองกล้อง

เมื่อคุณมีแอปพลิเคชันที่แสดงรูปร่างของคุณในสัดส่วนที่ถูกต้องแล้ว ก็ได้เวลา เพิ่มการเคลื่อนไหวให้กับรูปร่างได้