particle systems update

This commit is contained in:
peterino2 2025-09-23 17:29:37 -07:00
parent eaf1d2bcb7
commit 85c18f29ec
9 changed files with 115 additions and 48 deletions

View File

@ -10,9 +10,9 @@ const pod = lua.pod;
// LUA END
// vector versions.
pub const f32x4 = @Vector(4, f32);
pub const f32x8 = @Vector(8, f32);
pub const f32x16 = @Vector(16, f32);
pub const f32x4 = @Vector(4, f32); // __m128_int
pub const f32x8 = @Vector(8, f32); // __m256_int
pub const f32x16 = @Vector(16, f32); // __m512_int
pub const f32x4_zero = std.mem.zeroes(@Vector(4, f32));
pub const f32x8_zero = std.mem.zeroes(@Vector(8, f32));

View File

@ -85,20 +85,21 @@ Output main(Input input)
if(billboard > 0)
{
float3 billboardPosition = mul(scene[input.Instance].Model, float4(0,0,0,1)).xyz;
float3 toCamera = normalize(billboardPosition - cameraPosition.xyz);
float3 toCamera = normalize(cameraPosition.xyz - billboardPosition);
float3 up = float3(0,1,0);
float3 right = normalize(cross(up, toCamera));
up = cross(toCamera, right);
//toCamera = float3(0, 0, -1);
float d = length(cameraPosition.xyz - billboardPosition);
float perspectiveScale = d * 0.1f; // adjust multiplier as needed
float perspectiveScale = 1.0f; // adjust multiplier as needed
float finalSize = scene[input.Instance].float0 * perspectiveScale;
float3 wp = billboardPosition +
mul(mul(right, input.Position.x), finalSize) +
mul(mul(right, input.Position.y), finalSize);
mul(mul(right, -input.Position.x), finalSize) +
mul(mul(up, input.Position.y), finalSize);
WorldPos = float4(wp, 1.0);

View File

@ -287,6 +287,10 @@ pub const ParticleEmitter = struct {
}
pub fn update(self: *@This(), dt: f64) void {
if (self.state == .paused) {
return;
}
if (self.state != .dead) {
self.updateSpawn(dt);
}

View File

@ -6,6 +6,8 @@ spans: std.ArrayListUnmanaged(core.Span) = .{},
renderInfo: std.ArrayListUnmanaged(SgpuParticleRenderInfo) = .{},
lastParticleCount: u32 = 0,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.ParticleRenderer");
const SgpuParticleRenderInfo = struct {
@ -58,10 +60,10 @@ pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
uploadMapped[i + offset] = .{
.Model = final,
.textureMode = 0x2, //0x2, // default 0x2 is fullbright
.textureMode = if (emitter.billboard) 0x2 else 0x0, //0x2, // default 0x2 is fullbright
.animation = -1,
.float0 = size,
.flags = 0, //0x4,
.flags = if (emitter.billboard) 0x4 else 0, //0x4 for billboard mode
};
}
@ -70,6 +72,8 @@ pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
offset += emitter.finals.items.len;
}
self.lastParticleCount = @intCast(offset);
if (self.renderInfo.items.len == 0)
return;
@ -121,7 +125,7 @@ pub fn destroy(self: *@This()) void {
self.allocator.destroy(self);
}
const MaxParticleCount = 1_000_000;
const MaxParticleCount = 10_000_000;
const assets = @import("assets");
const core = @import("core");

View File

@ -44,6 +44,8 @@ pub const Renderer = struct {
depthTexture: *gpu.GPUTexture = undefined,
depthFormat: gpu.GPUTextureFormat = .textureformatD32Float,
transparentDepthTexture: *gpu.GPUTexture = undefined,
textureList: *TextureList = undefined,
shadowMapProjection: core.Transform = core.zm.identity(),
@ -398,6 +400,7 @@ pub const Renderer = struct {
gci.usage = .{ .textureusageDepthStencilTarget = true };
self.depthTexture = self.device.createGPUTexture(&gci);
self.transparentDepthTexture = self.device.createGPUTexture(&gci);
}
pub fn discoverFormats(self: *@This()) !void {
@ -696,6 +699,7 @@ pub const Renderer = struct {
ptr.ViewTransform = @bitCast(camera.transform);
ptr.ViewProjection = @bitCast(camera.final);
ptr.NoTranslateView = @bitCast(camera.noTranslate);
ptr.cameraPosition = @bitCast(camera.finalPos.toZm());
}
ptr.ShadowMapProjection = @bitCast(self.shadowMapProjection);
// ptr.ViewProjection = @bitCast(self.shadowMapProjection);
@ -963,6 +967,45 @@ pub const Renderer = struct {
self.state.pass = null;
}
pub fn renderTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
const targetInfo: [4]gpu.GPUColorTargetInfo = .{
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = self.state.targetTexture,
.load_op = .loadopLoad,
.store_op = .storeopStore,
}),
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = self.state.emissiveTarget,
.load_op = .loadopClear,
.store_op = .storeopStore,
}),
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = self.state.positionTarget,
.load_op = .loadopClear,
.store_op = .storeopStore,
}),
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = self.state.normalTarget,
.load_op = .loadopClear,
.store_op = .storeopStore,
}),
};
const depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{
.texture = self.transparentDepthTexture,
.load_op = .loadopDontCare,
.store_op = .storeopDontCare,
.stencil_load_op = .loadopDontCare,
.stencil_store_op = .storeopDontCare,
.clear_depth = 1.0,
.clear_stencil = 0,
});
const renderpass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget);
renderpass.endGPURenderPass();
}
pub fn drawPostProcess(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
const postProcTargetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = self.state.swapchainTargetTexture.?,

View File

@ -60,61 +60,60 @@ struct main0_in
vertex main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], const device type_StructuredBuffer_Scene& scene [[buffer(1)]], const device type_StructuredBuffer_BoneTransform& animationBuffer [[buffer(2)]], uint gl_InstanceIndex [[instance_id]])
{
main0_out out = {};
float3 _112;
float3 _111;
if (scene._m0[gl_InstanceIndex].animation != (-1))
{
float3 _84;
_84 = float3(0.0);
for (int _87 = 0; _87 < 4; )
float3 _83;
_83 = float3(0.0);
for (int _86 = 0; _86 < 4; )
{
uint _93 = (8u * uint(_87)) & 31u;
_84 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _93) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _93) & 255u) * 0.0039215688593685626983642578125));
_87++;
uint _92 = (8u * uint(_86)) & 31u;
_83 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _92) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _92) & 255u) * 0.0039215688593685626983642578125));
_86++;
continue;
}
_112 = _84;
_111 = _83;
}
else
{
_112 = in.in_var_TEXCOORD0;
_111 = in.in_var_TEXCOORD0;
}
float4 _116 = float4(_112, 1.0);
float3 _210;
float3 _211;
float3 _212;
float4 _213;
float4 _214;
float4 _115 = float4(_111, 1.0);
float3 _207;
float3 _208;
float3 _209;
float4 _210;
float4 _211;
if (int(scene._m0[gl_InstanceIndex].flags & 4u) > 0)
{
float3 _128 = (scene._m0[gl_InstanceIndex].Model * float4(0.0, 0.0, 0.0, 1.0)).xyz;
float3 _133 = fast::normalize(_128 - Uniforms.cameraPosition.xyz);
float3 _135 = fast::normalize(cross(float3(0.0, 1.0, 0.0), _133));
float _141 = scene._m0[gl_InstanceIndex].float0 * (length(Uniforms.cameraPosition.xyz - _128) * 0.100000001490116119384765625);
float4 _155 = float4((_128 + ((_135 * in.in_var_TEXCOORD0.x) * _141)) + ((_135 * in.in_var_TEXCOORD0.y) * _141), 1.0);
_210 = _155.xyz;
_211 = _133;
_212 = float3(0.0, 0.0, 1.0);
_213 = Uniforms.ViewProjection * _155;
_214 = _155;
float3 _127 = (scene._m0[gl_InstanceIndex].Model * float4(0.0, 0.0, 0.0, 1.0)).xyz;
float3 _132 = fast::normalize(Uniforms.cameraPosition.xyz - _127);
float3 _134 = fast::normalize(cross(float3(0.0, 1.0, 0.0), _132));
float4 _152 = float4((_127 + ((_134 * (-in.in_var_TEXCOORD0.x)) * scene._m0[gl_InstanceIndex].float0)) + ((cross(_132, _134) * in.in_var_TEXCOORD0.y) * scene._m0[gl_InstanceIndex].float0), 1.0);
_207 = _152.xyz;
_208 = _132;
_209 = float3(0.0, 0.0, 1.0);
_210 = Uniforms.ViewProjection * _152;
_211 = _152;
}
else
{
float4 _162 = scene._m0[gl_InstanceIndex].Model * _116;
float4x4 _197 = float4x4(float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][0], scene._m0[gl_InstanceIndex].Model[1][0], scene._m0[gl_InstanceIndex].Model[2][0])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][1], scene._m0[gl_InstanceIndex].Model[1][1], scene._m0[gl_InstanceIndex].Model[2][1])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][2], scene._m0[gl_InstanceIndex].Model[1][2], scene._m0[gl_InstanceIndex].Model[2][2])), 0.0), float4(0.0, 0.0, 0.0, 1.0));
float4 _201 = float4(in.in_var_TEXCOORD1, 1.0);
_210 = _162.xyz;
_211 = fast::normalize(_201 * _197).xyz;
_212 = (_201 * (_197 * transpose(Uniforms.NoTranslateView))).xyz;
_213 = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _116);
_214 = _162;
float4 _159 = scene._m0[gl_InstanceIndex].Model * _115;
float4x4 _194 = float4x4(float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][0], scene._m0[gl_InstanceIndex].Model[1][0], scene._m0[gl_InstanceIndex].Model[2][0])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][1], scene._m0[gl_InstanceIndex].Model[1][1], scene._m0[gl_InstanceIndex].Model[2][1])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][2], scene._m0[gl_InstanceIndex].Model[1][2], scene._m0[gl_InstanceIndex].Model[2][2])), 0.0), float4(0.0, 0.0, 0.0, 1.0));
float4 _198 = float4(in.in_var_TEXCOORD1, 1.0);
_207 = _159.xyz;
_208 = fast::normalize(_198 * _194).xyz;
_209 = (_198 * (_194 * transpose(Uniforms.NoTranslateView))).xyz;
_210 = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _115);
_211 = _159;
}
out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3;
out.out_var_TEXCOORD1 = _210;
out.out_var_TEXCOORD2 = _211;
out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _214;
out.out_var_TEXCOORD1 = _207;
out.out_var_TEXCOORD2 = _208;
out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _211;
out.out_var_TEXCOORD4 = gl_InstanceIndex;
out.out_var_TEXCOORD5 = _212;
out.gl_Position = _213;
out.out_var_TEXCOORD5 = _209;
out.gl_Position = _210;
return out;
}

