From c563c3aaf7791b50d4d9a11d76d86f5826e26fbe Mon Sep 17 00:00:00 2001 From: clementlandrin Date: Tue, 12 Nov 2024 08:14:51 +0100 Subject: [PATCH] GPUEmitter.hx adding particle random in particleBuffer. Remove blueNoise texture to get pseudo random values (fixing cube spawn artifacts). --- hrt/prefab/fx/gpuemitter/BaseSimulation.hx | 9 +- hrt/prefab/fx/gpuemitter/BaseSpawn.hx | 11 +- hrt/prefab/fx/gpuemitter/ComputeUtils.hx | 45 +------- hrt/prefab/fx/gpuemitter/CubeSpawn.hx | 8 +- hrt/prefab/fx/gpuemitter/GPUEmitter.hx | 47 ++++---- hrt/prefab/fx/gpuemitter/MeshSpawn.hx | 106 +++++++----------- .../fx/gpuemitter/OrbitSpeedSimulation.hx | 9 +- .../fx/gpuemitter/TurbulenceSimulation.hx | 9 +- 8 files changed, 99 insertions(+), 145 deletions(-) diff --git a/hrt/prefab/fx/gpuemitter/BaseSimulation.hx b/hrt/prefab/fx/gpuemitter/BaseSimulation.hx index a0ac6299f..d7666719d 100644 --- a/hrt/prefab/fx/gpuemitter/BaseSimulation.hx +++ b/hrt/prefab/fx/gpuemitter/BaseSimulation.hx @@ -5,7 +5,12 @@ class BaseSimulation extends ComputeUtils { @param var batchBuffer : RWPartialBuffer<{ modelView : Mat4, }>; - @param var particleBuffer : RWPartialBuffer<{ speed : Vec3, lifeTime : Float }>; + @param var particleBuffer : RWPartialBuffer<{ + speed : Vec3, + lifeTime : Float, + lifeRatio : Float, + random : Float, + }>; @const var INFINITE : Bool = false; @const var FACE_CAM : Bool = false; @@ -19,6 +24,7 @@ class BaseSimulation extends ComputeUtils { var dt : Float; var speed : Vec3; var lifeTime : Float; + var particleRandom : Float; var modelView : Mat4; var instanceID : Int; var prevModelView : Mat4; @@ -28,6 +34,7 @@ class BaseSimulation extends ComputeUtils { speed = particleBuffer[computeVar.globalInvocation.x].speed; lifeTime = particleBuffer[computeVar.globalInvocation.x].lifeTime; prevModelView = batchBuffer[computeVar.globalInvocation.x].modelView; + particleRandom = particleBuffer[computeVar.globalInvocation.x].random; } function main() { diff --git a/hrt/prefab/fx/gpuemitter/BaseSpawn.hx b/hrt/prefab/fx/gpuemitter/BaseSpawn.hx index bb498270a..32629b653 100644 --- a/hrt/prefab/fx/gpuemitter/BaseSpawn.hx +++ b/hrt/prefab/fx/gpuemitter/BaseSpawn.hx @@ -5,7 +5,12 @@ class BaseSpawn extends ComputeUtils { @param var batchBuffer : RWPartialBuffer<{ modelView : Mat4, }>; - @param var particleBuffer : RWPartialBuffer<{ speed : Vec3, lifeTime : Float, lifeRatio : Float }>; + @param var particleBuffer : RWPartialBuffer<{ + speed : Vec3, + lifeTime : Float, + lifeRatio : Float, + random : Float, + }>; @param var atomic : RWBuffer; @const var SPEED_NORMAL : Bool; @@ -17,12 +22,14 @@ class BaseSpawn extends ComputeUtils { @param var absPos : Mat4; var lifeTime : Float; + var particleRandom : Float; var modelView : Mat4; var relativeTransform : Mat4; var emitNormal : Vec3; function __init__() { emitNormal = vec3(0.0, 0.0, 1.0); - lifeTime = mix(minLifeTime, maxLifeTime, (global.time + computeVar.globalInvocation.x * 0.5123789) % 1.0); + particleRandom = particleBuffer[computeVar.globalInvocation.x].random; + lifeTime = mix(minLifeTime, maxLifeTime, (global.time + particleRandom) % 1.0); relativeTransform = translationMatrix(vec3(0.0)); modelView = relativeTransform * absPos; } diff --git a/hrt/prefab/fx/gpuemitter/ComputeUtils.hx b/hrt/prefab/fx/gpuemitter/ComputeUtils.hx index f2c157e4f..0d3329359 100644 --- a/hrt/prefab/fx/gpuemitter/ComputeUtils.hx +++ b/hrt/prefab/fx/gpuemitter/ComputeUtils.hx @@ -1,37 +1,10 @@ package hrt.prefab.fx.gpuemitter; class ComputeUtils extends hxsl.Shader { - static var blueNoise : h3d.mat.Texture; - - public function new() { - super(); - - if ( blueNoise == null ) { - blueNoise = new h3d.mat.Texture(256, 256, [NoAlloc], RGBA); - blueNoise.realloc = function() { - var rand = new hxd.Rand(0); - var pix = hxd.Pixels.alloc(256, 256, RGBA); - for ( i in 0...256 ) { - for ( j in 0...256 ) { - var color = rand.random(256); - color = color | (rand.random(256) << 8); - color = color | (rand.random(256) << 16); - color = color | (rand.random(256) << 24); - pix.setPixel(i, j, color); - } - } - blueNoise.uploadPixels(pix); - } - blueNoise.wrap = Repeat; - blueNoise.filter = Nearest; - } - blueNoiseSampler = blueNoise; - } public function onUpdate(emitter : GPUEmitter.GPUEmitterObject, buffer : h3d.Buffer, index : Int) {} static var SRC = { - @param var blueNoiseSampler : Sampler2D; @global var global : { var time : Float; @@ -41,22 +14,6 @@ class ComputeUtils extends hxsl.Shader { var position : Vec3; } - function randomNoise(pos : Vec2) : Float { - return blueNoiseSampler.get(pos).r; - } - - function randomNoise2d(pos : Vec2) : Vec2 { - return blueNoiseSampler.get(pos).rg; - } - - function randomNoise3d(pos : Vec2) : Vec3 { - return blueNoiseSampler.get(pos).rgb; - } - - function randomNoise4d(pos : Vec2) : Vec4 { - return blueNoiseSampler.get(pos); - } - function random(pos : Vec2) : Float { return fract(sin(dot(pos, vec2(12.9898,78.233)))*43758.5453123); } @@ -69,7 +26,7 @@ class ComputeUtils extends hxsl.Shader { function random3d(pos : Vec2) : Vec3 { return vec3(fract(sin(dot(pos, vec2(12.9898,78.233)))*43758.5453123), fract(sin(dot(pos, vec2(1572.9898,132.237)))*157468.33458), - fract(sin(dot(pos, vec2(14.5757,59.147)))*43756.281)); + fract(sin(dot(pos, vec2(14.5757,59.147)))*4756.281)); } function translationMatrix(pos : Vec3) : Mat4 { diff --git a/hrt/prefab/fx/gpuemitter/CubeSpawn.hx b/hrt/prefab/fx/gpuemitter/CubeSpawn.hx index 6fd95f9f9..84e04815a 100644 --- a/hrt/prefab/fx/gpuemitter/CubeSpawn.hx +++ b/hrt/prefab/fx/gpuemitter/CubeSpawn.hx @@ -1,21 +1,17 @@ package hrt.prefab.fx.gpuemitter; class CubeSpawnShader extends ComputeUtils { - override function onUpdate(emitter : GPUEmitter.GPUEmitterObject, buffer : h3d.Buffer, index : Int) { - super.onUpdate(emitter, buffer, index); - randOffset = index; - } static var SRC = { @param var boundsMin : Vec3; @param var boundsSize : Vec3; - @param var randOffset : Int; var emitNormal : Vec3; var lifeTime : Float; + var particleRandom : Float; var relativeTransform : Mat4; function main() { - var rnd = randomNoise3d(vec2(global.time, global.time * computeVar.globalInvocation.x + randOffset)); + var rnd = random3d(vec2(global.time + particleRandom, particleRandom * 100.0)); relativeTransform = translationMatrix(rnd * boundsSize + boundsMin); } } diff --git a/hrt/prefab/fx/gpuemitter/GPUEmitter.hx b/hrt/prefab/fx/gpuemitter/GPUEmitter.hx index 1a0258af4..6c5c81bc2 100644 --- a/hrt/prefab/fx/gpuemitter/GPUEmitter.hx +++ b/hrt/prefab/fx/gpuemitter/GPUEmitter.hx @@ -71,7 +71,7 @@ class GPUEmitterObject extends h3d.scene.MeshBatch { var shaderParams : Array<{ param : hrt.prefab.fx.BaseFX.ShaderParam, shader : UpdateParamShader }> = []; var paramTexture : h3d.mat.Texture; - var particleBuffers : ParticleBuffer; + var particleBuffers : ParticleBuffer; var particleShader : ParticleShader; var rateAccumulation : Float = 0.0; @@ -265,18 +265,17 @@ class GPUEmitterObject extends h3d.scene.MeshBatch { case Camera: baseSpawn.absPos.identity(); particleShader.absPos.identity(); - + var camPos = ctx.camera.pos; - var d = data.cameraModeDistance * 0.5; - var bounds = h3d.col.Bounds.fromValues(camPos.x - d, - camPos.y - d, - camPos.z - d, - 2.0 * d, - 2.0 * d, - 2.0 * d); + var d = data.cameraModeDistance; + var bounds = h3d.col.Bounds.fromValues(camPos.x - d * 0.5, + camPos.y - d * 0.5, + camPos.z - d * 0.5, + d, + d, + d); baseSimulation.boundsPos.set(bounds.xMin, bounds.yMin, bounds.zMin); baseSimulation.boundsSize.set(bounds.xSize, bounds.ySize, bounds.zSize); - particleShader.absPos.load(getAbsPos()); var cubeSpawn = spawnPass.getShader(CubeSpawnShader); if ( cubeSpawn == null ) { @@ -388,11 +387,10 @@ class GPUEmitter extends Object3D { @:s var maxLifeTime : Float = 1.0; @:s var minStartSpeed : Float = 0.5; @:s var maxStartSpeed : Float = 1.0; - @:s var gravity : Float = 1.0; - @:s var radius : Float = 1.0; - @:s var startSpeed : Float = 1.0; - @:s var infinite : Bool = false; - @:s var faceCam : Bool = false; + @:s var gravity : Float = 1.0; + @:s var radius : Float = 1.0; + @:s var startSpeed : Float = 1.0; + @:s var infinite : Bool = false; @:s var mode : Mode = World; @:s var cameraModeDistance : Float = 50.0; @:s var align : Align = FaceCam; @@ -402,6 +400,12 @@ class GPUEmitter extends Object3D { return new h3d.scene.Object(parent3d); } + override function makeChild(c : hrt.prefab.Prefab) { + if ( Std.isOfType(c, hrt.prefab.Object3D) ) + return; + super.makeChild(c); + } + function updateEmitters() { #if editor return; @@ -410,6 +414,7 @@ class GPUEmitter extends Object3D { emitter.remove(); var meshes = []; + meshes = local3d.findAll(o -> Std.downcast(o, h3d.scene.Mesh)); for ( c in children ) { if ( !Std.isOfType(c, Object3D) ) continue; @@ -431,7 +436,6 @@ class GPUEmitter extends Object3D { startSpeed : startSpeed, trs : trs, infinite : infinite, - faceCam : faceCam, mode : mode, cameraModeDistance : cameraModeDistance, align : align, @@ -458,9 +462,7 @@ class GPUEmitter extends Object3D { } } - override function postMakeInstance() { - super.postMakeInstance(); - + function bakeAnimations() { var obj = local3d.find(o -> Std.downcast(o, GPUEmitterObject)); if ( obj != null ) { obj.customAnimations = []; @@ -473,6 +475,12 @@ class GPUEmitter extends Object3D { } } + override function postMakeInstance() { + super.postMakeInstance(); + + bakeAnimations(); + } + override function updateInstance(?propName : String) { super.updateInstance(propName); updateEmitters(); @@ -501,7 +509,6 @@ class GPUEmitter extends Object3D {
Min life time
Max life time
Infinite
-
Face cam
Mode