نماهای پروجکشن و دوربین را اعمال کنید

در محیط OpenGL ES، نماهای طرح ریزی شده و دوربین به شما امکان می دهند اشیاء ترسیم شده را به گونه ای نمایش دهید که شباهت بیشتری به نحوه دیدن اشیاء فیزیکی با چشمان خود داشته باشد. این شبیه سازی مشاهده فیزیکی با تبدیل های ریاضی مختصات شیء ترسیم شده انجام می شود:

  • Projection - این تبدیل مختصات اشیاء ترسیم شده را بر اساس عرض و ارتفاع GLSurfaceView که در آن نمایش داده می شوند، تنظیم می کند. بدون این محاسبه، اشیاء ترسیم شده توسط OpenGL ES با نسبت‌های نابرابر پنجره مشاهده منحرف می‌شوند. یک تبدیل طرح‌ریزی معمولاً فقط باید زمانی محاسبه شود که نسبت‌های نمای OpenGL در متد onSurfaceChanged() رندر شما ایجاد یا تغییر کند. برای اطلاعات بیشتر درباره پیش‌بینی‌های OpenGL ES و نگاشت مختصات، به نقشه‌برداری مختصات برای اشیاء ترسیم شده مراجعه کنید.
  • نمای دوربین - این تبدیل مختصات اشیاء ترسیم شده را بر اساس موقعیت دوربین مجازی تنظیم می کند. توجه به این نکته مهم است که OpenGL ES یک شی دوربین واقعی را تعریف نمی‌کند، بلکه روش‌های مفیدی را ارائه می‌کند که دوربین را با تبدیل نمایش اشیاء ترسیم شده شبیه‌سازی می‌کند. هنگامی که GLSurfaceView خود را ایجاد می‌کنید، تغییر نمای دوربین ممکن است فقط یک بار محاسبه شود، یا ممکن است به صورت پویا بر اساس اقدامات کاربر یا عملکرد برنامه شما تغییر کند.

این درس نحوه ایجاد نمایان و نمای دوربین و اعمال آن بر روی اشکال ترسیم شده در GLSurfaceView را توضیح می دهد.

فرافکنی را تعریف کنید

داده های یک تبدیل طرح ریزی در روش onSurfaceChanged() کلاس GLSurfaceView.Renderer شما محاسبه می شود. کد مثال زیر ارتفاع و عرض GLSurfaceView را می گیرد و از آن برای پر کردن یک Matrix تبدیل طرح با استفاده از متد Matrix.frustumM() استفاده می کند:

کاتلین

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

جاوا

// 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() محاسبه شده و سپس با ماتریس طرح ریزی محاسبه شده قبلی ترکیب می شود. سپس ماتریس های تبدیل ترکیبی به شکل رسم شده منتقل می شوند.

کاتلین

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)

جاوا

@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 تعریف شده بود اضافه کنید:

کاتلین

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

    ...
}

جاوا

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() اشیاء گرافیکی خود را تغییر دهید تا ماتریس تبدیل ترکیبی را بپذیرد و آن را روی شکل اعمال کنید:

کاتلین

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

جاوا

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. مثلث ترسیم شده با برجستگی و نمای دوربین اعمال شده.

اکنون که اپلیکیشنی دارید که اشکال شما را با نسبت های صحیح نمایش می دهد، زمان آن رسیده است که حرکت را به اشکال خود اضافه کنید.