1. GlSurfaceView是什么
GlSurfaceView
是Android
中的一個(gè)類,繼承自SurfaceView
,是用于顯示OpenGL ES
圖形渲染的一個(gè)View
。OpenGL ES
是一種跨平臺(tái)的圖形API
,用于渲染2D
和3D
圖形,也可以將相機(jī)的畫(huà)面顯示到GlSurfaceView
上,從而實(shí)現(xiàn)濾鏡的效果。GlSurfaceView
提供了一個(gè)可以在Android
應(yīng)用程序中繪制OpenGL ES
圖形的接口,允許開(kāi)發(fā)者將復(fù)雜的3D
圖形、動(dòng)畫(huà)和視覺(jué)效果嵌入到應(yīng)用程序中。GlSurfaceView
處理了OpenGL ES
渲染環(huán)境的創(chuàng)建、維護(hù)和更新,以及與其他Android
視圖和事件系統(tǒng)的交互。
2. android中怎使用GlSurfaceview
2.1 添加OpenGL ES版本支持
新建Android
項(xiàng)目,在AndroidManifest.xml
文件中,添加 OpenGL ES
版本支持。例如,要使用 OpenGL ES 2.0
,請(qǐng)?zhí)砑右韵麓a:
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
如果需要使用 OpenGL ES 3.0 則需要以下聲明:0x00030000
如果需要使用 OpenGL ES 3.2 則需要以下聲明:0x00030002
2.2 新建自定義的GlSurfaceView
新建一個(gè)MyGlSurfaceView
類,繼承自 GLSurfaceView
,并進(jìn)行初始化
import android.content.Context
import android.opengl.GLSurfaceView
import android.util.AttributeSet
class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs) {
init {
// 設(shè)置 OpenGL ES 版本
setEGLContextClientVersion(2)
// 設(shè)置渲染器
val renderer = MyGLRenderer()
setRenderer(renderer)
}
}
2.3 新建自定義的Renderer
創(chuàng)建一個(gè)自定義的渲染器MyRenderer
類,實(shí)現(xiàn) GLSurfaceView.Renderer
接口,并實(shí)現(xiàn)其中的方法
class MyGLRenderer : GLSurfaceView.Renderer {
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
//設(shè)置清除屏幕時(shí)使用的顏色
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
}
override fun onDrawFrame(gl: GL10?) {
// 清除屏幕
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
// 設(shè)置視口大小
GLES20.glViewport(0, 0, width, height)
}
}
2.4 使用MyGLSurfaceView
在 Activity
的xml
中使用MyGLSurfaceView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.heiko.myglsurfaceviewtest.MyGLSurfaceView
android:id="@+id/gl_surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
2.5 運(yùn)行看下效果
運(yùn)行后,可以看到一個(gè)使用 OpenGL ES
繪制的黑色屏幕
3. 在自定義的MyGLRenderer中繪制三角形
3.1 添加頂點(diǎn)著色器和片段著色器的代碼
在 MyGLRenderer
類中,添加頂點(diǎn)著色器和片段著色器的代碼。在這里,我們創(chuàng)建一個(gè)簡(jiǎn)單的頂點(diǎn)著色器和片段著色器,它們將頂點(diǎn)位置傳遞給渲染管線并使用固定顏色進(jìn)行渲染:
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;" +
"}"
3.2 添加編譯和鏈接著色器的方法
在 MyGLRenderer
類中,添加一個(gè)方法來(lái)編譯和鏈接著色器,然后返回著色器程序的 ID
private fun loadShaderProgram(vertexCode: String, fragmentCode: String): Int {
// 編譯頂點(diǎn)著色器
val vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER)
GLES20.glShaderSource(vertexShader, vertexCode)
GLES20.glCompileShader(vertexShader)
// 編譯片段著色器
val fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER)
GLES20.glShaderSource(fragmentShader, fragmentCode)
GLES20.glCompileShader(fragmentShader)
// 鏈接著色器程序
val program = GLES20.glCreateProgram()
GLES20.glAttachShader(program, vertexShader)
GLES20.glAttachShader(program, fragmentShader)
GLES20.glLinkProgram(program)
return program
}
3.3 加載并創(chuàng)建著色器程序
在 MyGLRenderer
類中,添加成員變量來(lái)存儲(chǔ)頂點(diǎn)數(shù)據(jù)、頂點(diǎn)緩沖區(qū)對(duì)象(VBO
)和著色器程序 ID
。
private val vertexData = floatArrayOf(
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
)
private var vertexBufferId = 0
private var shaderProgramId = 0
這里vertexData
為什么這么傳,是和openGL
的世界坐標(biāo)系相關(guān)的
可以看到vertexData
的第一個(gè)值0.0f
,第二個(gè)值0.5f
這個(gè)坐標(biāo)點(diǎn)位于Y軸偏上的位置,第三個(gè)值0.0f
我們不用管,這個(gè)是Z
軸,在2D
圖形中我們不需要Z
軸,所以這個(gè)統(tǒng)一傳0.0f
就好了。
同理,第四個(gè)值-0.5f
、第五個(gè)值-0.5f
位于X
軸坐標(biāo)的偏左側(cè),第六個(gè)值也是Z
軸,我們不用管。
第七個(gè)值是0.5f
,第八個(gè)值是-0.5f
位于X
軸坐標(biāo)的偏右側(cè),第九個(gè)值也是Z
軸,我們不用管。
具體如下圖所示
然后,在 onSurfaceCreated
方法中初始化這些值,然后加載并創(chuàng)建著色器程序
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
// 設(shè)置清除屏幕時(shí)使用的顏色
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
// 創(chuàng)建頂點(diǎn)緩沖區(qū)對(duì)象
val buffers = IntArray(1)
GLES20.glGenBuffers(1, buffers, 0)
vertexBufferId = buffers[0]
// 將頂點(diǎn)數(shù)據(jù)上傳到緩沖區(qū)對(duì)象
val vertexBuffer = ByteBuffer.allocateDirect(vertexData.size * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
vertexBuffer.put(vertexData)
vertexBuffer.position(0)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
GLES20.glBufferData(
GLES20.GL_ARRAY_BUFFER,
vertexData.size * 4,
vertexBuffer,
GLES20.GL_STATIC_DRAW
)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
// 加載并創(chuàng)建著色器程序
shaderProgramId = loadShaderProgram(vertexShaderCode, fragmentShaderCode);
}
3.4 繪制三角形
在 onDrawFrame
方法中,使用創(chuàng)建的著色器程序和頂點(diǎn)緩沖區(qū)對(duì)象來(lái)繪制三角形:
override fun onDrawFrame(gl: GL10?) {
// 清除屏幕
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
// 使用著色器程序
GLES20.glUseProgram(shaderProgramId)
// 綁定頂點(diǎn)緩沖區(qū)對(duì)象并啟用頂點(diǎn)屬性
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
val positionLocation = GLES20.glGetAttribLocation(shaderProgramId, "vPosition")
GLES20.glEnableVertexAttribArray(positionLocation)
GLES20.glVertexAttribPointer(positionLocation, 3, GLES20.GL_FLOAT, false, 0, 0)
// 設(shè)置片段著色器的顏色
val colorLocation = GLES20.glGetUniformLocation(shaderProgramId, "vColor")
GLES20.glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f)
// 繪制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3) // GL_TRIANGLES:三角形 GL_POINTS:點(diǎn)
// 禁用頂點(diǎn)屬性并解除頂點(diǎn)緩沖區(qū)對(duì)象的綁定
GLES20.glDisableVertexAttribArray(positionLocation)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
}
3.5 設(shè)置視口大小
在 onSurfaceChanged
方法中,還是一樣,設(shè)置視口大小:
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
// 設(shè)置視口大小
GLES20.glViewport(0, 0, width, height)
}
3.6 運(yùn)行看下效果
4. Android中GLES20.java的API說(shuō)明
上面我們已經(jīng)實(shí)現(xiàn)了一個(gè)三角形的繪制,但是對(duì)于GLES20
的API
還是不太了解,接下來(lái)再來(lái)看下常用的GLES20 API
4.1 Android中GLES20 API的一些主要功能說(shuō)明
- Shaders(著色器):GLES20使用可編程的著色器來(lái)渲染圖形。頂點(diǎn)著色器處理頂點(diǎn)數(shù)據(jù),片段著色器處理像素?cái)?shù)據(jù)。著色器需要用GLSL(OpenGL Shading Language)編寫。
- Buffers(緩沖區(qū)):GLES20使用緩沖區(qū)來(lái)存儲(chǔ)頂點(diǎn)數(shù)據(jù)和索引數(shù)據(jù)。頂點(diǎn)緩沖區(qū)對(duì)象(VBO)存儲(chǔ)頂點(diǎn)數(shù)據(jù),元素緩沖區(qū)對(duì)象(EBO)存儲(chǔ)索引數(shù)據(jù)。
- Textures(紋理):GLES20支持多種紋理類型,如2D紋理、立方體貼圖等。紋理用于給3D對(duì)象添加詳細(xì)的表面特征
- Framebuffers(幀緩沖區(qū)):GLES20使用幀緩沖區(qū)對(duì)象(FBO)來(lái)存儲(chǔ)渲染結(jié)果。你可以將渲染結(jié)果渲染到紋理中,然后將紋理應(yīng)用到其他對(duì)象上,實(shí)現(xiàn)高級(jí)渲染效果。
- Transformations(變換):GLES20支持多種變換操作,如平移、旋轉(zhuǎn)、縮放等。變換矩陣用于在頂點(diǎn)著色器中處理頂點(diǎn)數(shù)據(jù)。
- Lighting(光照):GLES20支持基本的光照計(jì)算,如環(huán)境光、漫反射光、鏡面反射光等。光照計(jì)算通常在頂點(diǎn)著色器或片段著色器中進(jìn)行。
- Blending(混合):GLES20支持顏色混合,用于實(shí)現(xiàn)透明度、半透明等效果?;旌喜僮骺梢愿鶕?jù)源顏色和目標(biāo)顏色按照指定的混合因子進(jìn)行計(jì)算。
- Culling(剔除):GLES20支持面剔除,可以剔除不可見(jiàn)的面,提高渲染性能。面剔除可以根據(jù)面的正面或反面進(jìn)行。
- Depth Testing(深度測(cè)試):GLES20支持深度測(cè)試,用于判斷像素的可見(jiàn)性。深度測(cè)試可以根據(jù)像素的深度值進(jìn)行比較,只渲染最前面的像素。
- Stencil Testing(模板測(cè)試):GLES20支持模板測(cè)試,用于實(shí)現(xiàn)遮罩、鏡子等效果。模板測(cè)試可以根據(jù)模板緩沖區(qū)的值對(duì)像素進(jìn)行掩蓋或者保留。
4.2 GLES20 API中一些主要方法的說(shuō)明
- glGenBuffers:生成緩沖區(qū)對(duì)象,如頂點(diǎn)緩沖區(qū)對(duì)象(VBO)和元素緩沖區(qū)對(duì)象(EBO)。
- glBindBuffer:綁定緩沖區(qū)對(duì)象,使其成為當(dāng)前活動(dòng)的緩沖區(qū)。
- glBufferData:將數(shù)據(jù)上傳到緩沖區(qū)對(duì)象。
- glVertexAttribPointer:定義頂點(diǎn)屬性數(shù)組,指定頂點(diǎn)數(shù)據(jù)在緩沖區(qū)中的布局。
- glEnableVertexAttribArray:?jiǎn)⒂庙旤c(diǎn)屬性數(shù)組。
- glDisableVertexAttribArray:禁用頂點(diǎn)屬性數(shù)組。
- glUseProgram:使用某個(gè)著色器程序進(jìn)行渲染。
- glGetUniformLocation:獲取著色器程序中uniform變量的位置。
- glUniformMatrix4fv:為uniform變量設(shè)置矩陣數(shù)據(jù)。
- glCreateShader:創(chuàng)建著色器對(duì)象。
- glShaderSource:為著色器對(duì)象設(shè)置源代碼。
- glCompileShader:編譯著色器對(duì)象。
- glGetShaderiv:獲取著色器對(duì)象的編譯狀態(tài)。
- glAttachShader:將著色器對(duì)象附加到著色器程序。
- glLinkProgram:鏈接著色器程序。
- glGetProgramiv:獲取著色器程序的鏈接狀態(tài)。
- glDeleteShader:刪除著色器對(duì)象。
- glGenTextures:生成紋理對(duì)象。
- glBindTexture:綁定紋理對(duì)象。
- glTexParameteri:設(shè)置紋理參數(shù),如過(guò)濾模式、環(huán)繞模式等。
- glTexImage2D:上傳紋理數(shù)據(jù)。
- glGenFramebuffers:生成幀緩沖區(qū)對(duì)象。
- glBindFramebuffer:綁定幀緩沖區(qū)對(duì)象。
- glFramebufferTexture2D:將紋理對(duì)象附加到幀緩沖區(qū)對(duì)象。
- glDrawArrays:繪制頂點(diǎn)數(shù)組,渲染圖形。
- glDrawElements:繪制索引數(shù)組,渲染圖形。
- glEnable:?jiǎn)⒂媚硞€(gè)OpenGL功能,如深度測(cè)試、剔除、混合等。
- glDisable:禁用某個(gè)OpenGL功能。
- glBlendFunc:設(shè)置混合函數(shù)。
- glCullFace:設(shè)置剔除面的模式。
- glClearColor:設(shè)置清除顏色緩沖區(qū)時(shí)使用的顏色。
- glClear:清除顏色緩沖區(qū)、深度緩沖區(qū)和/或模板緩沖區(qū)。
4.3 擴(kuò)展 : EGL是什么
OpenGL
是一個(gè)跨平臺(tái)的操作GPU
的API
,但OpenGL
需要本地視窗系統(tǒng)進(jìn)行交互,這就需要一個(gè)中間控制層。
而EGL
就是連接OpenGL ES
和本地窗口系統(tǒng)的接口,引入EGL
就是為了屏蔽不同平臺(tái)上的區(qū)別。EGL
需要做一些環(huán)境配置,而GLSurfaceView
就已經(jīng)幫我們配置好了,從而讓我們不了解EGL
也可以調(diào)用OpenGL
。
當(dāng)然,我們也可以不使用GLSurfaceView,而是自己通過(guò)EGL來(lái)和OpenGL進(jìn)行交互,但這樣就比較麻煩了。
5. 開(kāi)啟調(diào)試
GLSurfaceView.setDebugFlags()
方法可以激活 log
或者錯(cuò)誤檢測(cè),它們可以幫助調(diào)試 OpenGL ES
調(diào)用。具體使用時(shí),在 GLSurfaceView
的構(gòu)造函數(shù)中,調(diào)用 setRender()
之前調(diào)用GLSurfaceView.setDebugFlags()
就可以了。下面是個(gè)例子:
class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs) {
init {
// 設(shè)置 OpenGL ES 版本
setEGLContextClientVersion(2)
//打開(kāi)調(diào)試和日志
setDebugFlags(DEBUG_CHECK_GL_ERROR or DEBUG_LOG_GL_CALLS)
// 設(shè)置渲染器
val renderer = MyGLRenderer()
setRenderer(renderer)
}
}
6. 源碼下載
本文源碼下載 : Android使用GlSurfaceView和OpenGL繪制三角形 Demo文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-534418.html
7. 官方文檔
GLSurfaceView | Android Developers (google.cn)
SurfaceView 和 GLSurfaceView | Android 開(kāi)源項(xiàng)目 | Android Open Source Project (google.cn)
構(gòu)建 OpenGL ES 環(huán)境 | Android 開(kāi)發(fā)者 | Android Developers (google.cn)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-534418.html
到了這里,關(guān)于Android GlSurfaceView 入門教程 : 繪制一個(gè)三角形的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!