Place Publique => Taverne des Empafés => Discussion démarrée par: 0Connors le 01 octobre 2014 à 19:20:25
-
Impressionnant !:
https://haxiomic.github.io/GPU-Fluid-Experiments/html5/?q=Medium
-
O_o' impressionnant mais j'aimerais pas voir les maths derrière .... *-*
-
It's a Pleasure ! :D
package;
import gltoolbox.render.RenderTarget2Phase;
import gltoolbox.render.RenderTarget;
import lime.graphics.GLRenderContext;
import lime.graphics.opengl.GLBuffer;
import lime.graphics.opengl.GLTexture;
import lime.math.Vector2;
import lime.utils.Float32Array;
import shaderblox.ShaderBase;
class GPUFluid{
var gl:GLRenderContext;
public var width (default, null) : Int;
public var height (default, null) : Int;
public var cellSize (default, set) : Float;
public var solverIterations : Int;
public var aspectRatio (default, null) : Float;
//Render Targets
public var velocityRenderTarget (default, null) : RenderTarget2Phase;
public var pressureRenderTarget (default, null) : RenderTarget2Phase;
public var divergenceRenderTarget (default, null) : RenderTarget;
public var dyeRenderTarget (default, null) : RenderTarget2Phase;
//User Shaders
public var applyForcesShader (default, set) : ApplyForces;
public var updateDyeShader (default, set) : UpdateDye;
//Internal Shaders
var advectShader : Advect = new Advect();
var divergenceShader : Divergence = new Divergence();
var pressureSolveShader : PressureSolve = new PressureSolve();
var pressureGradientSubstractShader : PressureGradientSubstract = new PressureGradientSubstract();
//Geometry
var textureQuad : GLBuffer;
public function new(gl:GLRenderContext, width:Int, height:Int, cellSize:Float = 8, solverIterations:Int = 18){
this.gl = gl;
this.width = width;
this.height = height;
this.solverIterations = solverIterations;
this.aspectRatio = this.width/this.height;
this.cellSize = cellSize;
var texture_float_linear_supported = true;
//setup gl
#if js //load floating point extension
//(no need for this unless we use linearFactory - for performance and compatibility, it's best to avoid this extension if possible!)
if(gl.getExtension('OES_texture_float_linear') == null) texture_float_linear_supported = false;
if(gl.getExtension('OES_texture_float') == null) null;
#end
//geometry
// inner quad, for main fluid shaders
textureQuad = gltoolbox.GeometryTools.getCachedTextureQuad(gl);
//create texture
// seems to run slightly faster with rgba instead of rgb in Chrome?
var nearestFactory = gltoolbox.TextureTools.customTextureFactory(gl.RGBA, gl.FLOAT , gl.NEAREST);
velocityRenderTarget = new RenderTarget2Phase(gl, nearestFactory, width, height);
pressureRenderTarget = new RenderTarget2Phase(gl, nearestFactory, width, height);
divergenceRenderTarget = new RenderTarget(gl, nearestFactory, width, height);
dyeRenderTarget = new RenderTarget2Phase(gl,
gltoolbox.TextureTools.customTextureFactory(
gl.RGB, gl.FLOAT,
texture_float_linear_supported ? gl.LINEAR : gl.NEAREST
),
width,
height
);
//texel-space parameters
updateCoreShaderUniforms(advectShader);
updateCoreShaderUniforms(divergenceShader);
updateCoreShaderUniforms(pressureSolveShader);
updateCoreShaderUniforms(pressureGradientSubstractShader);
}
public function step(dt:Float){
gl.viewport(0, 0, this.width, this.height);
//inner quad
gl.bindBuffer(gl.ARRAY_BUFFER, textureQuad);
advect(velocityRenderTarget, dt);
applyForces(dt);
computeDivergence();
solvePressure();
subtractPressureGradient();
updateDye(dt);
advect(dyeRenderTarget, dt);
}
public inline function resize(width:Int, height:Int){
velocityRenderTarget.resize(width, height);
pressureRenderTarget.resize(width, height);
divergenceRenderTarget.resize(width, height);
dyeRenderTarget.resize(width, height);
this.width = width;
this.height = height;
}
public inline function clear(){
velocityRenderTarget.clear(gl.COLOR_BUFFER_BIT);
pressureRenderTarget.clear(gl.COLOR_BUFFER_BIT);
dyeRenderTarget.clear(gl.COLOR_BUFFER_BIT);
}
public function simToClipSpaceX(simX:Float) return simX/(this.cellSize * this.aspectRatio);
public function simToClipSpaceY(simY:Float) return simY/(this.cellSize);
public inline function advect(target:RenderTarget2Phase, dt:Float){
advectShader.dt.set(dt);
//set velocity and texture to be advected
advectShader.target.set(target.readFromTexture);
advectShader.velocity.set(velocityRenderTarget.readFromTexture);
renderShaderTo(advectShader, target);
target.swap();
}
inline function applyForces(dt:Float){
if(applyForcesShader == null)return;
//set uniforms
applyForcesShader.dt.set(dt);
applyForcesShader.velocity.set(velocityRenderTarget.readFromTexture);
//render
renderShaderTo(applyForcesShader, velocityRenderTarget);
velocityRenderTarget.swap();
}
inline function computeDivergence(){
divergenceShader.velocity.set(velocityRenderTarget.readFromTexture);
renderShaderTo(divergenceShader, divergenceRenderTarget);
}
inline function solvePressure(){
pressureSolveShader.divergence.set(divergenceRenderTarget.texture);
pressureSolveShader.activate(true, true);
for (i in 0...solverIterations) {
pressureSolveShader.pressure.set(pressureRenderTarget.readFromTexture);
//(not using renderShaderTo to allow for minor optimization)
pressureSolveShader.setUniforms();
pressureRenderTarget.activate();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
pressureRenderTarget.swap();
}
pressureSolveShader.deactivate();
}
inline function subtractPressureGradient(){
pressureGradientSubstractShader.pressure.set(pressureRenderTarget.readFromTexture);
pressureGradientSubstractShader.velocity.set(velocityRenderTarget.readFromTexture);
renderShaderTo(pressureGradientSubstractShader, velocityRenderTarget);
velocityRenderTarget.swap();
}
inline function updateDye(dt:Float){
if(updateDyeShader==null)return;
//set uniforms
updateDyeShader.dt.set(dt);
updateDyeShader.dye.set(dyeRenderTarget.readFromTexture);
//render
renderShaderTo(updateDyeShader, dyeRenderTarget);
dyeRenderTarget.swap();
}
inline function renderShaderTo(shader:ShaderBase, target:gltoolbox.render.ITargetable){
shader.activate(true, true);
target.activate();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
shader.deactivate();
}
inline function updateCoreShaderUniforms(shader:FluidBase){
if(shader==null)return;
//set uniforms
shader.aspectRatio.set(this.aspectRatio);
shader.invresolution.data.x = 1/this.width;
shader.invresolution.data.y = 1/this.height;
}
inline function set_applyForcesShader(v:ApplyForces):ApplyForces{
this.applyForcesShader = v;
this.applyForcesShader.dx.data = this.cellSize;
updateCoreShaderUniforms(this.applyForcesShader);
return this.applyForcesShader;
}
inline function set_updateDyeShader(v:UpdateDye):UpdateDye{
this.updateDyeShader = v;
this.updateDyeShader.dx.data = this.cellSize;
updateCoreShaderUniforms(this.updateDyeShader);
return this.updateDyeShader;
}
inline function set_cellSize(v:Float):Float{
//shader specific
cellSize = v;
advectShader.rdx.set(1/cellSize);
divergenceShader.halfrdx.set(0.5*(1/cellSize));
pressureGradientSubstractShader.halfrdx.set(0.5*(1/cellSize));
pressureSolveShader.alpha.set(-cellSize*cellSize);
return cellSize;
}
}
@:vert('#pragma include("Source/shaders/glsl/fluid/texel-space.vert")')
@:frag('#pragma include("Source/shaders/glsl/fluid/fluid-base.frag")')
class FluidBase extends ShaderBase{}
@:frag('#pragma include("Source/shaders/glsl/fluid/advect.frag")')
class Advect extends FluidBase{}
@:frag('#pragma include("Source/shaders/glsl/fluid/velocity-divergence.frag")')
class Divergence extends FluidBase{}
@:frag('#pragma include("Source/shaders/glsl/fluid/pressure-solve.frag")')
class PressureSolve extends FluidBase{}
@:frag('#pragma include("Source/shaders/glsl/fluid/pressure-gradient-subtract.frag")')
class PressureGradientSubstract extends FluidBase{}
@:frag('
uniform sampler2D velocity;
uniform float dt;
uniform float dx;
varying vec2 texelCoord;
varying vec2 p;
')
class ApplyForces extends FluidBase{}
@:frag('
uniform sampler2D dye;
uniform float dt;
uniform float dx;
varying vec2 texelCoord;
varying vec2 p;
')
class UpdateDye extends FluidBase{}
-
WOW c'est badass :D
-
Alors, combien de temps tu as passé sur la page web ? :D