2017-05-18 20 views
0

私は今この間私の頭を叩いています。 GPGPU布物理シミュレーションに使用しているインデックス付きPlaneBufferGeometryがあります。シミュレーションをテクスチャにレンダリングした後、最終頂点シェーダで法線を正しく計算できません。Three.js /変位後に頂点シェーダ内のインデックス付きPlaneBufferGeometryの頂点法線を計算する

これは私の現在の設定です(関連する部分が含まれています)。私は現在のVertの順序を知る方法が必要で、それは動作していないと思います。ちょうどそれを正しく得ることはできません。

のjavascript:

// get faces 
const indices = geometry.index.array; 
const faces = []; 
for(let i = 0; i < indices.length; i += 3) 
{ 
    faces.push([indices[i + 0] * 3, indices[i + 1] * 3, indices[i + 2] * 3]); 
} 

const vertices = geometry.attributes.position.array; 

// begin loop 

// initializing data texture vertex positions 
dataTexturePixels[index * 4 + 0] = vertices[index * 3 + 0]; 
dataTexturePixels[index * 4 + 1] = vertices[index * 3 + 1]; 
dataTexturePixels[index * 4 + 2] = vertices[index * 3 + 2]; 
dataTexturePixels[index * 4 + 3] = 0; 

// storing lookup uv's in an attribute for looking up positions 
positionReference[index * 3 + 0] = (index % size)/size; 
positionReference[index * 3 + 1] = Math.floor(index/size)/size; 

// end loop 

私の脳がアップトリップされる場所です。私はさまざまな方法で顔の配列から顔のインデックス値を使用しようとしましたが、インデックスが重複しているため、データが上書きされています。各顔の頂点インデックス情報を適切に保存する方法を考えることができないので、positionReference(またはその他の方法)を使用して頂点シェーダで参照することができます。シミュレーションの実行後に

頂点シェーダ/:

// how I'd calculate the normals if I could get a proper ordered reference 
vec2 coord1 = faceVert1UvReference.xy; 
vec3 pos1 = texture2D(tPositions, coord1).xyz; 

vec2 coord2 = faceVert2UvReference.xy; 
vec3 pos2 = texture2D(tPositions, coord2).xyz; 

vec2 coord3 = faceVert3UvReference.xy; 
vec3 pos3 = texture2D(tPositions, coord3).xyz; 

vec3 tangent = pos3 - pos2; 
vec3 bitangent = pos1 - pos2; 
vec3 normal = normalMatrix * normalize(cross(tangent, bitangent)); 

フラグメントシェーダ/照明:

vec3 lightDirection = normalize(lightPosition); // also tried normalize(lightPosition - vWorldPosition); 
vec3 normal = normalize(vNormal); 
float lightValue = max(0.0, dot(normal, lightDirection)) * lightIntensity; 
finalColor.rgb *= lightValue; 

ない私が馬鹿に何かをやって/何かを明らかに不足している、またはこれよかどうかわから問題は本当に難しいです。私が試みた多くの失敗した方法を投稿することなく、誰もがアイデアを持っていますか?

ご協力いただきまして誠にありがとうございます。私の現在のめちゃくちゃスムーズ頂点法線の進行状況を示す私はカップルの例を追加しました、顔の法線とフラットシェーディングを使用していますthis one、およびthis one


[編集1]。苦労私のエラーを見つけることを持って...


[編集2]:これは私が各頂点に顔データでパイピングだ方法です。すべてがデータの観点から私には正しいように見えますが、視覚的に完全に混乱します。私の人生は、私が間違っている場所を見つけることができません。

javascriptの

const indices = geometry.index.array; 
const faces = []; 

// store faces for each vertex 
for(let i = 0; i < indices.length; i += 3) 
{ 
    const vertIndex1 = indices[ i + 0 ]; 
    const vertIndex2 = indices[ i + 1 ]; 
    const vertIndex3 = indices[ i + 2 ]; 

    faces[ vertIndex1 ] = faces[ vertIndex1 ] || []; 
    faces[ vertIndex2 ] = faces[ vertIndex2 ] || []; 
    faces[ vertIndex3 ] = faces[ vertIndex3 ] || []; 

    faces[ vertIndex1 ].push([ vertIndex1, vertIndex2, vertIndex3 ]); 
    faces[ vertIndex2 ].push([ vertIndex1, vertIndex2, vertIndex3 ]); 
    faces[ vertIndex3 ].push([ vertIndex1, vertIndex2, vertIndex3 ]); 
} 

const size = 128; 
const vertices = geometry.attributes.position; 
const faceIndices = new Uint16Array(vertices.array.length); 
const indices0 = gpuCompute.createTexture(size * 2, size * 2); // need 256x256 texture for all the data. 
const indicesPixels0 = indices0.image.data; 

let faceVertPixelIndex = 0, 
    faceIndexRangeStart = 0, 
    faceIndexRangeEnd = -1, 
    index; 

