تطبيق مرات العرض والكاميرات

في بيئة 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() ثم دمجها مع مصفوفة الإسقاط المحسوبة سابقًا. القيم المجمّعة يتم بعد ذلك تمرير مصفوفات التحويل إلى الشكل المرسوم.

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

تطبيق تحسينات العرض والكاميرا

ومن أجل استخدام المصفوفة المدمجة لتحويل عرض الكاميرا والإسقاط الموضحة في معاينة الأقسام، عليك أولاً إضافة متغيّر مصفوفة إلى أداة تظليل الرأس التي سبق تعريفها. في الفئة 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. مثلث مرسوم مع عرض وعرض الكاميرا.

الآن بعد أن أصبح لديك تطبيق يعرض الأشكال بنسب صحيحة، حان الوقت لإضافة حركة إلى أشكالك.