怎么在Android中利用OpenGLES繪制一個(gè)天空盒?相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
為西林等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及西林網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、西林網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
第一步
SkyBoxView繼承了GLSurfaceView,為什么要繼承GLSurfaceView,因?yàn)樵谑褂肙penGLES需要建立一個(gè)窗口和一個(gè)上下文,GLSurfaceView幫我們做了這些工作。下面是SkyBoxView的主要代碼:
class SkyBoxView(context: Context, attributeSet: AttributeSet?) : GLSurfaceView(context, attributeSet) { private lateinit var skyBoxRender: SkyBoxRender private var lastX=0F private var lastY=0F private var yaw=0f private var pitch=0f private var screenWidth=0 private var screenHeight=0 private var horSensity=0.03f private var verSensity=0.03f constructor(context: Context) : this(context, null) init { // initSensor() initSensity() initConfig() } private fun initSensity() { screenWidth=resources.displayMetrics.widthPixels screenHeight=resources.displayMetrics.heightPixels horSensity= 360.0f/screenWidth verSensity=180.0f/screenHeight } private fun rotate(pitch:Float,yaw:Float) { queueEvent { skyBoxRender.rotate(pitch,yaw) } } private fun initConfig() { setEGLContextClientVersion(3) skyBoxRender=SkyBoxRender(context) setRenderer(skyBoxRender) renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY } override fun onTouchEvent(event: MotionEvent?): Boolean { when(event?.action) { MotionEvent.ACTION_DOWN-> { lastX=event.x lastY=event.y return true } MotionEvent.ACTION_MOVE-> { val offsetX=event.x-lastX val offsetY=lastY-event.y yaw+=offsetX*horSensity pitch+=offsetY*verSensity lastX=event.x lastY=event.y skyBoxRender.rotate(pitch,yaw) } } return true } }
在initConfig方法里,設(shè)置了render為SkyBoxRender,真正的繪制是在這里進(jìn)行的。在initSensity方法里設(shè)置了旋轉(zhuǎn)精度, horSensity和verSensity,水平和數(shù)值旋轉(zhuǎn)時(shí)的精度,就像你玩fps游戲設(shè)置的鼠標(biāo)靈敏度一樣。在onTouchEvent則根據(jù)手指滑動(dòng)的距離設(shè)置俯仰角pitch和偏移腳yaw,調(diào)用skyBoxRender進(jìn)行相機(jī)的旋轉(zhuǎn)。另外如果你看github可能發(fā)現(xiàn)我注釋掉了很多代碼,那是用傳感器旋轉(zhuǎn)的嘗試,但是覺(jué)得麻煩,也沒(méi)繼續(xù)做,有興趣的讀者可以自己搞一下。
第二步
SkyboxRender的主要工作就是加載貼在正方體表面的6個(gè)圖片紋理,從文件讀取著色器語(yǔ)言,而真正創(chuàng)建opengles program和繪制是用C++代碼來(lái)寫(xiě)的,所以主要看一下這里。
#include <jni.h> #include <string> #include <GLUtils/GLUtils.h> #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/matrix_transform.hpp> extern "C" { JNIEXPORT jint JNICALL Java_com_skateboard_skybox_SkyBoxRender_genProgram(JNIEnv *env, jobject thiz, jstring vertexPath, jstring fragmentPath) { //load program const char *cVertexPath = env->GetStringUTFChars(vertexPath, nullptr); const char *cFragmentPath = env->GetStringUTFChars(fragmentPath, nullptr); int program = glutils::loadProgram(cVertexPath, cFragmentPath); return program; } JNIEXPORT jint JNICALL Java_com_skateboard_skybox_SkyBoxRender_preparePos(JNIEnv *env, jobject thiz, jfloatArray pos) { //gen vao vbo unsigned int VAO, VBO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); int posSize = env->GetArrayLength(pos); float* p=env->GetFloatArrayElements(pos, nullptr); glBufferData(GL_ARRAY_BUFFER, posSize* sizeof(float), p, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); glBindVertexArray(0); return VAO; } JNIEXPORT jint JNICALL Java_com_skateboard_skybox_SkyBoxRender_prepareTexture(JNIEnv *env, jobject thiz) { //gen texture unsigned int TEXTURE; glGenTextures(1, &TEXTURE); glBindTexture(GL_TEXTURE_CUBE_MAP, TEXTURE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); return 1; } glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); JNIEXPORT void JNICALL Java_com_skateboard_skybox_SkyBoxRender_draw(JNIEnv *env, jobject thiz, jint program, jint VAO, jint texture,jfloat width,jfloat height) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0, 1.0, 0.0, 1.0); glUseProgram(program); glEnable(GL_DEPTH_TEST); glm::mat4 viewMatrix = glm::mat4(1.0f); glm::mat4 projectionMatrix = glm::mat4(1.0f); glm::vec3 v = glm::vec3(cameraFront.x - cameraPos.x, cameraFront.y - cameraPos.y, cameraFront.z - cameraPos.z); viewMatrix = glm::lookAt(cameraPos, v, glm::vec3(0.0f, 1.0f, 0.0f)); projectionMatrix = glm::perspective(glm::radians(45.0f), width / height, 0.1f, 100.0f); int viewMatrixLocation = glGetUniformLocation(program, "view"); int projectMatrixLocation = glGetUniformLocation(program, "projection"); glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); glUniformMatrix4fv(projectMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]); glBindVertexArray(VAO); glBindTexture(GL_TEXTURE_CUBE_MAP, texture); glDrawArrays(GL_TRIANGLES, 0, 36); }
JNIEXPORT void JNICALL Java_com_skateboard_skybox_SkyBoxRender_rotate(JNIEnv *env, jobject thiz,jfloat pitch,jfloat yaw) { if(pitch>89) { pitch=89.0; } if(pitch<-89) { pitch=-89.0; } cameraFront.x=glm::cos(glm::radians(pitch))*glm::cos(glm::radians(yaw)); cameraFront.y=glm::sin(glm::radians(pitch)); cameraFront.z=glm::cos(glm::radians(pitch))*glm::sin(glm::radians(yaw)); cameraFront=glm::normalize(cameraFront); } }
genProgram主要是用來(lái)產(chǎn)生opengl es的program的,如果對(duì)這個(gè)概念不太理解請(qǐng)參考C++編譯過(guò)程。
preparePos是將java層頂點(diǎn)位置數(shù)組傳入進(jìn)來(lái)并寫(xiě)入頂點(diǎn)著色器。
prepareTexture用來(lái)生成紋理。
draw用來(lái)進(jìn)行繪制。
旋轉(zhuǎn)的時(shí)候就是通過(guò)改變cameraFront的單位向量的方向來(lái)做到的。
看完上述內(nèi)容,你們掌握怎么在Android中利用OpenGLES繪制一個(gè)天空盒的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
分享題目:怎么在Android中利用OpenGLES繪制一個(gè)天空盒
網(wǎng)站路徑:http://muchs.cn/article28/pioscp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、品牌網(wǎng)站制作、網(wǎng)站收錄、網(wǎng)站制作、網(wǎng)站內(nèi)鏈、
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)