2016-09-14 19 views
9

Tôi đang thực hiện mô phỏng vật lý mùa xuân bằng cách sử dụng mẫu 2D để xử lý dữ liệu vị trí trong một trình đổ bóng phân đoạn và nhận kết quả rất kỳ quặc. Nếu tôi bắt đầu với 16 lò xo riêng biệt (một điểm ở cuối của một suối vô hình bắt nguồn từ một neo vô hình), hình ảnh kết thúc với tám cặp, mỗi cặp treo từ cùng một điểm neo mùa xuân. Tuy nhiên, nếu tôi chỉ cần chạy trực quan để đặt các điểm chỉ sử dụng các giá trị tOffsets, tất cả thông tin để tính toán từng điểm neo là ở đó và hiển thị chính xác (mặc dù không có vật lý, tất nhiên). Đó là một khi tôi thêm trở lại trong vật lý mùa xuân mà tôi kết thúc với các cặp một lần nữa. Ngoài ra, từ việc xem trực quan, tôi có thể nói rằng các giá trị điểm neo của các cặp là không có giá trị 16 điểm neo ban đầu nào. Bất kỳ ý tưởng gì đang xảy ra ở đây? (Xem cả fiddle và các ý kiến ​​inline đóng vai chính bên dưới.)Kết quả lẻ từ bóng đổ được sử dụng để xử lý trước mô phỏng vật lý mùa xuân

(three.js v 80)

Xem fiddle sử dụng v79 đây.

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: thể vấn đề là với số lượng giá trị (rgba, xzyw) đồng ý giữa tất cả các mảnh của chương trình của tôi? Tôi đã chỉ định giá trị rgba bất cứ nơi nào tôi có thể nghĩ đến, nhưng có lẽ tôi đã bỏ lỡ một nơi nào đó. Dưới đây là một đoạn trích từ javascript của tôi:

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:

Có lẽ vấn đề đã làm với cách texels đang được đọc từ những kết cấu? Bằng cách nào đó nó có thể được đọc giữa hai texels, và do đó, đến với một vị trí trung bình được chia sẻ bởi hai lò xo? Điều này có thể không? Nếu vậy, tôi sẽ tìm cách sửa chữa nó ở đâu?

Trả lời

0

Tôi chưa bao giờ phát hiện vấn đề với câu hỏi trong câu hỏi của mình ở trên; tuy nhiên, cuối cùng tôi đã tìm thấy phiên bản mới hơn của tập lệnh BA.BOUtils mà tôi đã sử dụng ở trên - hiện được gọi là THREE.GPUComputationRenderer. Sau khi thực hiện nó, kịch bản của tôi cuối cùng đã làm việc!

Đối với những người thấy mình đang cố gắng giải quyết vấn đề tương tự, dưới đây là mới và cải tiến fiddle sử dụng GPUComputationRenderer thay cho FBOUtils cũ.

Ở đây, từ các tài liệu kịch bản, là một trường hợp sử dụng cơ bản của 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); 
Các vấn đề liên quan