日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3D模型体素化(Voxelization)过程实现与分析(二)

發(fā)布時間:2024/1/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3D模型体素化(Voxelization)过程实现与分析(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 體素化方法
    • 原理展示
    • 實(shí)現(xiàn)過程
      • 使用Buffer
      • 著色器
      • 讀取體素坐標(biāo)
    • 實(shí)現(xiàn)代碼
      • 頂點(diǎn)著色器
      • 片元著色器
      • CPU讀取
      • 效果圖

體素化方法

體素化能夠?qū)δP瓦M(jìn)行簡化,得到均勻的網(wǎng)格,在求模型的測地線,求交等過程中有較好的應(yīng)用。個人理解,把體素化分為基于CPU的方法和基于GPU渲染的方法。輸入是三角面片,輸出體素化格子。

直接使用三角形求交的方法見
3D模型體素化(Voxelization)過程實(shí)現(xiàn)與分析(一)

使用三角形求交的方法,體素化計算量與三角形的數(shù)量,體素分辨率直接相關(guān)。當(dāng)三角形數(shù)量增多,分辨率增大時,計算量將急劇增加,計算十分緩慢。
本文介紹使用OpenGL快速計算體素化的方法,使用渲染管線中的片段著色器,將三角形與體素的求交轉(zhuǎn)化為采樣點(diǎn)與體素的求交。運(yùn)用片元的并行性,快速得到體素化結(jié)果。

原理展示

  • 計算模型的包圍盒
  • 在包圍盒外部設(shè)置相機(jī),最好是用正交相機(jī),進(jìn)行投影
  • 對于投影后的片元,計算每個片元的三維位置對應(yīng)的體素【注意,深度測試前所有的片元都不會被丟棄】
  • 實(shí)現(xiàn)過程

    使用Buffer

    這里需要從著色器回傳會體素占用信息,使用一個一維的數(shù)組來展開三維的體素位置。uniform對于著色器是只讀的。因此使用Buffer,著色器是可讀寫的,同時Buffer也允許使用較大的空間。

    著色器

  • 由于著色器是并行的,使用原子操作來實(shí)現(xiàn)同步。
  • 所有從頂點(diǎn)著色器到片元著色器中的變量都會被插值,因此可以直接從頂點(diǎn)著色器計算三維坐標(biāo),傳入到片元著色器。
  • 片元著色器根據(jù)坐標(biāo)位置,直接計算體素坐標(biāo),寫入到數(shù)組中。
  • 讀取體素坐標(biāo)

    在CPU中讀取Buffer數(shù)組,解析出體素化結(jié)果。

    實(shí)現(xiàn)代碼

    頂點(diǎn)著色器

    #version 430 core layout (location=0) in vec3 aPos; layout (location=1) in vec3 aNormal; layout (location=2) in vec2 aTexture;out vec3 FragPos; uniform mat4 model; uniform mat4 view; uniform mat4 projection;void main() { FragPos = aPos; // 局部坐標(biāo)gl_Position = projection *view *model *vec4(aPos,1.0); }

    片元著色器

    #version 430 coreout vec4 FragColor;in vec3 FragPos;layout (std430, binding =0) buffer CountBuffer{int cnts[]; };uniform vec3 box_min; uniform float interval; // 步長 uniform vec3 xyz; // 分辨率 uniform int pass;void main() {if(pass ==0){ int x = int((FragPos.x-box_min.x)/interval);int y = int((FragPos.y-box_min.y)/interval);int z = int((FragPos.z-box_min.z)/interval);int idx = int(y *(xyz.z *xyz.x) + z *xyz.x + x); atomicAdd(cnts[idx], 1);}FragColor = vec4(1, 0, 0, 1); }

    CPU讀取

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, cntBO); // 獲取buffer指針 int * ptr = (int *)(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY)); // cout << "error node: " << glGetError() << endl; vector<glm::vec3> pos; // 體素位置 vector<glm::ivec3> idx; // 體素索引 if (ptr != NULL) {for (int i = 0; i < cnts.size(); ++i){if (*(ptr + i)){int y1 = i / (x*z);int z1 = (i - y1 *x*z) / x;int x1 = (i - y1*x*z - z1*x);pos.push_back(box_min + glm::vec3(x1*width, y1*width, z1*width));idx.push_back(glm::ivec3(x1, y1, z1));}} } else {Error("read buffer data error"); } glUnmapBuffer(cntBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

    效果圖

    如有錯誤,歡迎指出~

    總結(jié)

    以上是生活随笔為你收集整理的3D模型体素化(Voxelization)过程实现与分析(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。