W środowisku OpenGL ES funkcja projekcji i widoki kamery pozwalają wyświetlać narysowane obiekty na podobieństwo sposobu, w jaki widzicie obiekty oczami. Ta symulacja fizyczne przeglądanie polega na przekształcaniu matematycznych współrzędnych obiektów:
- Odwzorowanie – to przekształcenie dostosowuje współrzędne rysowanych obiektów na podstawie
szerokość i wysokość
GLSurfaceView
, w których są wyświetlane. Bez w tych obliczeniach obiekty rysowane przez OpenGL ES są zniekształcone przez nierówne proporcje obrazu okno. Transformacja rzutująca zwykle musi być obliczona tylko wtedy, gdy proporcje Widok OpenGL jest ustanawiany lub zmieniany w metodzieonSurfaceChanged()
mechanizmu renderowania. Więcej informacji na temat projekcji OpenGL ES mapowanie współrzędnych, patrz Nanoszenie współrzędnych na mapie . - Widok kamery – to przekształcenie dostosowuje współrzędne rysowanych obiektów na podstawie
pozycji kamery wirtualnej. Należy pamiętać, że OpenGL ES nie definiuje rzeczywistej kamery.
, ale zapewnia metody użytkowe symulujące działanie kamery przez przekształcenie obrazu
narysowanych obiektach. Transformacja widoku z kamery może zostać obliczona tylko raz po ustawieniu
GLSurfaceView
lub może się zmieniać dynamicznie w zależności od działań użytkowników lub do funkcji aplikacji.
Z tej lekcji dowiesz się, jak utworzyć projekcję i widok z kamery oraz zastosować je do kształtów rysowanych
GLSurfaceView
.
Definiowanie prognozy
Dane na potrzeby przekształcenia prognozy są obliczane w onSurfaceChanged()
klasy GLSurfaceView.Renderer
. Oto przykładowy kod
pobiera wysokość i szerokość GLSurfaceView
i używa ich do wypełnienia
przekształcenie prognozy Matrix
przy użyciu metody 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); }
Ten kod wypełnia macierz wyświetlania, mProjectionMatrix
, którą można następnie połączyć.
z przekształceniem widoku z kamery w metodzie onDrawFrame()
, co pokazano w następnej sekcji.
Uwaga: samo zastosowanie przekształcenia prognozy rysowanie obiektów zazwyczaj skutkuje bardzo pustym wyświetlaniem. Ogólnie rzecz biorąc, trzeba również użyć aparatu wyświetlić przekształcenie, aby pokazać na ekranie cokolwiek.
Zdefiniuj widok z kamery
Dokończ proces przekształcania rysowanych obiektów, dodając przekształcenie widoku kamery jako
stanowią część procesu rysowania. W poniższym przykładowym kodzie widok z kamery
przekształcenie jest obliczane za pomocą funkcji Matrix.setLookAtM()
a następnie połączona z obliczoną wcześniej macierzą projekcji. Połączone
macierze transformacji są następnie przekazywane do narysowanego kształtu.
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); }
Zastosuj przekształcanie obrazu i kamery
Aby zastosować połączone projekcję i macierz przekształcenia obrazu z kamery widoczną w
podgląd sekcji, najpierw dodaj zmienną macierzy do wcześniej zdefiniowanego programu do cieniowania wierzchołków
w zajęciach 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; ... }
Następnie zmodyfikuj metodę draw()
obiektów graficznych, by zaakceptować połączone wartości
macierz transformacji i zastosuj ją do kształtu:
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); }
Po prawidłowym obliczeniu i zastosowaniu przekształceń obrazu i widoku z kamery obiekty graficzne są rysowane we właściwych proporcjach i powinny wyglądać tak:
![](https://developer.android.google.cn/static/images/opengl/ogl-triangle-projected.png?authuser=8&hl=pl)
Rysunek 1. Trójkąt narysowany z projekcją i widokiem z kamery.
Teraz gdy masz już aplikację, która wyświetla kształty w odpowiednich proporcjach, czas aby dodać ruch do kształtów.