OpenGL के साथ बनाए जाने वाले आकारों को परिभाषित करने के बाद, आप संभावित रूप से उन्हें बनाना चाहेंगे. आकृतियां बनाना OpenGL ES 2.0 के साथ आपकी कल्पना से थोड़ा ज़्यादा कोड लगता है, क्योंकि एपीआई आप ग्राफ़िक रेंडरिंग पाइपलाइन पर बहुत ज़्यादा कंट्रोल कर सकते हैं.
यह लेसन बताता है कि OpenGL का इस्तेमाल करके पिछले लेसन में तय किए गए आकार कैसे बनाएं ES 2.0 API.
आकार शुरू करना
इससे पहले कि आप कोई ड्रॉइंग करें, आपको उन आकारों को शुरू करना और लोड करना होगा, जिन्हें आप ड्रॉ करना चाहते हैं. जब तक कि
कोर्स के दौरान, प्रोग्राम में इस्तेमाल किए जाने वाले आकारों का स्ट्रक्चर (ओरिजनल कोऑर्डिनेट) बदल जाता है
तो आपको उन्हें
onSurfaceCreated()
तरीका
रेंडरर की सुविधा का इस्तेमाल करें.
Kotlin
class MyGLRenderer : GLSurfaceView.Renderer { ... private lateinit var mTriangle: Triangle private lateinit var mSquare: Square override fun onSurfaceCreated(unused: GL10, config: EGLConfig) { ... // initialize a triangle mTriangle = Triangle() // initialize a square mSquare = Square() } ... }
Java
public class MyGLRenderer implements GLSurfaceView.Renderer { ... private Triangle mTriangle; private Square mSquare; public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... // initialize a triangle mTriangle = new Triangle(); // initialize a square mSquare = new Square(); } ... }
आकार बनाने का तरीका
OpenGL ES 2.0 का इस्तेमाल करके किसी तय आकार को बनाने के लिए, बहुत ज़्यादा कोड की ज़रूरत होती है, क्योंकि ग्राफ़िक्स रेंडरिंग पाइपलाइन को बहुत सी जानकारी देनी होगी. खास तौर पर, आपको फ़ॉलो किया जा रहा है:
- Vertex Shader - किसी आकार के शीर्षों को रेंडर करने के लिए OpenGL ES ग्राफ़िक्स कोड.
- फ़्रैगमेंट शेडर - किसी आकार के चेहरे को रंगों या बनावट.
- प्रोग्राम - एक OpenGL ES ऑब्जेक्ट जिसमें ऐसे शेडर होते हैं जिनका इस्तेमाल आपको ड्रॉइंग के लिए करना है एक या उससे ज़्यादा आकार.
किसी आकार को ड्रॉ करने के लिए, आपको कम से कम एक वर्टेक्स शेडर और उस आकार को रंग देने के लिए एक फ़्रैगमेंट शेडर की ज़रूरत होगी.
इन शेडर को कंपाइल करना और फिर उन्हें OpenGL ES प्रोग्राम में जोड़ना चाहिए, जिसका इस्तेमाल ड्रॉ करने के लिए किया जाता है
आकार. यहां एक उदाहरण दिया गया है, जिसमें बेसिक शेडर को परिभाषित करने का तरीका बताया गया है. इसका इस्तेमाल करके,
Triangle
क्लास:
Kotlin
class Triangle { private val vertexShaderCode = "attribute vec4 vPosition;" + "void main() {" + " gl_Position = vPosition;" + "}" private val fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}" ... }
Java
public class Triangle { private final String vertexShaderCode = "attribute vec4 vPosition;" + "void main() {" + " gl_Position = vPosition;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; ... }
शेडर में OpenGL शेडिंग लैंग्वेज (जीएलएसएल) कोड होता है जिसे कोड में इस्तेमाल करने से पहले कंपाइल करना ज़रूरी होता है OpenGL ES वातावरण में उपलब्ध है. इस कोड को कंपाइल करने के लिए, अपनी रेंडरर क्लास में यूटिलिटी तरीका बनाएं:
Kotlin
fun loadShader(type: Int, shaderCode: String): Int { // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) return GLES20.glCreateShader(type).also { shader -> // add the source code to the shader and compile it GLES20.glShaderSource(shader, shaderCode) GLES20.glCompileShader(shader) } }
Java
public static int loadShader(int type, String shaderCode){ // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) int shader = GLES20.glCreateShader(type); // add the source code to the shader and compile it GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; }
अपना आकार बनाने के लिए, आपको शेडर कोड को कंपाइल करना होगा और उन्हें OpenGL ES प्रोग्राम में जोड़ना होगा ऑब्जेक्ट सबमिट करें और फिर प्रोग्राम को लिंक करें. इसे अपने ड्रॉ किए गए ऑब्जेक्ट के कंस्ट्रक्टर में करें, ताकि ऐसा सिर्फ़ हो सके एक बार.
ध्यान दें: OpenGL ES शेडर को कंपाइल करना और प्रोग्राम लिंक करना महंगा है और प्रोसेस करने में लगने वाले समय के हिसाब से काम करता है, इसलिए आपको ऐसा एक से ज़्यादा बार नहीं करना चाहिए. अगर आपके पास रनटाइम पर अपने शेडर की सामग्री नहीं जानते, तो आपको अपना कोड इस तरह बनाना चाहिए कि वे एक बार बनाया जाता है और बाद में इस्तेमाल के लिए कैश मेमोरी में सेव किया जाता है.
Kotlin
class Triangle { ... private var mProgram: Int init { ... val vertexShader: Int = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader: Int = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode) // create empty OpenGL ES Program mProgram = GLES20.glCreateProgram().also { // add the vertex shader to program GLES20.glAttachShader(it, vertexShader) // add the fragment shader to program GLES20.glAttachShader(it, fragmentShader) // creates OpenGL ES program executables GLES20.glLinkProgram(it) } } }
Java
public class Triangle() { ... private final int mProgram; public Triangle() { ... int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); // create empty OpenGL ES Program mProgram = GLES20.glCreateProgram(); // add the vertex shader to program GLES20.glAttachShader(mProgram, vertexShader); // add the fragment shader to program GLES20.glAttachShader(mProgram, fragmentShader); // creates OpenGL ES program executables GLES20.glLinkProgram(mProgram); } }
इस समय, आप अपना आकार बनाने वाले वास्तविक कॉल जोड़ने के लिए तैयार हैं. इनसे आकार बनाए जा रहे हैं OpenGL ES के लिए ज़रूरी है कि आप रेंडरिंग पाइपलाइन को यह बताने के लिए कई पैरामीटर तय करें कि आपको क्या चाहिए उसे कैसे बनाएं. ड्रॉइंग के विकल्प, आकार के हिसाब से अलग-अलग हो सकते हैं. इसलिए, अपने शेप क्लास का अपना ड्रॉइंग लॉजिक होता है.
आकृति बनाने के लिए draw()
तरीका बनाएं. यह कोड स्थान सेट करता है और
कलर वैल्यू को शेप के वर्टेक्स शेडर और फ़्रैगमेंट शेडर में बदल देता है और फिर ड्रॉइंग को एक्ज़ीक्यूट करता है
फ़ंक्शन का इस्तेमाल करना होगा.
Kotlin
private var positionHandle: Int = 0 private var mColorHandle: Int = 0 private val vertexCount: Int = triangleCoords.size / COORDS_PER_VERTEX private val vertexStride: Int = COORDS_PER_VERTEX * 4 // 4 bytes per vertex fun draw() { // Add program to OpenGL ES environment GLES20.glUseProgram(mProgram) // get handle to vertex shader's vPosition member positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition").also { // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(it) // Prepare the triangle coordinate data GLES20.glVertexAttribPointer( it, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer ) // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor").also { colorHandle -> // Set color for drawing the triangle GLES20.glUniform4fv(colorHandle, 1, color, 0) } // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount) // Disable vertex array GLES20.glDisableVertexAttribArray(it) } }
Java
private int positionHandle; private int colorHandle; private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex public void draw() { // Add program to OpenGL ES environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(positionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(colorHandle, 1, color, 0); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // Disable vertex array GLES20.glDisableVertexAttribArray(positionHandle); }
यह सभी कोड डाले जाने के बाद, इस ऑब्जेक्ट को बनाने के लिए
आपके रेंडरर के onDrawFrame()
तरीके में से draw()
तरीका:
Kotlin
override fun onDrawFrame(unused: GL10) { ... mTriangle.draw() }
Java
public void onDrawFrame(GL10 unused) { ... mTriangle.draw(); }
जब आप यह ऐप्लिकेशन चलाएं, तो वह कुछ ऐसा दिखना चाहिए:
कोड के इस उदाहरण में कुछ समस्याएं हैं. पहली बात, यह आपकी ऑडियंस को
दोस्त. इसके अलावा, जब आप स्क्रीन बदलते हैं, तो त्रिकोण थोड़ा कच्चा होता है और इसका आकार बदल जाता है
डिवाइस की स्क्रीन की दिशा. आकार टेढ़ा होने का कारण यह होता है कि ऑब्जेक्ट
उस स्क्रीन क्षेत्र के अनुपात के लिए शीर्षों को ठीक नहीं किया गया है जहां
GLSurfaceView
दिखाया गया है. प्रोजेक्शन और कैमरे की मदद से, इस समस्या को ठीक किया जा सकता है
अगले लेसन में देखें.
आखिर में, त्रिकोण स्थिर है, जो थोड़ा उबाऊ है. इस मोशन जोड़ें लेसन, आप यह आकार बनाते हैं OpenGL ES ग्राफ़िक्स पाइपलाइन के और मज़ेदार इस्तेमाल को घुमाना होगा.