最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android利用OpenGLES繪制天空盒實例教程

 更新時間:2018年08月03日 08:35:48   作者:滑板上的老砒霜  
這篇文章主要給大家介紹了關于Android利用OpenGLES繪制天空盒的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧

前言

天空盒這個效果最早是在騰訊的實景地圖里看到的,當時覺得很牛逼,但是沒有想過自己去實現(xiàn)以下。最近這段時間對opengl很有興趣,順便就搞了這個天空盒,話不多說,先上效果。

天空盒的原理就是在三維空間中放置一個正方體,然后將我們的相機放置在正方體內(nèi),當我們的視點轉動,相機跟著轉動。我們就可以看到相應的景色的變換了,天空盒本質上是一個立方體。

OpenGL

關于什么是OpenGL,什么是OpenGLES就不細說了,不了解的就自行百度吧,我們主要是關注代碼。整個項目采用了Kotlin + Ndk的形式進行的開發(fā)?,F(xiàn)在NDK的環(huán)境搭建比以前容易了,而且現(xiàn)在是使用CMakeList來構建C++代碼的,不熟悉的可以去查看一下。整個項目就兩個關鍵類,SkyBoxView和SkyBoxRender。下面分別來看一下。

第一步

SkyBoxView繼承了GLSurfaceView,為什么要繼承GLSurfaceView,因為在使用OpenGLES需要建立一個窗口和一個上下文,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方法里,設置了render為SkyBoxRender,真正的繪制是在這里進行的。在initSensity方法里設置了旋轉精度, horSensity和verSensity,水平和數(shù)值旋轉時的精度,就像你玩fps游戲設置的鼠標靈敏度一樣。在onTouchEvent則根據(jù)手指滑動的距離設置俯仰角pitch和偏移腳yaw,調(diào)用skyBoxRender進行相機的旋轉。另外如果你看github可能發(fā)現(xiàn)我注釋掉了很多代碼,那是用傳感器旋轉的嘗試,但是覺得麻煩,也沒繼續(xù)做,有興趣的讀者可以自己搞一下。

第二步

SkyboxRender的主要工作就是加載貼在正方體表面的6個圖片紋理,從文件讀取著色器語言,而真正創(chuàng)建opengles program和繪制是用C++代碼來寫的,所以主要看一下這里。

#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主要是用來產(chǎn)生opengl es的program的,如果對這個概念不太理解請參考C++編譯過程。

preparePos是將java層頂點位置數(shù)組傳入進來并寫入頂點著色器。

prepareTexture用來生成紋理。

draw用來進行繪制。

旋轉的時候就是通過改變cameraFront的單位向量的方向來做到的。

源碼下載

最后附上

github (本地下載

總結

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • Android listview定位到上次顯示的位置的實現(xiàn)方法

    Android listview定位到上次顯示的位置的實現(xiàn)方法

    這篇文章主要介紹了Android listview定位到上次顯示的位置的實現(xiàn)方法的相關資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • Android觸摸事件的應用詳解

    Android觸摸事件的應用詳解

    這篇文章主要為大家詳細介紹了Android觸摸事件的應用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • android Animation監(jiān)聽器AnimationListener的使用方法)

    android Animation監(jiān)聽器AnimationListener的使用方法)

    AnimaitonListener的使用方法主要是在Animation上設置一個監(jiān)聽器,下面通過一個實例說明它的使用方法
    2013-11-11
  • android studio集成unity導出工程的實現(xiàn)

    android studio集成unity導出工程的實現(xiàn)

    本文主要介紹了android studio集成unity導出工程的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • Android開發(fā)中常用的一些小技巧

    Android開發(fā)中常用的一些小技巧

    這篇文章主要介紹了Android開發(fā)中常用的一些小技巧,個人總結的一些常用方法和小技巧,需要的朋友可以參考下
    2015-02-02
  • Android?Gradle?插件自定義Plugin實現(xiàn)注意事項

    Android?Gradle?插件自定義Plugin實現(xiàn)注意事項

    這篇文章主要介紹了Android?Gradle?插件自定義Plugin實現(xiàn)注意事項,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-06-06
  • Android 攝像頭高斯模糊的示例代碼

    Android 攝像頭高斯模糊的示例代碼

    本篇文章主要介紹了Android 攝像頭高斯模糊的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Android中對RecyclerView Adapter封裝解析

    Android中對RecyclerView Adapter封裝解析

    本篇文章主要介紹了Android中對RecyclerView Adapter封裝解析。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Android實現(xiàn)打開各種文件的intent方法小結

    Android實現(xiàn)打開各種文件的intent方法小結

    這篇文章主要介紹了Android實現(xiàn)打開各種文件的intent方法,結合實例形式總結分析了Android針對HTML、圖片文件、pdf文件、文本文件、音頻文件、視頻文件等的intent打開方法,需要的朋友可以參考下
    2016-08-08
  • 利用Android模仿微信攝像圓環(huán)進度效果實例

    利用Android模仿微信攝像圓環(huán)進度效果實例

    圓環(huán)進度條,大家應該都見過,而這篇文章主要給大家介紹了關于利用Android模仿微信攝像圓環(huán)進度效果的相關資料,實現(xiàn)后的效果非常不錯,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-11-11

最新評論

阳高县| 丰台区| 璧山县| 密云县| 惠州市| 信宜市| 界首市| 绿春县| 南城县| 内江市| 新平| 新龙县| 呼和浩特市| 新平| 抚州市| 景洪市| 桃园县| 曲周县| 无锡市| 双鸭山市| 陆川县| 都江堰市| 东乡族自治县| 岳西县| 杭锦后旗| 望城县| 苍南县| 县级市| 茶陵县| 塔河县| 怀柔区| 防城港市| 九江县| 繁峙县| 陇川县| 金溪县| 敖汉旗| 彭水| 无棣县| 凤山市| 赤城县|