2016-09-14 3 views
9

私は、2Dサンプラを使用したスプリング物理シミュレーションを行って、フラグメントシェーダの一部の位置データを格納し、あらかじめ処理し、非常に奇妙な結果を得ています。個別に配置された16個のスプリング(目に見えないアンカーに由来する目に見えないスプリングの端にある点)から始めると、視覚化は8個のペアで終わり、各ペアは同じスプリングアンカーポイントにぶら下がります。しかし、私が単にtOffsets値だけを使って点を配置するために視覚化を実行すると、各アンカーポイントを計算するためのすべての情報がそこにあり、正しく表示されます(物理はありません)。私はもう一度春の物理学に戻って、もう一度ペアになってしまいます。また、ビジュアライゼーションを見て、ペアのアンカーポイントの値は元の16個のアンカーポイントの値ではないことが分かります。ここで何が起こっているか考えてみましょうか? (フィドルと以下の星付きインラインコメントの両方を参照してください。)春の物理シミュレーションの前処理に使用されたシェーダからの奇妙な結果

(V 80 three.js)

はここV79を使用してfiddleを参照してください。

uniform sampler2D tPositions; 
uniform sampler2D tOffsets; 

varying vec2 vUv; 

void main() { 

    float damping = 0.98; 

    vec4 nowPos = texture2D(tPositions, vUv).xyzw; 
    vec4 offsets = texture2D(tOffsets, vUv).xyzw; 
    vec2 velocity = vec2(nowPos.z, nowPos.w); 


    vec2 anchor = vec2(offsets.x, 130.0); 

    // Newton's law: F = M * A 
    float mass = 24.0; 
    vec2 acceleration = vec2(0.0, 0.0); 

    // 1. apply gravity's force: **this works fine 
    vec2 gravity = vec2(0.0, 2.0); 
    gravity /= mass; 
    acceleration += gravity; 

    // 2. apply the spring force ** something goes wrong once I add the spring physics - the springs display in pairs 
    float restLength = length(yAnchor - offsets.y); 
    float springConstant = 0.2; 

    // Vector pointing from anchor to point position 
    vec2 springForce = vec2(nowPos.x - anchor.x, nowPos.y - anchor.y); 
    // length of the vector 
    float distance = length(springForce); 
    // stretch is the difference between the current distance and restLength 
    float stretch = distance - restLength; 

    // Calculate springForce according to Hooke's Law 
    springForce = normalize(springForce); 
    springForce *= (1.0 * springConstant * stretch); 

    springForce /= mass; 
    acceleration += springForce; // ** If I comment out this line, all points display where expected, and fall according to gravity. If I add it it back in the springs work properly but display in 8 pairs as opposed to 16 independent locations 

    velocity += acceleration; 
    velocity *= damping; 

    vec2 newPosition = vec2(nowPos.x - velocity.x, nowPos.y - velocity.y);  

    // Write new position out to texture for the next shader 
    gl_FragColor = vec4(newPosition.x, newPosition.y, velocity.x, velocity.y); // **the pair problem shows up with this line active 

    // sanity checks with comments: 
    // gl_FragColor = vec4(newPosition.x, newPosition.y, 0.0, 0.0); // **the pair problem also shows up in this case 
    // gl_FragColor = vec4(offsets.x, offsets.y, velocity); // **all points display in the correct position, though no physics 
    // gl_FragColor = vec4(nowPos.x, nowPos.y, 0.0, 0.0); // **all points display in the correct position, though no physics 

UPDATE 1: は、問題は私のプログラムの断片の全ての間で合意した値の数(RGBA、xzyw)とのだろうか?私はどこでもrgbaの値を指定しましたが、おそらく私はどこかで逃したでしょう。ここに私のjavascriptからの抜粋です:

if (! renderer.context.getExtension('OES_texture_float')) { 
     alert('OES_texture_float is not :('); 
} 

var width = 4, height = 4; 
particles = width * height; 

// Start creation of DataTexture 
var positions = new Float32Array(particles * 4); 
var offsets = new Float32Array(particles * 4); 

// hardcoded dummy values for the sake of debugging: 
var somePositions = [10.885510444641113, -6.274578094482422, 0, 0, -10.12020206451416, 0.8196354508399963, 0, 0, 35.518341064453125, -5.810637474060059, 0, 0, 3.7696402072906494, -3.118760347366333, 0, 0, 9.090447425842285, -7.851400375366211, 0, 0, -32.53229522705078, -26.4628849029541, 0, 0, 32.3623046875, 22.746187210083008, 0, 0, 7.844726085662842, -15.305091857910156, 0, 0, -32.65345001220703, 22.251712799072266, 0, 0, -25.811357498168945, 32.4153938293457, 0, 0, -28.263731002807617, -31.015430450439453, 0, 0, 2.0903847217559814, 1.7632032632827759, 0, 0, -4.471604347229004, 8.995194435119629, 0, 0, -12.317420959472656, 12.19576358795166, 0, 0, 36.77312469482422, -14.580523490905762, 0, 0, 36.447078704833984, -16.085195541381836, 0, 0]; 

for (var i = 0, i4 = 0; i < particles; i ++, i4 +=4) { 

    positions[ i4 + 0 ] = somePositions[ i4 + 0 ]; // x 
    positions[ i4 + 1 ] = somePositions[ i4 + 1 ]; // y 
    positions[ i4 + 2 ] = 0.0; // velocity 
    positions[ i4 + 3 ] = 0.0; // velocity 

    offsets[ i4 + 0 ] = positions[ i4 + 0 ];// - gridPositions[ i4 + 0 ]; // width offset 
    offsets[ i4 + 1 ] = positions[ i4 + 1 ];// - gridPositions[ i4 + 1 ]; // height offset 
    offsets[ i4 + 2 ] = 0; // not used 
    offsets[ i4 + 3 ] = 0; // not used 

} 

positionsTexture = new THREE.DataTexture(positions, width, height, THREE.RGBAFormat, THREE.FloatType); 
positionsTexture.minFilter = THREE.NearestFilter; 
positionsTexture.magFilter = THREE.NearestFilter; 
positionsTexture.needsUpdate = true; 

offsetsTexture = new THREE.DataTexture(offsets, width, height, THREE.RGBAFormat, THREE.FloatType); 
offsetsTexture.minFilter = THREE.NearestFilter; 
offsetsTexture.magFilter = THREE.NearestFilter; 
offsetsTexture.needsUpdate = true; 

rtTexturePos = new THREE.WebGLRenderTarget(width, height, { 
    wrapS:THREE.RepeatWrapping, 
    wrapT:THREE.RepeatWrapping, 
    minFilter: THREE.NearestFilter, 
    magFilter: THREE.NearestFilter, 
    format: THREE.RGBAFormat, 
    type:THREE.FloatType, 
    stencilBuffer: false 
}); 

rtTexturePos2 = rtTexturePos.clone(); 

simulationShader = new THREE.ShaderMaterial({ 
    uniforms: { 
     tPositions: { type: "t", value: positionsTexture }, 
     tOffsets: { type: "t", value: offsetsTexture }, 
    }, 
     vertexShader: document.getElementById('texture_vertex_simulation_shader').textContent, 
     fragmentShader: document.getElementById('texture_fragment_simulation_shader').textContent 
}); 

fboParticles = new THREE.FBOUtils(width, renderer, simulationShader); 
fboParticles.renderToTexture(rtTexturePos, rtTexturePos2); 

fboParticles.in = rtTexturePos; 
fboParticles.out = rtTexturePos2; 

UPDATE 2:

おそらく問題は、テクセルは、これらのテクスチャから読まれているかに関係していますか?どうにかして2つのテクセルの間で読んでいるかもしれないので、2つのばねで共有される平均の位置で出てくるでしょうか?これは可能ですか?もしそうなら、私はそれを修正するためにどこを見ますか?

答えて

0

上記の私の質問では、フィドルの問題を発見したことはありません。しかし、私は最終的に私が上記で使用していたTHREE.FBOUtilsスクリプトの新しいバージョンを見つけました。これは現在THREE.GPUComputationRendererと呼ばれています。それを実装した後、私のスクリプトは最終的に働いた!自身はここので、同様の問題を解決しようと試みて見つける人のため

は新しいものと古いFBOUtilsの代わりにGPUComputationRendererを使用してfiddleを改善しました。ここで

は、スクリプトのドキュメントから、GPUComputationRendererの基本的なユースケースである:

//Initialization... 

// Create computation renderer 
var gpuCompute = new GPUComputationRenderer(1024, 1024, renderer); 

// Create initial state float textures 
var pos0 = gpuCompute.createTexture(); 
var vel0 = gpuCompute.createTexture(); 
// and fill in here the texture data... 

// Add texture variables 
var velVar = gpuCompute.addVariable("textureVelocity", fragmentShaderVel, pos0); 
var posVar = gpuCompute.addVariable("texturePosition", fragmentShaderPos, vel0); 

// Add variable dependencies 
gpuCompute.setVariableDependencies(velVar, [ velVar, posVar ]); 
gpuCompute.setVariableDependencies(posVar, [ velVar, posVar ]); 

// Add custom uniforms 
velVar.material.uniforms.time = { value: 0.0 }; 

// Check for completeness 
var error = gpuCompute.init(); 
if (error !== null) { 
    console.error(error); 
} 

// In each frame... 

// Compute! 
gpuCompute.compute(); 

// Update texture uniforms in your visualization materials with the gpu renderer output 
myMaterial.uniforms.myTexture.value = gpuCompute.getCurrentRenderTarget(posVar).texture; 

// Do your rendering 
renderer.render(myScene, myCamera); 
関連する問題