{"id":752,"date":"2018-11-12T00:28:09","date_gmt":"2018-11-11T15:28:09","guid":{"rendered":"http:\/\/www.charlezz.com\/?p=752"},"modified":"2018-12-31T14:51:26","modified_gmt":"2018-12-31T05:51:26","slug":"3-opengl-es%eb%a1%9c-%ec%82%bc%ea%b0%81%ed%98%95-%eb%a7%8c%eb%93%a4%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/charlezz.com\/?p=752","title":{"rendered":"[OpenGL] 3. \uc0bc\uac01\ud615 \ub9cc\ub4e4\uae30"},"content":{"rendered":"<h1>\uc0bc\uac01\ud615 \ub9cc\ub4e4\uae30<\/h1>\n<p>\uc9c0\ub09c <a href=\"http:\/\/www.charlezz.com\/?p=742\">1. Android OpenGL ES\uc758 \uac1c\uc694<\/a>\u00a0\ud3ec\uc2a4\ud305\uc5d0\uc11c \uac04\ub2e8\ud788 \uc0bc\uac01\ud615\uc744 \ub9cc\ub4e4\uc5c8\uace0, \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\uae30\uc704\ud574\uc11c Activity, GLSurfaceView, Renderer\uac00 \ud544\uc694\ud588\uc5c8\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc774\ubc88 \uc2dc\uac04\uc5d0\ub294 \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\ub294 \ud504\ub85c\uc138\uc2a4\uc5d0 \ub300\ud574\uc11c \uc54c\uc544\ubcf4\ub3c4\ub85d \ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\uc548\ub4dc\ub85c\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8 \uc124\uc815<\/h2>\n<p>\ub514\ubc14\uc774\uc2a4\uac00 OpenGL ES 2.0\uc744 \uc9c0\uc6d0\ud574\uc57c\ud558\uae30\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uba54\ub2c8\ud398\uc2a4\ud2b8\uc5d0 \uc120\uc5b8\ud574\uc90d\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true\">&lt;manifest&gt;\r\n&lt;uses-feature android:glEsVersion=\"0x00020000\" android:required=\"true\" \/&gt;\r\n...\r\n&lt;\/manifest&gt;<\/pre>\n<h2>MainActivity.kt<\/h2>\n<p>OpenGL ES 2.0 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud558\uae30 \uc704\ud574 GLSurfaceView.setEGLContextClientVersion(2) \ub97c \ud638\ucd9c\ud569\ub2c8\ub2e4.<\/p>\n<p>GLSurfaceView.setRenderer(Renderer)\ub97c \ud638\ucd9c\ud558\uc5ec, GLSurfaceView\uc5d0 \uadf8\ub9b4 \ub80c\ub354\ub7ec\ub97c \uc900\ube44\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true\">class MainActivity : AppCompatActivity() {\r\n\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        super.onCreate(savedInstanceState)\r\n        setContentView(R.layout.activity_main)\r\n        gl_surface_view.setEGLContextClientVersion(2)\r\n        gl_surface_view.setRenderer(MyRenderer())\r\n    }\r\n}<\/pre>\n<h2>GLSurfaceView.Renderer<\/h2>\n<p><a href=\"https:\/\/developer.android.com\/reference\/android\/opengl\/GLSurfaceView.Renderer\">Renderer<\/a>\ub294 \ubc94\uc6a9 \ub80c\ub354\ub7ec \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud504\ub808\uc784\uc744 \ub80c\ub354\ub9c1 \ud558\uae30 \uc704\ud574 OpenGL \ud568\uc218\ub97c \ud638\ucd9c\uc744 \uc218\ud589\ud569\ub2c8\ub2e4.<\/p>\n<p>GLSurfaceView\uc640\uc758 \uc5f0\uacb0\uc740 <a href=\"https:\/\/developer.android.com\/reference\/android\/opengl\/GLSurfaceView.html#setRenderer(android.opengl.GLSurfaceView.Renderer)\">GLSurfaceView.setRenderer(GLSurfaceView.Renderer)<\/a>\ub97c \ud1b5\ud574 \uac00\ub2a5\ud569\ub2c8\ub2e4.<\/p>\n<p><a href=\"https:\/\/github.com\/Charlezz\/OpenGLStudy\/blob\/master\/01_Triangle\/src\/main\/java\/com\/charlezz\/a01_triangle\/MyRenderer.kt\">1_Triangle<\/a> \uc608\uc81c\uc5d0\uc11c\ub294 Renderer\uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c MyRenderer\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5c8\uc5c8\uc2b5\ub2c8\ub2e4. \ub80c\ub354\ub7ec \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uac8c \ub418\uba74 \ud544\uc218\uc801\uc73c\ub85c \uad6c\ud604\ud574\uc57c\ud560 \uba54\uc18c\ub4dc 3\uac00\uc9c0\uac00 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<ul>\n<li>onSurfaceCreated(GL10 gl, EGLConfig config) : \uc11c\ube44\uc2a4\uac00 \uc0dd\uc131 \ub610\ub294 \uc7ac\uc0dd\uc131\ub420 \ub54c \ud638\ucd9c\ub429\ub2c8\ub2e4.\u00a0<\/li>\n<li>onSurfaceChanged(GL10 gl, int width, int height) : surface\uc758 \uc0ac\uc774\uc988\uac00 \ubcc0\uacbd\ub420 \uacbd\uc6b0 \ud638\ucd9c\ub429\ub2c8\ub2e4.<\/li>\n<li>onDrawFrame(GL10 gl) : \ud604\uc7ac \ud504\ub808\uc784\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \ud638\ucd9c\ub429\ub2c8\ub2e4.<\/li>\n<\/ul>\n<p>onSurfaceCreated\ub294 \ub80c\ub354\ub9c1\uc4f0\ub808\ub4dc\uac00 \uc2dc\uc791\ub418\uace0 EGL context\uac00 \uc720\uc2e4\ub420 \ub54c\ub9c8\ub2e4 \ud638\ucd9c \ub429\ub2c8\ub2e4. EGL Context\ub294 \uc77c\ubc18\uc801\uc73c\ub85c sleep\ubaa8\ub4dc\uac00 \ub41c \ud6c4 \ub514\ubc14\uc774\uc2a4\uac00 \uae68\uc5b4 \ub0a0 \ub54c \uc720\uc2e4\ub429\ub2c8\ub2e4.<\/p>\n<p>onSurfaceChanged\uc5d0\uc11c\ub294\u00a0\ubcf4\ud1b5 viewport\ub97c \uc9c0\uc815\ud569\ub2c8\ub2e4. \ub9cc\uc57d \uce74\uba54\ub77c(\uc0ac\uc9c4\ucc0d\ub294 \uce74\uba54\ub77c\uac00 \uc544\ub2d8) \uace0\uc815\ub418\uc5b4\uc788\ub2e4\uba74 \ud504\ub85c\uc81d\uc158 \ub9e4\ud2b8\ub9ad\uc2a4\ub97c \uc5ec\uae30\uc11c \uc124\uc815\ud560 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>onDrawFrame\uc5d0\uc11c\ub294 \ud654\uba74\uc5d0 \uadf8\ub9ac\uace0\uc790 \ud558\ub294 \ub0b4\uc6a9\uc5d0 \ub300\ud55c\uc791\uc5c5\uc744 \uc8fc\ub85c \ud569\ub2c8\ub2e4.<\/p>\n<p>\uc774\uc81c \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\uae30 \uc704\ud55c \uc18c\uc2a4\ub97c \ud30c\uc545\ud574\ubcf4\ub3c4\ub85d \ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h3><em><strong>MyRenderer.kt<\/strong><\/em><\/h3>\n<p>\ud654\uba74\uc744 \uadf8\ub9ac\ub294 \uc8fc\ub41c \uc5ed\ud560\uc744 \ud558\uac8c\ub420 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.<\/p>\n<p>GLSurfaceView.Renderer \uad6c\ud604\ud558\uc5ec \uc704\uc5d0\uc11c \uc124\uba85\ud55c 3\uac00\uc9c0 \uba54\uc18c\ub4dc\ub97c \uad6c\ud604\ud558\uac8c \ub420\uac83\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true\">import android.opengl.GLES20.*\r\nimport android.opengl.GLSurfaceView\r\nimport com.charlezz.a01_triangle.GlUtil.checkGlError\r\nimport com.charlezz.a01_triangle.GlUtil.createProgram\r\nimport java.nio.Buffer\r\nimport javax.microedition.khronos.egl.EGLConfig\r\nimport javax.microedition.khronos.opengles.GL10\r\n\r\nclass MyRenderer : GLSurfaceView.Renderer {\r\n\r\n    val vertexShader = \"\" +\r\n            \"attribute vec4 vPosition;\" +\r\n            \"void main() {\" +\r\n            \"  gl_Position = vPosition;\" +\r\n            \"}\"\r\n\r\n    val fragmentShader = \"\" +\r\n            \"precision mediump float;\" +\r\n            \"void main() {\" +\r\n            \"  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\" +\r\n            \"}\"\r\n\r\n    val triangleVertices: Buffer = GlUtil.createFloatBuffer(arrayOf(\r\n            0.0f, 0.5f,\r\n            -0.5f, -0.5f,\r\n            0.5f, -0.5f\r\n    ).toFloatArray())\r\n\r\n    var vPositionHandle: Int = 0\r\n    var program: Int = 0\r\n    var grey = 0f\r\n    var flag = false\r\n    override fun onDrawFrame(p0: GL10?) {\r\n        if( grey &gt; 1.0f || grey &lt; 0.0f){\r\n            flag = !flag\r\n        }\r\n        if(flag){\r\n            grey += 0.01f\r\n        }else{\r\n            grey -= 0.01f\r\n        }\r\n\r\n        glClearColor(grey,grey,grey, 1.0f)\r\n        checkGlError(\"glClearColor\")\r\n\r\n        glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT)\r\n        checkGlError(\"glClear\")\r\n\r\n        glUseProgram(program)\r\n        checkGlError(\"glUseProgram\")\r\n\r\n        glVertexAttribPointer(vPositionHandle,2,GL_FLOAT, false, 0, triangleVertices)\r\n        checkGlError(\"glVertexAttribPointer\")\r\n\r\n        glEnableVertexAttribArray(vPositionHandle)\r\n        checkGlError(\"glEnableVertexAttribArray\")\r\n\r\n        glDrawArrays(GL_TRIANGLES, 0, 3)\r\n        checkGlError(\"glDrawArrays\")\r\n    }\r\n\r\n    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {\r\n        program = createProgram(vertexShader, fragmentShader)\r\n\r\n        vPositionHandle = glGetAttribLocation(program, \"vPosition\")\r\n        checkGlError(\"glGetAttribLocation\")\r\n\r\n        glViewport(0, 0, width, height)\r\n        checkGlError(\"glViewport\")\r\n    }\r\n\r\n    override fun onSurfaceCreated(gl: GL10, p1: EGLConfig) {\r\n        \/\/nothing to do\r\n    }\r\n}<\/pre>\n<h3>VertexShader(\uc815\uc810 \uc250\uc774\ub354)<\/h3>\n<pre class=\"lang:java decode:true\">val vertexShader = \"\" +\r\n    \"attribute vec4 vPosition;\" +\r\n    \"void main() {\" +\r\n    \"  gl_Position = vPosition;\" +\r\n    \"}\"<\/pre>\n<p>\uc815\uc810\uc744 \uacc4\uc0b0\ud558\uae30 \uc704\ud55c \ubc84\ud14d\uc2a4 \uc250\uc774\ub354 \uc785\ub2c8\ub2e4.<\/p>\n<ul>\n<li>attribute :\u00a0 Vertex Shader\uc5d0\uc11c\ub9cc \uc0ac\uc6a9\uac00\ub2a5\ud55c \ud0c0\uc785. \uc815\uc810 \uc815\ubcf4\ub97c \uc804\ub2ec\ud558\uae30\uc704\ud574 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/li>\n<li>vec4 : homogeneous \uc88c\ud45c\uacc4\uc758 \uae30\ubcf8\uc801\uc778 \uc815\uc810 \uc704\uce58\ub97c \uac16\ub294 4\ucc28\uc6d0(x,y,z,w) float\ud615 \ubca1\ud130 \ub370\uc774\ud130\uc785\ub2c8\ub2e4. \uc9c0\uae08\uc740 \uc0bc\uac01\ud615\ub9cc \uadf8\ub9ac\ubbc0\ub85c \ud3c9\uba74\uc0c1\uc758 x\ucd95\uacfc y\ucd95\ub9cc \uc774\ud574\ud558\uba74\ub429\ub2c8\ub2e4.<\/li>\n<li>gl_Position : Vertex Shader\uc758 \ub0b4\uc7a5\ubcc0\uc218\uc911 \ub2e4\uc74c \uc2a4\ud14c\uc774\uc9c0\uc5d0 \uc815\uc810\uc758 \uc704\uce58 \uc815\ubcf4\ub97c \uc804\ub2ec\ud569\ub2c8\ub2e4.<\/li>\n<\/ul>\n<h3>FragmentShader(\ud504\ub808\uadf8\uba3c\ud2b8 \uc250\uc774\ub354)<\/h3>\n<pre class=\"lang:java decode:true\">val fragmentShader = \"\" +\r\n    \"precision mediump float;\" +\r\n    \"void main() {\" +\r\n    \"  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\" +\r\n    \"}\"<\/pre>\n<ul>\n<li>precision mediump : \uc815\ud655\ub3c4\ub97c \uc911\uac04\uc73c\ub85c \uc124\uc815\ud569\ub2c8\ub2e4. Highp\ub294 \ucd5c\uace0 \uc815\ud655\ub3c4, lowp\ub294 \ucd5c\ud558 \uc815\ud655\ub3c4\uc785\ub2c8\ub2e4. Highp\uc758 \uacbd\uc6b0 \ub514\ubc14\uc774\uc2a4\uac00 \uc9c0\uc6d0\uc744 \uc548\ud558\ub294 \uacbd\uc6b0\ub3c4 \uc788\uace0, \ud37c\ud3ec\uba3c\uc2a4\uce21\uba74\uc5d0\uc11c \ubb38\uc81c\uac00 \ub420\uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<li>gl_FragColor : \ucd5c\uc885 \ud504\ub798\uadf8\uba3c\ud2b8 \uc0c9\uc0c1\uc73c\ub85c \uace0\uc815\ub41c \ub0b4\uc7a5 \ubcc0\uc218 \uc785\ub2c8\ub2e4.<\/li>\n<\/ul>\n<h3>\uc0bc\uac01\ud615 \uc815\uc810 \ubc84\ud37c \ub9cc\ub4e4\uae30<\/h3>\n<p>\uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\uae30\uc704\ud574 \uaf2d\uc9c0\uc810 3\uac1c\ub97c \ucc0d\uc2b5\ub2c8\ub2e4.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.charlezz.com\/wordpress\/wp-content\/uploads\/2018\/11\/coordinates.png\" alt=\"\" width=\"786\" height=\"300\" class=\"aligncenter size-full wp-image-905\" srcset=\"https:\/\/charlezz.com\/wordpress\/wp-content\/uploads\/2018\/11\/coordinates.png 786w, https:\/\/charlezz.com\/wordpress\/wp-content\/uploads\/2018\/11\/coordinates-300x115.png 300w, https:\/\/charlezz.com\/wordpress\/wp-content\/uploads\/2018\/11\/coordinates-768x293.png 768w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/p>\n<pre class=\"lang:java decode:true\">val triangleVertices: Buffer = GlUtil.createFloatBuffer(arrayOf(\r\n        0.0f, 0.5f,\r\n        -0.5f, -0.5f,\r\n        0.5f, -0.5f\r\n).toFloatArray())<\/pre>\n<table border=\"1\" style=\"border-collapse: collapse; width: 100%;\">\n<tbody>\n<tr>\n<td style=\"width: 100%;\">\n<p>Note : \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c OpenGL\uc744 \uc704\ud55c \ubc84\ud37c \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \uc810\uc740 \uc790\ubc14\uc758 \ud799\uba54\ubaa8\ub9ac\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4\ub294 \uc810\uc785\ub2c8\ub2e4. \uadf8\ub7ec\ubbc0\ub85c NIO\ud328\ud0a4\uc9c0\uc5d0\uc11c ByteBuffer.allocate(int)\uac00 \uc544\ub2cc ByteBuffer.allocateDirect(int)\ub97c \uc774\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>onSurfaceCreated<\/h4>\n<p>Surface\uac00 \uc0dd\uc131 \ub610\ub294 \uc7ac\uc0dd\uc131 \ub420\ub54c \ud638\ucd9c\ub418\ub294\ub370 \ub2f9\uc7a5\uc740 \uc774\ubc88 \uc608\uc81c\uc5d0\uc11c\ub294 \ub531\ud788 \ud560 \uc791\uc5c5\uc774 \uc5c6\uc73c\ubbc0\ub85c \uc0dd\ub7b5\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h4>onSurfaceChanged<\/h4>\n<p>Surface\uc758 \uc0ac\uc774\uc988\uc5d0 \ubcc0\ud654\uac00 \uc0dd\uae38 \ub54c \ud638\ucd9c\ub429\ub2c8\ub2e4. \uc774\uacf3\uc5d0\uc11c \uba87\uba87 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true\">program = createProgram(vertexShader, fragmentShader)\r\n\/\/\uc250\uc774\ub354 \ud504\ub85c\uadf8\ub7a8\uc744 \ud558\ub098 \uc0dd\uc131\ud569\ub2c8\ub2e4.\r\n\/\/\ubc84\ud14d\uc2a4 \uc250\uc774\ub354\uc640 \ud504\ub808\uadf8\uba3c\ud2b8 \uc250\uc774\ub354 \ucf54\ub4dc\uac00 \ud544\uc694\ud569\ub2c8\ub2e4.\r\n\r\nvPositionHandle = glGetAttribLocation(program, \"vPosition\")\r\n\/\/\ubc84\ud14d\uc2a4 \uc250\uc774\ub354\uc5d0\uc11c \uc120\uc5b8\ud55c \ubcc0\uc218 vPosition\uc744 \uc5f0\uacb0\ud560 \ud578\ub4e4\ub7ec\ub97c \uac00\uc838\uc635\ub2c8\ub2e4.\r\n\r\nglViewport(0, 0, width, height)\r\n\/\/Surface\uc5d0 \uaf49\ucc44\uc6b4 \ud654\uba74\uc744 OpenGL\ub85c \uad6c\uc131\ud558\uae30 \uc704\ud574 \ubdf0\ud3ec\ud2b8\ub97c Surface \uc0ac\uc774\uc988\ub85c \uc124\uc815\ud569\ub2c8\ub2e4.<\/pre>\n<h4>onDrawFrame<\/h4>\n<pre class=\"lang:java decode:true\">glClearColor(grey,grey,grey, 1.0f) \r\n\/\/\uc774\uc804\uc5d0 \uc788\ub358 \ubc84\ud37c\ub97c \uc9c0\uc6b0\uace0 RGBA\uc0c9\uc0c1\uc73c\ub85c \ubc30\uacbd\uc0c9\uc744 \uc9c0\uc815\ud569\ub2c8\ub2e4.\r\nglClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT)\r\n\/\/GL_DEPTH_BUFFER_BIT\uc73c\ub85c \ub381\uc2a4\ubc84\ud37c\ub97c \uc9c0\uc6c1\ub2c8\ub2e4. \r\n\/\/OpenGL\uc740 3\ucc28\uc6d0 \uc138\uacc4\ub97c \ud45c\ud604\ud558\uc5ec \ub514\uc2a4\ud50c\ub808\uc774\uc758 2\ucc28\uc6d0 \ud3c9\uba74\uc5d0 \ud45c\ud604\ud558\ub294\ub370,\r\n\/\/\ud53d\uc140\ud558\ub098\ud558\ub098 \ub381\uc2a4\ubc84\ud37c\ub97c \ub530\ub85c \uad00\ub9ac\ud569\ub2c8\ub2e4.\r\n\/\/\ub3d9\uc77c \uc88c\ud45c\uc0c1\uc5d0 \uc788\ub294 \uacb9\uccd0\uc9c4 \ud53d\uc140 \ub610\ub294 \ubb3c\uccb4\ub97c \uadf8\ub9ac\uace0\uc790 \ud560\ub54c \uc774 \ub381\uc2a4\ubc84\ud37c\ub97c \uc774\uc6a9\ud558\ub294\ub370,\r\n\/\/\uc774\uc804 \ub381\uc2a4 \ubc84\ud37c\uac00 \uadf8\ub300\ub85c \ub0a8\uc544\uc788\uc73c\uba74 \ud654\uba74\uc744 \uadf8\ub9b4\ub54c \ubb38\uc81c\uac00 \ub418\ubbc0\ub85c \ucd08\uae30\ud654 \uc2dc\ud0b5\ub2c8\ub2e4.\r\n\/\/GL_COLOR_BUFFER_BIT\uc740 glClearColor\uc5d0\uc11c \uc9c0\uc815\ud55c \uc0c9\uc73c\ub85c \ubc30\uacbd\uc744 \uce60\ud569\ub2c8\ub2e4.\r\n\r\nglUseProgram(program)\r\n\/\/\ubbf8\ub9ac \ub9cc\ub4e4\uc5b4\ub450\uc5c8\ub358 \uc250\uc774\ub354 \ud504\ub85c\uadf8\ub798\uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4.\r\n\r\nglVertexAttribPointer(vPositionHandle,2,GL_FLOAT, false, 0, triangleVertices)\r\n\/\/ \ubc84\ud14d\uc2a4 \ud578\ub4e4\ub7ec\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 \uc815\uc810\uc758 \uc704\uce58\ub97c \uacc4\uc0b0\ud569\ub2c8\ub2e4.\r\n\/\/ \uc815\uc810 \uc250\uc774\ub354\uc5d0\uc11c vec4\ub97c \uc774\uc6a9\ud558\uc600\uae30 \ub54c\ubb38\uc5d0 \ud55c \uc815\uc810\uc758 \ud45c\ud604\uc5d0 \ub300\ud574 3\ucc28\uc6d0\ud45c\ud604(x,y,z,1)\uc744 \ud560\uc218 \uc788\uc73c\ub098,\r\n\/\/ \uc9c0\uae08\uc740 \ub2e8\uc21c\ud788 2\ucc28\uc6d0 \ud3c9\uba74\uc0c1\uc5d0 \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\ub294\uac83\uc774\ubbc0\ub85c x,y\uac12\ub9cc \uc4f0\ub3c4\ub85d \ud569\ub2c8\ub2e4.\r\n\/\/ \uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 float\uac12 2\uac1c\ub9cc \ub85c\ub4dc\ud558\uba74 \ub418\ubbc0\ub85c \ub450\ubc88\uc9f8 \uc778\uc790\uc5d0 2\ub97c \ub123\uc5c8\uc2b5\ub2c8\ub2e4.\r\n\/\/ 4\ubc88\uc9f8 \uc778\uc790\ub294 \uace0\uc815 \uc18c\uc218\uc810 \uac12\uc758 \ubc94\uc704\ub97c \uc815\uaddc\ud654\ud560\uc9c0\ub97c \uacb0\uc815\ud569\ub2c8\ub2e4.(-1\uc5d0\uc11c1 \ub610\ub294 0\uc5d0\uc11c1)\r\n\/\/ stride\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \uc815\uc810 \ubc30\uc5f4\uc758 \uc0ac\uc774\uc988\ub97c \ub123\uc2b5\ub2c8\ub2e4 (\uc815\uc810\uac1c\uc218 * 4)\r\n\/\/ stride\uac12\uc774 0\uc77c \uacbd\uc6b0 \ubc30\uc5f4\uc758 \uc0ac\uc774\uc988\ub85c \uac04\uc8fc\ud569\ub2c8\ub2e4.\r\n\r\nglEnableVertexAttribArray(vPositionHandle)\r\n\/\/ \uba54\ubaa8\ub9ac\uc5d0 \ub85c\ub4dc\ud55c \uc815\uc810\ub4e4\uc744 \ud65c\uc131\ud654 \ud569\ub2c8\ub2e4.\r\n\r\nglDrawArrays(GL_TRIANGLES, 0, 3)\r\n\/\/ \uccab\ubc88\uc9f8 \uc778\uc790\ub294 \uc8fc\uc5b4\uc9c4 \uc815\uc810\uc744 \uc5b4\ub5a4\uc2dd\uc73c\ub85c \uadf8\ub9b4\uac83\uc778\uc9c0\uc5d0 \ub300\ud55c\uac83\uc774\uace0,\r\n\/\/ \ub450\ubc88\uc9f8 \uc778\uc790\ub294 \uba54\ubaa8\ub9ac\uc5d0 \ub85c\ub4dc\ub41c \uc815\uc810 \ubc30\uc5f4\uc5d0\uc11c \uadf8\ub9ac\uae30 \uc2dc\uc791\ud560 \uc815\uc810\r\n\/\/ \ub9c8\uc9c0\ub9c9 \uc778\uc790\ub294 \uba87\uac1c\uc758 \uc815\uc810\uc744\uc774\uc6a9\ud558\uc5ec \ud654\uba74\uc744 \uadf8\ub9b4\uac83\uc778\uc9c0 \uc815\ud569\ub2c8\ub2e4.<\/pre>\n<p>&nbsp;<\/p>\n<h3><em><strong>GlUtil.kt<\/strong><\/em><\/h3>\n<p>OpenGL \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \uc790\uc8fc \uc4f0\uac8c\ub418\ub294 \ubcf4\uc77c\ub7ec\ud50c\ub808\uc774\ud2b8 \ucf54\ub4dc\ub97c \uc720\ud2f8\ub9ac\ud2f0 \ud074\ub798\uc2a4\ub85c \ub530\ub85c \ube7c\ub454 \uac83\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true \">import android.opengl.GLES20\r\nimport android.util.Log\r\nimport java.nio.ByteBuffer\r\nimport java.nio.ByteOrder\r\nimport java.nio.FloatBuffer\r\n\r\nobject GlUtil {\r\n    val TAG = \"GlUtil\"\r\n\r\n    private val SIZEOF_FLOAT = 4\r\n\r\n    \/**\r\n     * \ubc84\ud14d\uc2a4 \uc250\uc774\ub354\uc640 \ud504\ub808\uadf8\uba3c\ud2b8 \uc250\uc774\ub354\ub85c \uc0c8\ub85c\uc6b4 \ud504\ub85c\uadf8\ub7a8\uc744 \ub9cc\ub4ed\ub2c8\ub2e4\r\n     * @return \ud504\ub85c\uadf8\ub7a8\uc744 \uc544\uc774\ub514\ub97c \ub9ac\ud134\ud569\ub2c8\ub2e4. \ud504\ub85c\uadf8\ub7a8\uc744 \ub9cc\ub4dc\ub294\ub370 \uc2e4\ud328\ud560 \uacbd\uc6b0 0\uc744 \ub9ac\ud134\ud569\ub2c8\ub2e4.\r\n     *\/\r\n    fun createProgram(vertexSource: String, fragmentSource: String): Int {\r\n        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource)\r\n        \/\/ \ubc84\ud14d\uc2a4 \uc250\uc774\ub354\ub97c \ub85c\ub4dc \ud569\ub2c8\ub2e4.\r\n        if (vertexShader == 0) {\r\n            return 0\r\n        }\r\n        val pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource)\r\n        \/\/ \ud504\ub808\uadf8\uba3c\ud2b8 \uc250\uc774\ub354\ub97c \ub85c\ub4dc\ud569\ub2c8\ub2e4.\r\n        if (pixelShader == 0) {\r\n            return 0\r\n        }\r\n\r\n        var program = GLES20.glCreateProgram() \/\/ \ube48 \uc250\uc774\ub354 \ud504\ub85c\uadf8\ub7a8 \uc0dd\uc131\r\n        checkGlError(\"glCreateProgram\")\r\n        if (program == 0) {\r\n            Log.e(TAG, \"Could not create program\")\r\n        }\r\n        GLES20.glAttachShader(program, vertexShader)\/\/\ubc84\ud14d\uc2a4 \uc250\uc774\ub354\ub97c \ud504\ub85c\uadf8\ub7a8\uc5d0 \ubd99\uc785\ub2c8\ub2e4.\r\n        checkGlError(\"glAttachShader\")\r\n        GLES20.glAttachShader(program, pixelShader)\/\/\ud504\ub808\uadf8\uba3c\ud2b8 \uc250\uc774\ub354\ub97c \ud504\ub85c\uadf8\ub7a8\uc5d0 \ubd99\uc785\ub2c8\ub2e4.\r\n        checkGlError(\"glAttachShader\")\r\n        GLES20.glLinkProgram(program)\/\/\uc250\uc774\ub354\ub97c \ubd99\uc600\ub2e4\uba74 \uc774\uc81c \ud504\ub85c\uadf8\ub7a8\uc774 \uc2e4\ud589\uac00\ub2a5\ud55c \ud504\ub85c\uadf8\ub7a8\uc774 \ub41c\uac83\uc785\ub2c8\ub2e4.\r\n        val linkStatus = IntArray(1)\r\n        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0) \/\/\ud504\ub85c\uadf8\ub7a8\uc774 \uc798 \uc5f0\uacb0\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\r\n        if (linkStatus[0] != GLES20.GL_TRUE) { \/\/\ud504\ub85c\uadf8\ub7a8\uc774 \uc798 \uc5f0\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4\uba74,\r\n            Log.e(TAG, \"Could not link program: \")\r\n            Log.e(TAG, GLES20.glGetProgramInfoLog(program)) \/\/ \ub85c\uadf8\r\n            GLES20.glDeleteProgram(program) \/\/ \ud504\ub85c\uadf8\ub7a8 \uc0ad\uc81c\r\n            program = 0\r\n        }\r\n        return program\r\n    }\r\n\r\n    \/**\r\n     * \uc81c\uacf5\ub41c \uc250\uc774\ub354 \uc18c\uc2a4\ub97c \ucef4\ud30c\uc77c \ud569\ub2c8\ub2e4.\r\n     *\r\n     * @return \uc250\uc774\ub354 \uc544\uc774\ub514\ub97c \ub9ac\ud134\ud569\ub2c8\ub2e4. \uc2e4\ud328\uc2dc 0\uc744 \ub9ac\ud134\ud569\ub2c8\ub2e4.\r\n     *\/\r\n    fun loadShader(shaderType: Int, source: String): Int {\r\n        var shader = GLES20.glCreateShader(shaderType) \/\/ \uc250\uc774\ub354 \ud578\ub4e4\uc744 \ub9cc\ub4ed\ub2c8\ub2e4\r\n        checkGlError(\"glCreateShader type=$shaderType\")\r\n        GLES20.glShaderSource(shader, source) \/\/ \uc250\uc774\ub354\uc18c\uc2a4\ub97c \uc5f0\uacb0\ud569\ub2c8\ub2e4.\r\n        GLES20.glCompileShader(shader) \/\/ \ucef4\ud30c\uc77c \ud569\ub2c8\ub2e4.\r\n        val compiled = IntArray(1)\r\n        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0) \/\/ \ucef4\ud30c\uc77c\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4\r\n        if (compiled[0] == 0) {\r\n            Log.e(TAG, \"Could not compile shader $shaderType:\")\r\n            Log.e(TAG, \" \" + GLES20.glGetShaderInfoLog(shader)) \/\/\ub85c\uadf8\r\n            GLES20.glDeleteShader(shader) \/\/\uc250\uc774\ub354 \ud578\ub4e4 \uc0ad\uc81c\r\n            shader = 0\r\n        }\r\n        return shader\r\n    }\r\n\r\n    \/**\r\n     * GLError\uac00 \ubc1c\uc0dd\ud588\ub294\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.\r\n     *\/\r\n    fun checkGlError(op: String) {\r\n        val error = GLES20.glGetError()\r\n        if (error != GLES20.GL_NO_ERROR) {\r\n            val msg = op + \": glError 0x\" + Integer.toHexString(error)\r\n            Log.e(TAG, msg)\r\n            throw RuntimeException(msg)\r\n        }\r\n    }\r\n\r\n    \/**\r\n     * C++\ub808\ubca8\uc758 float \ubc30\uc5f4\uc744 \uc800\uc7a5\ud558\uae30 \uc704\ud55c \uba54\ubaa8\ub9ac\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4.\r\n     *\/\r\n    fun createFloatBuffer(coords: FloatArray): FloatBuffer {\r\n        \/\/ Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it.\r\n        val bb = ByteBuffer.allocateDirect(coords.size * SIZEOF_FLOAT) \/\/ \ubc18\ub4dc\uc2dc allocateDirect\ub85c \uc0dd\uc131\r\n        bb.order(ByteOrder.nativeOrder())\r\n        val fb = bb.asFloatBuffer()\r\n        fb.put(coords)\r\n        fb.position(0)\r\n        return fb\r\n    }\r\n}<\/pre>\n<p>\ubcf8 \ud504\ub85c\uc81d\ud2b8\ub294 <a href=\"https:\/\/github.com\/Charlezz\/OpenGLStudy\">github<\/a>\uc5d0\uc11c \ud655\uc778 \uac00\ub2a5\ud569\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc0bc\uac01\ud615 \ub9cc\ub4e4\uae30 \uc9c0\ub09c 1. Android OpenGL ES\uc758 \uac1c\uc694\u00a0\ud3ec\uc2a4\ud305\uc5d0\uc11c \uac04\ub2e8\ud788 \uc0bc\uac01\ud615\uc744 \ub9cc\ub4e4\uc5c8\uace0, \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\uae30\uc704\ud574\uc11c Activity, GLSurfaceView, Renderer\uac00 \ud544\uc694\ud588\uc5c8\uc2b5\ub2c8\ub2e4. \uc774\ubc88 \uc2dc\uac04\uc5d0\ub294 \uc0bc\uac01\ud615\uc744 \uadf8\ub9ac\ub294 \ud504\ub85c\uc138\uc2a4\uc5d0 \ub300\ud574\uc11c \uc54c\uc544\ubcf4\ub3c4\ub85d \ud558\uaca0\uc2b5\ub2c8\ub2e4. \uc548\ub4dc\ub85c\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8 \uc124\uc815 \ub514\ubc14\uc774\uc2a4\uac00 OpenGL ES 2.0\uc744 \uc9c0\uc6d0\ud574\uc57c\ud558\uae30\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uba54\ub2c8\ud398\uc2a4\ud2b8\uc5d0 \uc120\uc5b8\ud574\uc90d\ub2c8\ub2e4. &lt;manifest&gt; &lt;uses-feature android:glEsVersion=&#8221;0x00020000&#8243; android:required=&#8221;true&#8221; \/&gt; &#8230; &lt;\/manifest&gt; MainActivity.kt OpenGL ES 2.0 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud558\uae30 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[24],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/752"}],"collection":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=752"}],"version-history":[{"count":10,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/752\/revisions"}],"predecessor-version":[{"id":985,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/752\/revisions\/985"}],"wp:attachment":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=752"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=752"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=752"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}