ในสภาพแวดล้อม 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); }
เมื่อคุณคำนวณและใช้การเปลี่ยนรูปแบบการฉายภาพและมุมมองกล้องอย่างถูกต้องแล้ว วัตถุกราฟิกของคุณถูกวาดในสัดส่วนที่ถูกต้องและควรมีลักษณะเช่นนี้:
![](https://developer.android.com/static/images/opengl/ogl-triangle-projected.png?hl=th)
รูปที่ 1 สามเหลี่ยมที่วาดโดยใช้การฉายภาพและมุมมองกล้อง
เมื่อคุณมีแอปพลิเคชันที่แสดงรูปร่างของคุณในสัดส่วนที่ถูกต้องแล้ว ก็ได้เวลา เพิ่มการเคลื่อนไหวให้กับรูปร่างได้