OpenGL ES 3.0のSSAO



ある日、効果のある次のデモを芋お、疑問が生じたしたモバむルデバむスでSSAOを䜜成しお、芋た目が遅くならないようにするこずは可胜ですか

Galaxy Note 3 n9000mali T62がデバむスずしお採甚されたした。目暙はFPSが30以䞊であり、品質は䞊の図のようになりたす。



この効果に぀いおは詳しく説明したせんが、読者は他の゜ヌス wikiたたはsteps3d から効果に぀いお孊ぶこずができるず想定されおいたす 。 この蚘事ではモバむルプラットフォヌムぞの適応に重点を眮いおいたすが、「Varieties of SSAO」セクションで簡単なレビュヌが行われたす。



SSAOはパフォヌマンスの面で非垞に倧食いの効果であるず同時に、平均的なナヌザヌにはたったく芋えないので、モバむルデバむスではただ芋おいたせん。 さらに、それを加速するには、 MRTサポヌトが必芁です。これは、OpenGL ESバヌゞョン3.0でのみ登堎したした。



SSAOの皮類



アルゎリズムの䞻なアむデアは、空間内のサヌフェスポむントのシェヌディングを決定するこずです。 特定の半埄内のこのポむントのシャドりむングの皋床を決定するために、オブゞェクトの存圚がチェックされ、オブゞェクトの近くにあるほど、ポむントがシェヌディングされたす。



もちろん、3次元空間のサヌフェス䞊の各ポむントのシェヌディングを蚈算するこずは䞍可胜であるため、アルゎリズムのすべおの䜜業は画像空間で実行されたすそのため、 画面空間アンビ゚ントオクルヌゞョンず呌ばれたす 。 ぀たり、画面䞊のピクセルは衚面䞊の点ずしお機胜したす実際、必ずしも画面䞊ではなく、SSAOバッファヌのサむズは画面サむズよりも小さいこずが倚いため、フレヌムたたはフレヌム内のピクセルを蚀う方がより正確です。 たた、近隣の空間のすべおのポむントの倀を凊理するこずは䞍可胜です。したがっお、通垞は、問題のポむントから特定の半埄内のランダムなポむントの小さな遞択に制限されたす。



最も単玔な実装では、深床バッファはシェヌディングを蚈算するのに十分です-そのため、問題のピクセルのz座暙は、この差に基づいおサンプルのピクセルのz座暙ず比范され、シェヌディングが考慮されたす。



ただし、䞊の図を芋るず、ポむントの䞋のサヌフェス自䜓もシェヌディングに独自の「圹に立たない」貢献をしおいるこずがわかりたす。 その結果、画像はグレヌトヌンで取埗されたす。぀たり、シェヌディングがないはずです。 次のようになりたす。





これを回避するには、深床に関する情報に加えお、この時点での法線に関する情報も必芁です。 これを行うには、シヌンのレンダリング䞭に、色に加えお、別の通垞のバッファヌにも曞き蟌たれたす。 それらを指定するず、サンプルからポむントの䜍眮を倉曎しお、「有甚な」貢献をするこずができたす。 これは、問題のポむントの法線ずサンプルのポむントの法線ずの間の角床に基づいお行われたす。角床角床が90°より倧きい堎合-サンプルの法線が反転し、それに基づいおポむントが再蚈算されたす アルゎリズムのこのような倉曎は、必芁な堎所にのみシェヌディングを提䟛したすが、深刻な欠点がありたす-サンプルからの各ポむントに぀いお、深床バッファヌからの読み取りに加えお、法線のテクスチャからの远加読み取りが衚瀺されたす。 たた、SSAOのボトルネックはさたざたなバッファヌからの倧量の読み取りであり、これらの読み取りはランダムな順序で行われたす。これはキャッシュを匷制終了したす。 特にモバむルデバむスで。



別の修正は、球䜓を近傍ずしお䜿甚するのではなく、サンプルからの点が䜍眮する半球を䜿甚するこずを意味したす。 この堎合、怜蚎䞭のポむントの法線に沿っおこの球を方向付ける必芁がありたす。



この堎合、サンプルから各ポむントの法線を読み取る必芁はありたせん。すべおのポむントが既にあるはずなので、問題のポむントの法線を取埗するだけで十分です。



私の意芋では、これが最良の修正であり、適甚可胜です。



実装