View File

@ -99,8 +99,10 @@ pub const ExternGameObject = struct {
pub fn particleDebug(self: *@This()) void {
if (ig.begin("particleDebugger", null, .{})) {
var buffer: [256]u8 = undefined;
ig.textFmt("active particles: {d}", .{rend.context().particleRenderer.lastParticleCount}) catch unreachable;
for (rend.ParticleEmitter.BaseContainer.dense.items, 0..) |*emitter, i| {
ig.textFmt("emitter {d}", .{emitter.sparseIndex.index}) catch {};
ig.sameLine(0, 10);
if (ig.smallButton(std.fmt.bufPrintZ(&buffer, "edit##{d}", .{i}) catch unreachable)) {
self.editParticle = emitter.value.entity;
}
@ -142,6 +144,20 @@ pub const ExternGameObject = struct {
_ = ig.inputInt("maxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{});
_ = ig.checkbox("showDebug", &emitter._showDebug);
_ = ig.checkbox("useLocalScene", &emitter.useLocalScene);
_ = ig.checkbox("billboard", &emitter.billboard);
if (ig.smallButton("alive")) {
emitter.state = .alive;
}
ig.sameLine(0, 10);
if (ig.smallButton("kill")) {
emitter.state = .dead;
}
ig.sameLine(0, 10);
if (ig.smallButton("pause")) {
emitter.state = .paused;
}
}
ig.end();
}