私は、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つのばねで共有される平均の位置で出てくるでしょうか?これは可能ですか?もしそうなら、私はそれを修正するためにどこを見ますか?