たず、法線、深床、色を保存するためのバッファが必芁です。 OpenGL ES 3.0のテクノロゞヌ-耇数のレンダヌタヌゲットを䜿甚し、耇数のバッファヌを䜜成しお、同時に曞き蟌みたす。 コヌドでは、次のようになりたすテクスチャ䜜成は別の関数ずしお䜜成したした

// ,        (  ),     GLenum buffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; GLuint fbo; GLuint colorBuff; GLuint normBuff; GLuint depthBuff; //     void createTexture(GLuint &id, int inFormat, int w, int h, int format, int type, int filter, int wrap, void* pix=NULL) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, inFormat, w, h, 0, format, type, pix); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); } ... glGenFramebuffers(1, &fbo); //   glBindFramebuffer(GL_FRAMEBUFFER, fbo); // width  height -   createTexture(colorBuff, GL_RGB8, width, height, GL_RGB, GL_UNSIGNED_BYTE, GL_NEAREST, GL_MIRRORED_REPEAT); createTexture(normBuff, GL_RGB8, width, height, GL_RGB, GL_UNSIGNED_BYTE, GL_NEAREST, GL_MIRRORED_REPEAT); createTexture(depthBuff, GL_DEPTH_COMPONENT24, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_NEAREST, GL_MIRRORED_REPEAT); //    ,        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuff, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normBuff, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthBuff, 0); int err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err != GL_FRAMEBUFFER_COMPLETE) LOGE("Main framebuffer error: %i", err); glDrawBuffers(2, buffers);
      
      





さらに同様の方法ですが、1぀のテクスチャを䜿甚しお、SSAOの䞋にバッファを䜜成する必芁がありたす。

SSAOの䞋のバッファヌ
 glGenFramebuffers(1, &ssaoFbo1); glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo1); //     ,     ,    GL_R8 createTexture(ssaoBuff1, GL_R8, width/ssaoScaleW, height/ssaoScaleH, GL_RED, GL_UNSIGNED_BYTE, GL_LINEAR, GL_MIRRORED_REPEAT); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuff1, 0); // glDrawBuffers   ,       
      
      







このバッファは小さいかもしれたせんが、今のずころは画面解像床ず同じにしたしょう私の堎合は1920x1080。



z-bufferに぀いおも蚀う必芁がありたす。 SSAOで䜿甚するには、最初に線圢にする必芁がありたす。そうしないず、䞭間およびバックグラりンドで粟床が倧幅に倱われたす。 通垞、このために、深床倀は、通垞の法線ず䞀緒に、別のバッファに曞き蟌たれたす。 ただし、远加のバッファヌはパフォヌマンスの点でうたく機胜しないため、倀を線圢化しお別のバッファヌに曞き蟌むのではなく、珟圚の暙準深床バッファヌgl_FragDepthに盎接曞き蟌みたす。 これにより、前景にアヌティファクト非垞に近く、ほが正面のクリッピングプレヌンの近くが発生する可胜性がありたすが、基本的にこのようなバッファヌは非垞に正垞に動䜜したす。



シヌンは通垞どおりレンダリングされたすが、唯䞀の違いは色のほかに法線も蚘録し、深床バッファをわずかに倉曎するこずです。 シヌンレンダリング甚の頂点シェヌダヌ

 #version 300 es uniform mat4 matrixProj; uniform mat4 matrixView; uniform vec3 lightPos; layout(location = 0) in vec3 vPos; //   layout(location = 1) in vec3 nPos; //  layout(location = 2) in vec3 tPos; //     layout(location = 3) in vec2 tCoord; //   out vec3 light; out vec3 gNorm; out float zPos; out vec2 texCoord; void main() { vec4 p = matrixProj*matrixView*vec4(vPos, 1.0); gl_Position = p; texCoord = tCoord; //      ,           vec3 bitangent = cross(tPos, nPos); mat3 tbn = mat3(tPos, bitangent, nPos); light = normalize(lightPos-vPos)*tbn; zPos = pz; //  z-  -      vec4 n = (matrixView*vec4(nPos, 0.0)); //      gNorm = normalize(n.xyz); }
      
      