for(let i = 0; i < size; i++) 
{ 
    for(let j = 0; j < size; j++) 
    { 
     index = j + (i * size); 

     // ---------------------------------------------- 
     // writing vertex positions to data texture here 
     // ---------------------------------------------- 


     if(faces[index]) 
     { 
      const face = faces[index]; 
      const fLen = face.length; 

      faceIndexRangeStart = faceIndexRangeEnd + 1; 
      faceIndexRangeEnd = faceIndexRangeStart + fLen - 1; 

      // face index range for looking up up all faces a single vertex is in 
      faceIndices[index * 3 + 0] = faceIndexRangeStart; 
      faceIndices[index * 3 + 1] = faceIndexRangeEnd; 
      faceIndices[index * 3 + 2] = 0; // unused 

      for(let v = 0; v < fLen; v++) 
      { 
       // store face vertex indices in each pixel rgb 
       indicesPixels0[faceVertPixelIndex * 4 + 0] = face[v][0]; // current face, vertex 1 index 
       indicesPixels0[faceVertPixelIndex * 4 + 1] = face[v][1]; // current face, vertex 2 index 
       indicesPixels0[faceVertPixelIndex * 4 + 2] = face[v][2]; // current face, vertex 3 index 
       indicesPixels0[faceVertPixelIndex * 4 + 3] = 0; // unused 

       faceVertPixelIndex++; 
      } 
     } 
    } 
} 

geometry.addAttribute('faceIndices', new THREE.BufferAttribute(faceIndices, 3)); 

uniforms.tIndices.value = indices0; 

頂点シェーダ(関連部分)

uniform vec2 resolution; 
uniform sampler2D tPositions; 
uniform sampler2D tIndices; 

attribute vec3 faceIndices; 

varying vec3 vNormal; 

vec2 getCoord(in float index, in vec2 size) 
{ 
    return vec2(mod(index, size.x)/size.x, floor(index/size.y)/size.y); 
} 

void addNormal(inout vec3 nrml, in float index) 
{ 
    vec2 coord = getCoord(index, resolution * 2.0); // 256x256 sized texture for faces 
    vec4 face = texture2D(tIndices, coord); 

    // get uv for each vertex index in the face and grab positions. 
    vec2 v1Coord = getCoord(face.x, resolution); 
    vec3 v1 = texture2D(tPositions, v1Coord).xyz; 

    vec2 v2Coord = getCoord(face.y, resolution); 
    vec3 v2 = texture2D(tPositions, v2Coord).xyz; 

    vec2 v3Coord = getCoord(face.z, resolution); 
    vec3 v3 = texture2D(tPositions, v3Coord).xyz; 

    vec3 tangent = v3 - v2; 
    vec3 bitangent = v1 - v2; 

    vec3 n = normalize(cross(tangent, bitangent)); 

    nrml += n; 
} 

void main() 
{ 
    vec3 nrml = vec3(0.0); 
    vec2 faceIndexRange = faceIndices.xy; 

    float from = faceIndexRange.x; 
    float to = faceIndexRange.y; 
    float index = from; 

    for(int i = 0; i < 6; i++) 
    { 
     if(index <= to) 
     { 
      addNormal(nrml, index); 
      index += 1.0; 
     } 
     else 
     { 
      break; 
     } 
    } 

    vNormal = normalMatrix * normalize(nrml); 
} 
+0

[フラットシェーディング](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/normal_fragment)のライブサンプルを初めてデモンストレーションすると、ヘルプが表示される場合があります。 .glsl#L5-L7)。その場合、法線は必要ありません。また、uvsはピクセルの中心にインデックスを付ける必要があります。したがって、テクスチャが4x4の場合、UVは1/8,3/8,5/8,7/8になります。 – WestLangley

+0

@WestLangley私は現在の進行状況を示すカップルのコードを追加しました。フラットシェーディング - [リンク](https://codepen.io/mystaticself/pen/WjYRRm)、そして私の現在の法線の進捗状況は非常にうんざりです - [リンク](https://codepen.io/mystaticself/pen/oWQaZg) – mystaticself

+0

あなたはこれをデバッグするスキルを持っているはずです。 :)デバッグのためにサイズを4に設定しました。ところで、ユニフォームを指定するときに 'type'を設定する必要はなくなりました。 – WestLangley

答えて

0

私は上記の共有面のアプローチを廃棄しまって、代わりに近隣のルックアップ・アプローチを使用し、感謝に@ luigi-de-rosaを助けてください。私はこれまでこれを試していましたが、ルックアップテクスチャから近隣のものを取得するために間違った値を使用していました。

ここで、頂点シェーダで法線を計算しています。

float diff = 0.06; // tweak this value to yield different results. 
vec2 coord = positionReference.xy; 
vec3 transformed = texture2D(tPositions, coord).xyz; 
vec3 neighbour1 = texture2D(tPositions, coord + vec2(diff, 0.0)).xyz; 
vec3 neighbour2 = texture2D(tPositions, coord + vec2(0.0, diff)).xyz; 
vec3 tangent = neighbour1 - transformed; 
vec3 bitangent = neighbour2 - transformed;    
vec3 nrml = cross(tangent, bitangent); 
vNormal = normalMatrix * -normalize(nrml); // pass to fragment shader 

非常に簡単なアプローチ...一口。

関連する問題