Zdefiniowanie kształtów do rysowania w kontekście widoku OpenGL ES to pierwszy etap tworzenia wysokiej jakości grafiki dla aplikacji. Rysowanie za pomocą OpenGL ES może być nieco trudne, jeśli nie trzeba znać kilku podstawowych kwestii o tym, jak OpenGL ES oczekuje definiowania obiektów graficznych.
Ta lekcja przedstawia układ współrzędnych OpenGL ES względem ekranu urządzenia z Androidem, podstawowe zasady definiowania kształtu i płaszczyzn oraz definiowania trójkątów i kwadratów.
Zdefiniuj trójkąt
OpenGL ES umożliwia definiowanie rysowanych obiektów przy użyciu współrzędnych w przestrzeni trójwymiarowej. Zanim więc narysujesz trójkąt, musisz określić jego współrzędne. W trybie OpenGL typowym sposobem jest zdefiniowanie tablicy wierzchołkowej liczb zmiennoprzecinkowych dla współrzędnych. Aby uzyskać maksymalną wydajność, zapisujesz te współrzędne w obiekcie ByteBuffer
, który jest przekazywany do potoku graficznego OpenGL ES w celu przetworzenia.
Kotlin
// number of coordinates per vertex in this array const val COORDS_PER_VERTEX = 3 var triangleCoords = floatArrayOf( // in counterclockwise order: 0.0f, 0.622008459f, 0.0f, // top -0.5f, -0.311004243f, 0.0f, // bottom left 0.5f, -0.311004243f, 0.0f // bottom right ) class Triangle { // Set color with red, green, blue and alpha (opacity) values val color = floatArrayOf(0.63671875f, 0.76953125f, 0.22265625f, 1.0f) private var vertexBuffer: FloatBuffer = // (number of coordinate values * 4 bytes per float) ByteBuffer.allocateDirect(triangleCoords.size * 4).run { // use the device hardware's native byte order order(ByteOrder.nativeOrder()) // create a floating point buffer from the ByteBuffer asFloatBuffer().apply { // add the coordinates to the FloatBuffer put(triangleCoords) // set the buffer to read the first coordinate position(0) } } }
Java
public class Triangle { private FloatBuffer vertexBuffer; // number of coordinates per vertex in this array static final int COORDS_PER_VERTEX = 3; static float triangleCoords[] = { // in counterclockwise order: 0.0f, 0.622008459f, 0.0f, // top -0.5f, -0.311004243f, 0.0f, // bottom left 0.5f, -0.311004243f, 0.0f // bottom right }; // Set color with red, green, blue and alpha (opacity) values float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; public Triangle() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect( // (number of coordinate values * 4 bytes per float) triangleCoords.length * 4); // use the device hardware's native byte order bb.order(ByteOrder.nativeOrder()); // create a floating point buffer from the ByteBuffer vertexBuffer = bb.asFloatBuffer(); // add the coordinates to the FloatBuffer vertexBuffer.put(triangleCoords); // set the buffer to read the first coordinate vertexBuffer.position(0); } }
Domyślnie OpenGL ES zakłada układ współrzędnych, w którym [0,0,0] (X,Y,Z) określa środek ramki GLSurfaceView
, [1,1,0] to prawy górny róg ramki, a [-1,-1,0] to lewy dolny róg klatki. Przykład tego układu współrzędnych znajdziesz w przewodniku dla programistów OpenGL ES.
Zauważ, że współrzędne tego kształtu są określone w kierunku przeciwnym do ruchu wskazówek zegara. Kolejność rysowania jest ważna, ponieważ określa, która strona jest przednią ścianą kształtu, którą zwykle chcesz narysować, oraz tylną ścianę, której nie można rysować za pomocą funkcji wygładzania OpenGL ES. Więcej informacji o twarzach i identyfikowaniu znajdziesz w przewodniku dla programistów OpenGL ES.
Zdefiniuj kwadrat
W trybie OpenGL definiowanie trójkątów jest proste, ale co jeśli chcesz uzyskać nieco bardziej złożone elementy? Powiedzmy, kwadrat? Można to zrobić na wiele sposobów, ale typową metodą rysowania takiego kształtu w Open OpenGL ES jest użycie 2 połączonych ze sobą trójkątów:
![](https://developer.android.google.cn/static/images/opengl/ccw-square.png?authuser=6&hl=pl)
Rysunek 1. Rysowanie kwadratu z dwóch trójkątów.
Ponownie zdefiniuj wierzchołki w lewo dla obu trójkątów reprezentujących ten kształt i podaj ich wartości w polu ByteBuffer
. Aby uniknąć dwukrotnego zdefiniowania dwóch współrzędnych wspólnych dla każdego trójkąta, użyj listy rysunków, aby przekazać potokowi graficznemu OpenGL ES instrukcje rysowania tych wierzchołków. Oto kod tego kształtu:
Kotlin
// number of coordinates per vertex in this array const val COORDS_PER_VERTEX = 3 var squareCoords = floatArrayOf( -0.5f, 0.5f, 0.0f, // top left -0.5f, -0.5f, 0.0f, // bottom left 0.5f, -0.5f, 0.0f, // bottom right 0.5f, 0.5f, 0.0f // top right ) class Square2 { private val drawOrder = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw vertices // initialize vertex byte buffer for shape coordinates private val vertexBuffer: FloatBuffer = // (# of coordinate values * 4 bytes per float) ByteBuffer.allocateDirect(squareCoords.size * 4).run { order(ByteOrder.nativeOrder()) asFloatBuffer().apply { put(squareCoords) position(0) } } // initialize byte buffer for the draw list private val drawListBuffer: ShortBuffer = // (# of coordinate values * 2 bytes per short) ByteBuffer.allocateDirect(drawOrder.size * 2).run { order(ByteOrder.nativeOrder()) asShortBuffer().apply { put(drawOrder) position(0) } } }
Java
public class Square { private FloatBuffer vertexBuffer; private ShortBuffer drawListBuffer; // number of coordinates per vertex in this array static final int COORDS_PER_VERTEX = 3; static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left -0.5f, -0.5f, 0.0f, // bottom left 0.5f, -0.5f, 0.0f, // bottom right 0.5f, 0.5f, 0.0f }; // top right private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices public Square() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect( // (# of coordinate values * 4 bytes per float) squareCoords.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(squareCoords); vertexBuffer.position(0); // initialize byte buffer for the draw list ByteBuffer dlb = ByteBuffer.allocateDirect( // (# of coordinate values * 2 bytes per short) drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); } }
Ten przykład pokazuje, jak można tworzyć bardziej złożone kształty za pomocą OpenGL. Ogólnie do rysowania obiektów wykorzystuje się zbiory trójkątów. Na następnej lekcji dowiesz się, jak rysować na ekranie.