フラグメントシェヌダヌ

 #version 300 es precision highp float; //      24- ,     ,     24 ,       uniform sampler2D texDiff; //   uniform sampler2D texNorm; //       layout(location = 0) out vec3 colorBuff; //    layout(location = 1) out vec3 normBuff; //   in vec3 light; in vec3 gNorm; in float zPos; in vec2 texCoord; const vec3 ambientColor = vec3(0.3); const float zFar = 40.0; //    void main() { vec3 n = normalize(texture(texNorm, texCoord).xyz*2.0-1.0); vec3 l = normalize(light); vec3 c = texture(texDiff, texCoord).rgb; float a = clamp(dot(n, l), 0.0, 1.0); colorBuff = c*(a+ambientColor); //   normBuff = normalize(gNorm)*0.5+0.5; //   gl_FragDepth = zPos/zFar; //       }
      
      







たた、半球内のランダムポむントの配列実際の遞択も必芁です。 シェヌディングを矎しくするためにいわば、より物理的に-半球内のポむントの密床は、䞭倮では高く、境界では䜎くする必芁がありたす。 ぀たり、正芏分垃の法則を持぀こずです。

 for (int i=0; i<samples; i++) { rndTable[i] = vec3(random(-1, 1), random(-1, 1), random(-1, -0)); //    ( ) rndTable[i].normalize(); //   rndTable[i] *= (i+1.0f)/samples; //  ( ) }
      
      













もちろん、サンプル内のポむントの数はそれほど倚くありたせん。 ここたでで10に等しくしたす。



ただし、このような擬䌌乱数倀のサンプルでは十分ではありたせん。これらの倀は同じフラグメント内でのみランダムであり、次のフラグメントはわずかなバむアスはありたすが同じポむントを取りたす。 この欠点を解消するために、圌らは通垞、疑䌌ランダム倀を持぀小さなテクスチャヌ玄4x4ピクセルを䜿甚したす。 これで、各フラグメントで、このテクスチャから倀を取埗し、それに基づいお半球ポむントの回転行列をコンパむルできたす。 そしお同時に、それらを法線に察しお回転させたす。これはすでに法線のテクスチャから読み取られたす。 したがっお、結果のマトリックスでポむントを乗算し、それらを同時に法線に察しお方向付け、疑䌌ランダムベクトルによっお回転させたす。 このような行列の構築は、グラムシュミット過皋ず呌ばれたす 。



シェヌダヌでは、次のようになりたす。

 vec3 normal = texture(normBuff, texCoord).xyz*2.0-1.0; vec3 rvec = texture(randMap, texCoord*scr).xyz*2.0-1.0; vec3 tangent = normalize(rvec-normal*dot(rvec, normal)); vec3 bitangent = cross(tangent, normal); mat3 rotate = mat3(tangent, bitangent, normal);
      
      







たた、空間内のポむントの座暙を埩元する必芁がありたす。 これを行うには、画像空間内のポむントの座暙に透芖倉換の逆行列を掛けるか、たたはより簡単に行うこずができたす珟圚のピクセルを介しおカメラから向けられたベクトル光線にこのピクセルのz座暙倀を掛けたす。 Z座暙は深床バッファヌに栌玍され、カメラからのビヌムは芖野角に基づいお構築されたす。芖野角は、透芖行列投圱行列の構築に䜿甚されたす-これはfovです。 ナニフォヌムを保存するこずにし、この倀を定数ずしお頂点シェヌダヌに入力したした。

 #version 300 es const fov = 0.57735; layout(location = 0) in vec2 vPos; layout(location = 1) in vec2 tCoord; uniform float aspect; out vec2 texCoord; out vec3 viewRay; void main() { gl_Position = vec4(vPos, 0.0, 1.0); texCoord = tCoord; viewRay = vec3(-vPos.x*aspect*fov, -vPos.y*fov, 1.0); //   ,      }
      
      





ピクセルシェヌダヌでは、レむに基づくポむントの䜍眮が次のように埩元されたす。

 float depth = texture(depthBuff, texCoord).x; //    ,   depth *= zFar; //  z- vec3 pos = viewRay*depth; //     
      
      





回転行列ずポむントの䜍眮を受け取ったら、サンプルからシェヌディング倀を取埗するこずができたす。

 float acc = 0.0; for (int i=0; i<samples; i++) { vec3 samplePos = rotate*rndTable[i]; //  samplePos = samplePos*radius+pos; //        //          ,            vec4 shift = proj*vec4(samplePos, 1.0); shift.xy /= shift.w; shift.xy = shift.xy*0.5+0.5; //   z- float sampleDepth = texture(depthBuff, shift.xy).x*zFar; //       -      .     ,       ,   smoothstep,   -   float distanceCheck = smoothstep(0.0, 1.0, radius/abs(pos.z-sampleDepth)); //       -     .  - ,    step acc += step(sampleDepth, samplePos.z)*distanceCheck; }
      
      





結果はがやける可胜性があるため、ガりスがかし甚に別のバッファを䜜成したす。 サンプルの数を少なくし、最終的にはテクスチャの最䞊郚にある単なる圱にするため、アヌティファクトはあたり目立たないはずです。 ここで、キャッシュはすでに私たちの偎にありたす。SSAOでのランダムな読み取りの堎合、キャッシュミスが垞に発生する堎合、テクスチャからのサンプルは適切にキャッシュされるはずです。

垂盎がかしシェヌダヌ
 #version 300 es precision mediump float; uniform sampler2D ssaoBuff; layout(location = 0) out float outColor; in vec2 texCoord; const float blurSize = 2.5/1920.0; void main() { float sum = 0.0; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y - 2.0*blurSize)).r * 0.0625; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y - blurSize)).r * 0.25; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y )).r * 0.375; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y + blurSize)).r * 0.25; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y + 2.0*blurSize)).r * 0.0625; outColor = sum; }
      
      





氎平がかしシェヌダヌ
 #version 300 es precision mediump float; uniform sampler2D ssaoBuff; layout(location = 0) out float outColor; in vec2 texCoord; const float blurSize = 2.5/1080.0; void main() { float sum = 0.0; sum += texture(ssaoBuff, vec2(texCoord.x - 2.0*blurSize, texCoord.y)).r * 0.0625; sum += texture(ssaoBuff, vec2(texCoord.x - blurSize, texCoord.y)).r * 0.25; sum += texture(ssaoBuff, vec2(texCoord.x, texCoord.y)).r * 0.375; sum += texture(ssaoBuff, vec2(texCoord.x + blurSize, texCoord.y)).r * 0.25; sum += texture(ssaoBuff, vec2(texCoord.x + 2.0*blurSize, texCoord.y)).r * 0.0625; outColor = sum; }
      
      







結果を芋るこずができたす



巊䞊隅の数字は、1秒あたりのフレヌム数を瀺しおいたす。 あたりない。 さらに、衚面の瞞暡様にも泚意しおください。 問題は、深床バッファを衚す際に、衚面が完党に滑らかではないこずです。 ここではすべおが完党に分離されおおり、衚面は梯子のように芋えるため、サンプルのポむントの䞀郚はこれらの「ステップ」内にあるように芋えたす。



したがっお、サンプルを䜜成するずきは、れロのZ座暙からではなく、たずえば0.1などの小さな倀から開始するこずをお勧めしたす。 この堎合、半球は䞋から切り取られたようになりたす。



そしお、サンプルからのポむントは「ステップ」に分類されたせん。 写真は良くなりたす



しかし、FPSはただ高くありたせん。



最適化



明癜で最も䞀般的な解決策は、サンプル内のポむント数を枛らし、SSAOバッファヌのサむズを小さくするこずです。 バッファヌサむズを半分にするず、FPSが玄150増加したす。 ただし、バッファヌのサむズを倉曎するず、オブゞェクトの境界でアヌティファクトが発生するため、倧幅に削枛するこずはありたせん。



アルゎリズムの結果を芋おください。画像のほずんどが癜で、シェヌディングがたったくないこずがわかりたす。 ただし、アルゎリズムはピクセルごずに満たされたす。 䞍芁な断片をカットできるようなマスクを䜜成するずよいでしょう。

このマスクは、より小さいバッファヌのSSAOを倧たかに蚈算するこずで取埗できたす。 ぀たり、別のバッファヌを䜜成したす。たずえば、SSAOのバッファヌの16倍の幅ず高さです。 サンプルの数を5に枛らしお、ランダムではなく、半球の䞭心から同じ距離に配眮したす。

 for (int i=0; i<samplesLow; i++) { float angle = DEG2RAD*360.0f*i/samplesLow; rndTableLow[i] = vec3(sinf(angle), cosf(angle), -0.1); }
      
      





シャドりがスムヌズに移行しないマスクが必芁なので、結果を非垞に察照的にしたす-ピクセルは黒たたは癜です

 outColor = step(254.0/255.0, 1.0-(acc/float(samples)));
      
      





ブラヌシェヌダヌも簡玠化され、2぀のフラグメントシェヌダヌではなく、正方圢の角に4぀のサンプルがあるシェヌダヌになりたす。

 #version 300 es precision mediump float; uniform sampler2D ssaoLowBuff; uniform float aspect; layout(location = 0) out float outColor; in vec2 texCoord; const float blurSize = 0.01; void main() { float sum = 0.0; sum += texture(ssaoLowBuff, vec2(texCoord.x - blurSize, texCoord.y - blurSize*aspect)).r; sum += texture(ssaoLowBuff, vec2(texCoord.x - blurSize, texCoord.y + blurSize*aspect)).r; sum += texture(ssaoLowBuff, vec2(texCoord.x, texCoord.y )).r; sum += texture(ssaoLowBuff, vec2(texCoord.x + blurSize, texCoord.y - blurSize*aspect)).r; sum += texture(ssaoLowBuff, vec2(texCoord.x + blurSize, texCoord.y + blurSize*aspect)).r; outColor = step(254.0/255.0, sum/5.0); }
      
      





このマスクを取埗したす。



それを䜿甚しお、SSAOを蚈算したすバッファヌサむズを1.5倍に枛らし、サンプル数を8に枛らしたした。



その結果、FPSは品質を芖芚的に損なうこずなく3倍になりたした。 この方法には欠点がありたす-シヌン内に倚くの角床たたは他のシェヌディング堎所がある堎合、マスクはほが完党に黒くなりたす。これは、そのような最適化の有効性が倧幅に䜎䞋するこずを意味したす。

完党なSSAOフラグメントシェヌダヌコヌド

 #version 300 es precision highp float; //  24-   const int samples = 8; //   const float radius = 0.5; //   const float power = 2.0; //   const float zFar = 40.0; //    uniform sampler2D normBuff; //   uniform sampler2D depthBuff; //   uniform sampler2D randMap; //      uniform sampler2D ssaoMask; //  SSAO -  uniform vec2 scr; //    randMap,     SSAO uniform vec3 rndTable[samples]; //  uniform mat4 proj; //   layout(location = 0) out float outColor; //   in vec2 texCoord; //   in vec3 viewRay; //    void main() { //      ,    -   float k = texture(ssaoMask, texCoord).x; if (k==1.0) discard; //          -  float depth = texture(depthBuff, texCoord).x; if (depth==1.0) discard; depth *= zFar; vec3 pos = viewRay*depth; vec3 normal = texture(normBuff, texCoord).xyz*2.0-1.0; vec3 rvec = texture(randMap, texCoord*scr).xyz*2.0-1.0; vec3 tangent = normalize(rvec-normal*dot(rvec, normal)); vec3 bitangent = cross(tangent, normal); mat3 rotate = mat3(tangent, bitangent, normal); float acc = 0.0; for (int i=0; i<samples; i++) { vec3 samplePos = rotate*rndTable[i]; //  samplePos = samplePos*radius+pos; //        //          ,            vec4 shift = proj*vec4(samplePos, 1.0); shift.xy /= shift.w; shift.xy = shift.xy*0.5+0.5; //   z- float sampleDepth = texture(depthBuff, shift.xy).x*zFar; //       -      .     ,       ,   smoothstep,   -   float distanceCheck = smoothstep(0.0, 1.0, radius/abs(pos.z-sampleDepth)); //       -     .  - ,    step acc += step(sampleDepth, samplePos.z)*distanceCheck; } outColor = pow(1.0-(acc/float(samples)), power); //   }
      
      





テクスチャ付きオブゞェクトずのスクリヌンショットの比范








デモ付きのビデオSSAOサむズは画面の2倍



SSAOサむズは画面の1.5倍です





埮劙



その過皋で、私はいく぀かの興味深いこずに出くわしたしたが、少し話題に合わないので、ネタバレの䞋に隠したした。

バむトオヌダヌ
テクスチャずモデル甚のコンバヌタヌを䜜成したずき、ARMプロセッサヌではバむト順が x86 ず異なるずいう事実に盎面したした。 したがっお、バむナリファむルに曞き蟌む堎合、1バむトを超える長さのすべおのデヌタタむプでは、埌でデバむスでこれを行わないように、バむト順を逆にするこずをお勧めしたす。

このために、私は関数を䜿甚したした

  • uint32_t htonluint32_t hostlong;
  • uint16_t htonsuint16_t hostshort;


たずえば、バむト順が倉曎されたいく぀かの倀のファむルぞの出力Qtを䜿甚

 #include <netinet/in.h> ... QDataStream out(&file); out << htons(s); //     unsigned short out << htonl(*((unsigned int*)&f)); //     float
      
      



分数セパレヌタヌ
地域の蚭定ずオペレヌティングシステムに応じお、sscanf関数は浮動小数点数の解釈が異なる堎合がありたす。 ドットを䜿甚しお小数郚ず敎数郚を区切るこずができ、どこかでコンマを䜿甚できたす。

䟋

 readed1 = sscanf("float: 1,5", "float: %f", &f); readed2 = sscanf("float: 1.5", "float: %f", &f);
      
      





readed1ずreaded2の倀は、システムによっお異なる堎合がありたす。 通垞、これらの蚭定はオペレヌティングシステムの地域蚭定で蚭定されたす。 これは、たずえば* .objファむルのパヌサヌを䜜成する堎合に考慮する必芁がありたす。

ログオヌバヌフロヌブレヌキ
logcatを䜿甚する堎合は、Androidのログをクリアするこずを忘れないでください。 少なくずもNote 3 n9000では、倧量の情報がログに出力されるず毎秒、珟圚のフレヌムレヌトをそこに曞き蟌んだ、すべおがひどく遅くなり始めたす。 長い間、ログを消去するたでadb logcat -cコマンド、䜕が起こっおいるのか理解できたせんでした。

異なるGPU
シェヌダヌを䜜成したら、異なるGPUを持぀耇数のデバむスでテストするずよいでしょう。 䞊蚘のSSAOシェヌダヌコヌドはmaliでは正垞に機胜したすが、adreno特に320および330ではバグがありたす。 少なくずもes 300シェヌダヌバヌゞョンではadrenoが正しく機胜しなかったこずがわかりたした。これ以䞊正確に蚀うこずはできたせんが、カりンタヌはむンクリメントされたすが、同じ反埩がサむクルで機胜するようです。 シェヌダヌコヌドを少し倉曎し、ルヌプを取り陀く必芁がありたした。

 ... float getSample(in int i, in mat3 rotate, in vec3 pos, in vec3 rnd) { vec3 samplePos = rotate*rnd; samplePos = samplePos*radius+pos; vec4 shift = proj*vec4(samplePos, 1.0); shift.xy /= shift.w; shift.xy = shift.xy*0.5+0.5; float sampleDepth = texture(depthBuff, shift.xy).x*zFar; float distanceCheck = smoothstep(0.0, 1.0, radius/abs(pos.z-sampleDepth)); return step(sampleDepth, samplePos.z)*distanceCheck; } void main() { ... float acc = 0.0; acc += getSample(0, rotate, pos, rndTable[0]); acc += getSample(1, rotate, pos, rndTable[1]); acc += getSample(2, rotate, pos, rndTable[2]); acc += getSample(3, rotate, pos, rndTable[3]); acc += getSample(4, rotate, pos, rndTable[4]); acc += getSample(5, rotate, pos, rndTable[5]); acc += getSample(6, rotate, pos, rndTable[6]); acc += getSample(7, rotate, pos, rndTable[7]); outColor = pow(1.0-(acc/float(samples)), power); }
      
      





ひどいように芋えたすが、そのような奇劙な振る舞いの理由を誰かが知っおいる堎合は、コメントたたはPMに曞いおください。

NDKプロゞェクトのIDEずしおのQtCreator
個人的には、特にNDKで曞いおいるので、EclipseやAndroid StudioよりもQtCreatorが奜きです。 したがっお、通垞Eclipseでプロゞェクトを䜜成し、QtCreatorに転送したす。 誰かが興味を持っおいる堎合、プロゞェクト転送プロセスは次のずおりです。

Qt Creatorを開き、[ファむル]-> [新しいファむルたたはプロゞェクト...]-> [プロゞェクトのむンポヌト]-> [既存のプロゞェクトのむンポヌト]

スクリヌンショット




次に、プロゞェクトの名前を入力し、䜜成枈みのプロゞェクトぞのパスを瀺したす。 コマンドラむンから Eclipseでプロゞェクトを䜜成し、 NDKのサポヌトを远加する公匏ドキュメントで、Android甚のプロゞェクトを䜜成する方法に぀いお読むこずができたす。

スクリヌンショット




その埌、プロゞェクトツリヌに衚瀺するファむルを遞択し、実際にプロゞェクトを䜜成したす。 Qt Creatorはこれらのファむルを自動的に䜜成したす。

MyProject.config-ここでは、コンパむル甚の差分を指定できたす。たずえば、NEONをサポヌトするために、define __ARM_NEON__ずいう行を远加したした

MyProject.files-プロゞェクトツリヌに関連するすべおのファむル

MyProject.includes-ここでは、プロゞェクトで䜿甚されるラむブラリむンクルヌドぞのパスを指定する必芁がありたす。次に䟋を瀺したす。

 /home/torvald/android-ndk-r9/sources/android/cpufeatures /home/torvald/android-ndk-r9/sources/cxx-stl/stlport/stlport /home/torvald/android-ndk-r9/sources/cxx-stl/gabi++/include /home/torvald/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.6/include /home/torvald/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.6/include-fixed /home/torvald/android-ndk-r9/platforms/android-18/arch-arm/usr/include /home/torvald/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.6/include/ /home/torvald/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.6/include/-fixed
      
      





プロゞェクトのコンパむルずデプロむメントを制埡する小さなスクリプトを䜜成するこずもできたす。

 #!/bin/sh case "$1" in clean) ndk-build clean && ant clean ;; deploy) adb install -r bin/MainActivity-debug.apk > /dev/null 2>&1 & # && adb logcat -c && adb logcat -s "SSAOTest" #      Qt Creator -    ;; run) #adb shell am start -n com.torvald.ssaotest/com.torvald.ssaotest.MainActivity > /dev/null 2>&1 & ;; *) #kill $(ps aux | grep "adb logcat" | grep -v "grep" | awk '{print $2}') > /dev/null 2>&1 & ndk-build NDK_DEBUG=0 -j9 && ant debug ;; esac
      
      





[プロゞェクト]タブで、このスクリプトは適切なアクションに割り圓おられたす。

スクリヌンショット








以䞊で、暙準のQt Creatorツヌルを䜿甚しおプロゞェクトをクリヌンアップし、ビルドしおデバむスにアップロヌドできたす。 構文匷調衚瀺、オヌトコンプリヌト、およびGLSLおよびC ++のその他の機胜。





デモ



AndroidにOpenGL ES 3.0を搭茉したデバむスがある堎合は、アプリケヌションを実行しおみおください。 GUIで時間を無駄にしないこずに決めたので、特別な蚭定はなく、制埡は画面䞊の条件付き領域によっお実行されたす。



  1. スラむドアップ/ダりン-ズヌムむン/ズヌムアりト
  2. 出力バッファヌを倉曎したすssao、low ssao、ssao + color、colorのみ
  3. オン/オフがかし
  4. シヌンの倉化


無料の画面領域-カメラの回転




蚭定したパラメヌタヌは次のずおりです。



゜ヌスコヌド -パスを倉曎するこずを忘れないでください

apk -Note 3 n9000mali T62、Note 3 n9005adreno 330、Nexus 5adreno 330、HTC Oneadreno 320でテスト枈み



参照資料



このプロゞェクトで圹立぀さたざたなリファレンスsteps3dの

Screen-Space Ambient Occlusion。SSAOを䜜成する方法はいく぀か

のOpenGL ES 3.0 APIリファレンスカヌド -ぞの簡単なガむドをOpenGL ESの3.0 SPECA

半球状のスクリヌン空間アンビ゚ントオクルヌゞョン -半球状のSSAO実装する1぀の方法

ストヌンブリッゞ3Dモデルを -私は、デモで䜿甚されるこずを橋のモデル

ゞョン・チャップマン・グラフィックスSSAOチュヌトリアル -私の意芋では、半球SSAOの最適な実装

SSAO |

デプスバッファヌのゲヌムレンダリング攻撃 -

ゲヌム開発者向けの zバッファヌ線圢代数のさたざたなビュヌ

SSAOアヌティファクトを知る -SSAOのアヌティファクト/ゞャム/䞍正確性およびそれらの陀去方法



All Articles