added example smoke and particle emitter

This commit is contained in:
peterino2 2025-09-21 00:51:04 -07:00
parent bba99d4d91
commit 2046b1d7c8
22 changed files with 492 additions and 190 deletions

View File

@ -21,16 +21,7 @@ cbuffer Uniforms : register(b0, space3)
float time;
};
struct Scene
{
float4x4 Model;
uint textureMode; // 0 = regular triple,
// 0x10 = video yuv,
uint pad0; // 0 = regular triple,
uint pad1; // 0 = regular triple,
uint pad2; // 0 = regular triple,
};
#include "sceneShared.hlsli"
StructuredBuffer<Scene> scene: register(t4, space2);
@ -247,7 +238,7 @@ PixelOutput main(
if((texMode & 0x2) > 0) // full bright no lighting bit
{
c2 = col * 2.0;
c2 = pow(col, 1.0/2.2);
}
// float4 rv = float4(pow(c2, 1.0 / 2.2), alpha);

View File

@ -62,18 +62,18 @@
"offset" : 64
},
{
"name" : "pad0",
"type" : "uint",
"name" : "animation",
"type" : "int",
"offset" : 68
},
{
"name" : "pad1",
"name" : "flags",
"type" : "uint",
"offset" : 72
},
{
"name" : "pad2",
"type" : "uint",
"name" : "float0",
"type" : "float",
"offset" : 76
}
]

View File

@ -5,42 +5,8 @@ uint getCharFromUintArray(uint color, uint index)
return uint((color >> 8 * index) & 0xFF);
}
struct Input
{
float3 Position : TEXCOORD0;
float3 Normal : TEXCOORD1;
float4 Color : TEXCOORD2;
float2 UV : TEXCOORD3;
uint Bones : TEXCOORD4;
uint weights : TEXCOORD5;
uint Instance : SV_InstanceID;
};
struct Output
{
float2 TexCoord : TEXCOORD0;
float3 WorldPos : TEXCOORD1;
float3 Normal: TEXCOORD2;
float4 DirectionalShadowFragPos: TEXCOORD3;
uint Instance: TEXCOORD4;
float3 ScreenNormal: TEXCOORD5;
float4 Position : SV_Position;
};
struct Scene
{
float4x4 Model;
uint textureMode; // 0 = regular triple,
// 0x10 = video yuv,
int animation; // -1 means no animation, any non-zero value means an index into the animationBuffer
uint flags; // 0 -> 0: always in front
// 1 -> 1: useAltCamera
uint pad2;
};
#include "vertexShared.hlsli"
#include "sceneShared.hlsli"
StructuredBuffer<Scene> scene: register(t0, space0);
@ -55,7 +21,9 @@ cbuffer Uniforms : register(b0, space1)
{
float4x4 ViewProjection;
float4x4 NoTranslateView;
float4x4 ViewTransform;
float4x4 ShadowMapProjection;
float4 cameraPosition;
float time;
};
@ -110,23 +78,56 @@ Output main(Input input)
// pos.x += 0.2 * sin(time * 0.5 ) * pos.y * 0.5;
// pos.y += 0.2 * cos(time * 0.5 ) * pos.z * 0.5;
int billboard = scene[input.Instance].flags & 0x4;
float4 WorldPos;
if(billboard > 0)
{
float3 billboardPosition = mul(scene[input.Instance].Model, float4(0,0,0,1)).xyz;
float3 toCamera = normalize(billboardPosition - cameraPosition.xyz);
float3 up = float3(0,1,0);
float3 right = normalize(cross(up, toCamera));
up = cross(toCamera, right);
float d = length(cameraPosition.xyz - billboardPosition);
float perspectiveScale = d * 0.1f; // 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);
WorldPos = float4(wp, 1.0);
output.Position = mul(ViewProjection, WorldPos);
output.WorldPos = WorldPos.xyz;
output.Normal = toCamera;
output.ScreenNormal = float3(0, 0, 1);
}
else
{
// todo. maybe all world position values should be
// transformed into screen space
WorldPos = mul(scene[input.Instance].Model, pos);
output.Position = mul(ViewProjection, mul(scene[input.Instance].Model, pos));
output.WorldPos = WorldPos.xyz;
float4x4 noTranslate = ExtractRotation(scene[input.Instance].Model);
output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz;
float4x4 noTranslateScreen = mul(NoTranslateView, noTranslate);
output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz;
// output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz;
// output.ScreenNormal = input.Normal;
// output.ScreenNormal = float4(input.Normal, 1.0).xyz;
}
// todo. maybe all world position values should be
// transformed into screen space
float4 WorldPos = mul(scene[input.Instance].Model, pos);
output.Position = mul(ViewProjection, mul(scene[input.Instance].Model, pos));
output.WorldPos = WorldPos.xyz;
float4x4 noTranslate = ExtractRotation(scene[input.Instance].Model);
output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz;
float4x4 noTranslateScreen = mul(NoTranslateView, noTranslate);
output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz;
// output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz;
// output.ScreenNormal = input.Normal;
// output.ScreenNormal = float4(input.Normal, 1.0).xyz;
output.DirectionalShadowFragPos = mul(ShadowMapProjection, WorldPos);
output.Instance = input.Instance;

View File

@ -32,8 +32,8 @@
"offset" : 72
},
{
"name" : "pad2",
"type" : "uint",
"name" : "float0",
"type" : "float",
"offset" : 76
}
]
@ -102,16 +102,28 @@
"row_major" : true
},
{
"name" : "ShadowMapProjection",
"name" : "ViewTransform",
"type" : "mat4",
"offset" : 128,
"matrix_stride" : 16,
"row_major" : true
},
{
"name" : "ShadowMapProjection",
"type" : "mat4",
"offset" : 192,
"matrix_stride" : 16,
"row_major" : true
},
{
"name" : "cameraPosition",
"type" : "vec4",
"offset" : 256
},
{
"name" : "time",
"type" : "float",
"offset" : 192
"offset" : 272
}
]
}
@ -197,7 +209,7 @@
{
"type" : "_22",
"name" : "type.Uniforms",
"block_size" : 196,
"block_size" : 276,
"set" : 1,
"binding" : 0
}

View File

@ -0,0 +1,26 @@
struct Scene
{
float4x4 Model;
uint textureMode; // 0 = regular triple,
// 0x10 = video yuv,
// bit 0 == srgb correction
// bit 1 == fullbright
// bit 2 = reserved
// bit 3 = reserved
// bit 4 - 7 = color space:
// 0 -> regular rgb
// 1 -> regular video yuv // used for decoding video files
int animation; // -1 means no animation, any non-zero value means an index into the animationBuffer
uint flags; // 0 -> 0: always in front
// 1 -> 1: useAltCamera
// 2 -> 2: billboard (& 0x4)
float float0; // uses:
// in billboard mode: this represents the size
};
uint isBillboard(Scene s)
{
return s.flags & 0x4;
}

View File

@ -0,0 +1,23 @@
struct Input
{
float3 Position : TEXCOORD0;
float3 Normal : TEXCOORD1;
float4 Color : TEXCOORD2;
float2 UV : TEXCOORD3;
uint Bones : TEXCOORD4;
uint weights : TEXCOORD5;
uint Instance : SV_InstanceID;
};
struct Output
{
float2 TexCoord : TEXCOORD0;
float3 WorldPos : TEXCOORD1;
float3 Normal: TEXCOORD2;
float4 DirectionalShadowFragPos: TEXCOORD3;
uint Instance: TEXCOORD4;
float3 ScreenNormal: TEXCOORD5;
float4 Position : SV_Position;
};

View File

@ -74,6 +74,31 @@ pub const Rotationals = struct {
pub const RenderInfo = struct {
meshIndex: u32 = 0,
textureIndex: u32 = 0,
var quad_mesh: ?rend.IndexedMesh = null;
var default_texture: ?*rend.Texture = null;
pub fn getMesh(self: @This(), emitter: *const ParticleEmitter) rend.IndexedMesh {
if (emitter.mesh.items.len == 0) {
if (quad_mesh == null) {
quad_mesh = rend.getMesh("m_screenPlane").?;
}
return quad_mesh.?;
}
return emitter.mesh.items[self.meshIndex];
}
pub fn getTexture(self: @This(), emitter: *const ParticleEmitter) *rend.Texture {
if (emitter.texture.items.len == 0) {
if (default_texture == null) {
default_texture = rend.getTexture("t_white").?;
}
return default_texture.?;
}
return emitter.texture.items[self.textureIndex];
}
};
pub const ParticleEmitter = struct {
@ -85,11 +110,12 @@ pub const ParticleEmitter = struct {
life: std.ArrayListUnmanaged(Life) = .{},
particlesPVA: std.ArrayListUnmanaged(ParticlePVA) = .{},
finals: std.ArrayListUnmanaged(core.Mat) = .{},
renderInfo: std.ArrayListUnmanaged(RenderInfo) = .{},
size: std.ArrayListUnmanaged(f32) = .{},
particleAcceleration: ParticleRandRangef = .{ .min = 0.0, .max = 0.0 },
particleVelocity: ParticleRandRangef = .{ .min = 8, .max = 10 },
particleLife: ParticleRandRangef = .{ .min = 2, .max = 2 },
particleSizeSpawn: ParticleRandRangef = .{ .min = 0.8, .max = 1.0 },
spawnRate: ParticleRandRangef = .{ .min = 10, .max = 10 },
nextSpawn: f64 = 0.0,
@ -106,10 +132,10 @@ pub const ParticleEmitter = struct {
// and only position and scale will be used to render the particle.
// an empty list means that this will use quad_mesh
mesh: std.ArrayListUnmanaged(rend.IndexedMesh) = .{},
mesh: rend.IndexedMesh = undefined,
// empty list means will use t_white
texture: std.ArrayListUnmanaged(*rend.Texture) = .{},
texture: *rend.Texture = undefined,
emitterLife: f64 = 0.0, // 0.0 means this emitter lives forever.
emitterMaxLife: f64 = 0.0,
@ -173,7 +199,7 @@ pub const ParticleEmitter = struct {
_ = self.life.swapRemove(i);
_ = self.particlesPVA.swapRemove(i);
_ = self.finals.swapRemove(i);
_ = self.renderInfo.swapRemove(i);
_ = self.size.swapRemove(i);
}
pub fn updateSpawn(self: *@This(), dt: f64) void {
@ -235,12 +261,9 @@ pub const ParticleEmitter = struct {
const life = self.particleLife.getRange();
try self.life.append(gParticleAllocator, .{ .current = life, .max = life });
try self.particlesPVA.append(gParticleAllocator, pva);
// renderinfo not used rn
try self.renderInfo.append(gParticleAllocator, .{});
try self.finals.append(gParticleAllocator, std.mem.zeroes(core.Mat));
try self.size.append(gParticleAllocator, self.particleSizeSpawn.getRange());
}
fn updateLife(self: *@This(), dt: f64) void {
@ -264,12 +287,30 @@ pub const ParticleEmitter = struct {
self.updatePVA(dt);
self.updateParticleLife(dt);
self.updateLife(dt);
self.updateFinals();
}
pub fn updateFinals(self: *@This()) void {
const scene = self.entity.fetch(core.Scene).?;
const transform = scene.getPosRot().toTransform();
for (self.particlesPVA.items, 0..) |pva, i| {
const p = core.zm.translationV(pva.position);
self.finals.items[i] = core.zm.mul(p, transform);
}
}
var t_whiteName: core.Name = core.DefineName("t_white");
var m_quad: core.Name = core.DefineName("m_screenPlane");
pub fn initECS(self: *@This(), handle: core.SetHandle) void {
// get the mesh component
self.entity = core.Entity{ .handle = handle };
self.texture = rend.getTexture(&t_whiteName).?;
self.mesh = rend.getMeshByName(&m_quad).?;
if (self.entity.fetch(core.Scene)) |scene| {
_ = scene;
} else {

View File

@ -0,0 +1,137 @@
allocator: std.mem.Allocator,
ssboScene: *gpu.GPUBuffer = undefined,
ssboSceneUpload: *gpu.GPUTransferBuffer = undefined,
spans: std.ArrayListUnmanaged(core.Span) = .{},
renderInfo: std.ArrayListUnmanaged(SgpuParticleRenderInfo) = .{},
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.ParticleRenderer");
const SgpuParticleRenderInfo = struct {
mesh: rend.IndexedMesh,
texture: *rend.Texture,
};
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
};
const device = rend.context().device;
self.ssboScene = device.createGPUBuffer(&.{
.usage = .{
.bufferusageGraphicsStorageRead = true,
.bufferusageVertex = true,
},
.size = MaxParticleCount * @sizeOf(meshes_vert.Scene),
.props = 0,
});
self.ssboSceneUpload = device.createGPUTransferBuffer(&.{
.usage = .transferbufferusageUpload,
.size = MaxParticleCount * @sizeOf(meshes_vert.Scene),
.props = 0,
});
return self;
}
pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
self.spans.clearRetainingCapacity();
self.renderInfo.clearRetainingCapacity();
var offset: usize = 0;
const device = rend.context().device;
const uploadMapped: [*]meshes_vert.Scene = @ptrCast(@alignCast(device.mapGPUTransferBuffer(self.ssboSceneUpload, true)));
defer device.unmapGPUTransferBuffer(self.ssboSceneUpload);
for (rend.ParticleEmitter.BaseContainer.dense.items) |*c| {
const emitter = &c.value;
for (emitter.finals.items, 0..) |final, i| {
const size = emitter.size.items[i];
uploadMapped[i + offset] = .{
.Model = final,
.textureMode = 0x2, //0x2, // default 0x2 is fullbright
.animation = -1,
.float0 = size,
.flags = 0, //0x4,
};
}
try self.renderInfo.append(self.allocator, .{ .texture = emitter.texture, .mesh = emitter.mesh });
try self.spans.append(self.allocator, .{ .start = @intCast(offset), .size = @intCast(emitter.finals.items.len) });
offset += emitter.finals.items.len;
}
if (self.renderInfo.items.len == 0)
return;
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.ssboSceneUpload, .offset = 0 }, &.{
.buffer = self.ssboScene,
.offset = 0,
.size = @intCast(offset * @sizeOf(meshes_vert.Scene)),
}, true);
}
pub fn postMesh(p: *anyopaque, cmd: *gpu.GPUCommandBuffer, renderpass: *gpu.GPURenderPass) void {
const self: *@This() = @ptrCast(@alignCast(p));
_ = cmd;
renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 1);
renderpass.bindGPUFragmentStorageBuffers(0, &self.ssboScene, 1);
const ctx = rend.context();
for (self.spans.items, 0..) |span, i| {
const ri = self.renderInfo.items[i];
const mesh = ri.mesh;
const _t = ri.texture;
var sampler: *gpu.GPUSampler = undefined;
switch (_t.samplerMode) {
.blocky => {
sampler = ctx.blockySampler;
},
.linear => {
sampler = ctx.linearSampler;
},
}
renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 0);
renderpass.bindGPUFragmentSamplers(0, &.{ .texture = _t.texture, .sampler = sampler }, 1);
renderpass.drawGPUIndexedPrimitives(mesh.index.size, span.size, mesh.index.start, @intCast(mesh.vertex.start), @intCast(span.start));
}
}
pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void {
_ = self;
_ = device;
}
pub fn destroy(self: *@This()) void {
self.spans.deinit(self.allocator);
self.renderInfo.deinit(self.allocator);
self.allocator.destroy(self);
}
const MaxParticleCount = 1_000_000;
const assets = @import("assets");
const core = @import("core");
const std = @import("std");
const rend = @import("../rend.zig");
const renderer = rend.renderer;
const particles = rend.particles;
const sdl3 = @import("sdl3");
const gpu = sdl3.gpu;
const meshes_vert = @import("meshes.vert");

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

View File

@ -86,6 +86,7 @@ pub const Renderer = struct {
lightPower: f32 = 4.0,
particleRenderer: *ParticleRenderer = undefined,
ssaoSystem: *SsaoSystem = undefined,
positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float,
normalTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float,
@ -174,6 +175,7 @@ pub const Renderer = struct {
try self.createSamplers();
_ = try core.fs().installFileBytesMount("embedded:texture_sample.png", @constCast(&texture_sample_png), true);
_ = try core.fs().installFileBytesMount("embedded:texture_white.png", @constCast(&texture_white_png), true);
_ = try core.fs().installFileBytesMount("embedded:primitive_box.obj", @constCast(&primitive_box_obj), true);
// todo... make these embedded
@ -185,6 +187,14 @@ pub const Renderer = struct {
),
);
try assets.load(
assets.MakeImportRefOptions(
"Texture",
"t_white",
.{ .path = "embedded:texture_white.png" },
),
);
try assets.load(
assets.MakeImportRefOptions(
"Mesh",
@ -194,11 +204,13 @@ pub const Renderer = struct {
);
var defaultTextureName = core.MakeName("t_default");
self.defaultTexture = getTexture(&defaultTextureName).?;
self.debugDrawSys = try self.createRendererEngineObject(DebugDrawSystem);
try self.createDirectionalShadowsPipeline();
self.skyboxSystem = try self.createRendererEngineObject(SkyboxSystem);
self.particleRenderer = try self.createRendererEngineObject(ParticleRenderer);
self.debugDrawSys = try self.createRendererEngineObject(DebugDrawSystem);
_ = try core.fs().installFileBytesMount("embedded:plane.obj", @constCast(&plane_obj), true);
_ = try core.fs().installFileBytesMount("embedded:screenPlane.obj", @constCast(&screenPlane_obj), true);
@ -352,9 +364,7 @@ pub const Renderer = struct {
pub fn createRendererObject(self: *@This(), T: type) !*T {
const object = try T.create(self.device, self.allocator, .{});
try self.registerRendererObject(T, object);
try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy });
return object;
@ -501,7 +511,16 @@ pub const Renderer = struct {
pci.target_info.color_target_descriptions = &[4]gpu.GPUColorTargetDescription{
.{
.format = self.hdrTextureFormat,
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
//.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
.blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{
.alpha_blend_op = .blendopAdd,
.color_blend_op = .blendopAdd,
.src_color_blendfactor = .blendfactorSrcAlpha,
.dst_color_blendfactor = .blendfactorOneMinusSrcAlpha,
.src_alpha_blendfactor = .blendfactorSrcAlpha,
.dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha,
.enable_blend = true,
}),
},
.{
.format = self.hdrTextureFormat,
@ -559,7 +578,7 @@ pub const Renderer = struct {
});
}
pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) void {
const container = rend.MeshComponent.BaseContainer;
const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount);
{
@ -604,6 +623,8 @@ pub const Renderer = struct {
}
}
self.particleRenderer.uploadSsbos(copyPass) catch unreachable;
if (uploadCount == 0)
return;
@ -672,6 +693,7 @@ pub const Renderer = struct {
var data = std.mem.zeroes([@sizeOf(meshes_vert.Uniforms) / 8 + 1]usize);
const ptr: *meshes_vert.Uniforms = @ptrCast(@alignCast(&data));
if (self.activeCamera) |camera| {
ptr.ViewTransform = @bitCast(camera.transform);
ptr.ViewProjection = @bitCast(camera.final);
ptr.NoTranslateView = @bitCast(camera.noTranslate);
}
@ -727,7 +749,7 @@ pub const Renderer = struct {
// .size = 4 * 12,
// }, true);
try self.uploadSSBOs(copyPass);
self.uploadSSBOs(copyPass);
for (self.uploads.items) |upload| {
upload.func(upload.ptr, copyPass);
@ -936,6 +958,7 @@ pub const Renderer = struct {
for (self.postMesh.items) |interface| {
interface.func(interface.ptr, cmd, renderpass);
}
renderpass.endGPURenderPass();
self.state.pass = null;
}
@ -1127,6 +1150,7 @@ pub const GPUTextureType = gpu.GPUTexture;
const plane_obj align(8) = @embedFile("embedded/plane.obj").*;
const screenPlane_obj align(8) = @embedFile("embedded/screenPlane.obj").*;
const texture_sample_png align(8) = @embedFile("embedded/texture_sample.png").*;
const texture_white_png align(8) = @embedFile("embedded/texture_white.png").*;
const primitive_box_obj align(8) = @embedFile("embedded/primitive_box.obj").*;
const tracy = core.tracy;
@ -1134,3 +1158,4 @@ const animationSystem = rend.animationSystem;
const builtin = @import("builtin");
pub const SsaoSystem = @import("ssao.zig");
pub const ParticleRenderer = @import("ParticleRenderer.zig");

View File

@ -196,7 +196,16 @@ pub fn createPipeline(self: *@This()) !void {
pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{
.{
.format = self.ssaoOutputFormat,
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
//.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
.blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{
.alpha_blend_op = .blendopAdd,
.color_blend_op = .blendopAdd,
.src_color_blendfactor = .blendfactorSrcAlpha,
.dst_color_blendfactor = .blendfactorOneMinusSrcAlpha,
.src_alpha_blendfactor = .blendfactorSrcAlpha,
.dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha,
.enable_blend = true,
}),
},
};

View File

@ -18,9 +18,9 @@ struct Scene
{
float4x4 Model;
uint textureMode;
uint pad0;
uint pad1;
uint pad2;
int animation;
uint flags;
float float0;
};
struct type_StructuredBuffer_Scene
@ -28,8 +28,8 @@ struct type_StructuredBuffer_Scene
Scene _m0[1];
};
constant float4 _90 = {};
constant float3 _92 = {};
constant float4 _92 = {};
constant float3 _94 = {};
struct main0_out
{
@ -52,145 +52,145 @@ struct main0_in
fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], const device type_StructuredBuffer_Scene& scene [[buffer(1)]], texture2d<float> Texture0 [[texture(0)]], texture2d<float> Texture1 [[texture(1)]], texture2d<float> Texture2 [[texture(2)]], texture2d<float> DirectionalShadowDepthMap [[texture(3)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]], sampler Sampler2 [[sampler(2)]], sampler DirectionalShadowSampler [[sampler(3)]])
{
main0_out out = {};
int _102 = int(scene._m0[in.in_var_TEXCOORD4].textureMode);
int _103 = _102 & 240;
float4 _137;
if (_103 == 16)
int _104 = int(scene._m0[in.in_var_TEXCOORD4].textureMode);
int _105 = _104 & 240;
float4 _139;
if (_105 == 16)
{
float3 _124 = float3(Texture0.sample(Sampler0, in.in_var_TEXCOORD0).x, Texture1.sample(Sampler1, in.in_var_TEXCOORD0).x, Texture2.sample(Sampler2, in.in_var_TEXCOORD0).x) + float3(-0.0625, -0.5, -0.5);
_137 = float4(dot(_124, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_124, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_124, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0);
float3 _126 = float3(Texture0.sample(Sampler0, in.in_var_TEXCOORD0).x, Texture1.sample(Sampler1, in.in_var_TEXCOORD0).x, Texture2.sample(Sampler2, in.in_var_TEXCOORD0).x) + float3(-0.0625, -0.5, -0.5);
_139 = float4(dot(_126, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_126, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_126, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0);
}
else
{
float4 _136;
if (_103 == 0)
float4 _138;
if (_105 == 0)
{
_136 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0);
_138 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0);
}
else
{
_136 = _90;
_138 = _92;
}
_137 = _136;
_139 = _138;
}
float4 _143;
if ((_102 & 1) == 1)
float4 _145;
if ((_104 & 1) == 1)
{
_143 = powr(_137, float4(2.2000000476837158203125));
_145 = powr(_139, float4(2.2000000476837158203125));
}
else
{
_143 = _137;
_145 = _139;
}
if (_143.w < 0.00999999977648258209228515625)
if (_145.w < 0.00999999977648258209228515625)
{
discard_fragment();
}
float3 _153 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower;
float3 _200;
float3 _155 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower;
float3 _202;
do
{
float3 _157 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1;
float _158 = length(_157);
float _159 = _158 * _158;
float _165;
if (_158 > 2.0)
float3 _159 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1;
float _160 = length(_159);
float _161 = _160 * _160;
float _167;
if (_160 > 2.0)
{
_165 = 0.5 / _159;
_167 = 0.5 / _161;
}
else
{
_165 = 1.0 / _159;
_167 = 1.0 / _161;
}
float _170;
if (_158 > 4.0)
float _172;
if (_160 > 4.0)
{
_170 = _165 * 0.5;
_172 = _167 * 0.5;
}
else
{
_170 = _165;
_172 = _167;
}
float _172 = (_158 > 15.0) ? 0.0 : _170;
float _174 = (_172 > 1.0) ? 1.0 : _172;
float _174 = (_160 > 15.0) ? 0.0 : _172;
float _176 = (_174 > 1.0) ? 1.0 : _174;
if (length(in.in_var_TEXCOORD2) < 0.100000001490116119384765625)
{
_200 = (in.in_var_TEXCOORD1 * _153) * _174;
_202 = (in.in_var_TEXCOORD1 * _155) * _176;
break;
}
float3 _181 = fast::normalize(_157);
_200 = ((_153 * precise::max(dot(_181, in.in_var_TEXCOORD2), 0.0)) * _174) + (((_153 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_181 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _174);
float3 _183 = fast::normalize(_159);
_202 = ((_155 * precise::max(dot(_183, in.in_var_TEXCOORD2), 0.0)) * _176) + (((_155 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_183 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _176);
break;
} while(false);
float3 _217 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5);
float3 _219;
_219.x = _217.x;
float2 _220 = _219.xy;
_220.y = -_217.y;
float _227;
int _230;
float3 _219 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5);
float3 _221;
_221.x = _219.x;
float2 _222 = _221.xy;
_222.y = -_219.y;
float _229;
int _232;
_227 = 0.0;
_230 = 0;
_232 = -2;
float _228;
int _231;
for (; _232 <= 2; _227 = _228, _230 = _231, _232++)
int _234;
_229 = 0.0;
_232 = 0;
_234 = -2;
float _230;
int _233;
for (; _234 <= 2; _229 = _230, _232 = _233, _234++)
{
_231 = _230;
_228 = _227;
for (int _241 = -2; _241 <= 2; )
_233 = _232;
_230 = _229;
for (int _243 = -2; _243 <= 2; )
{
_231++;
_228 += float((in.in_var_TEXCOORD3.z - 0.0030000000260770320892333984375) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_220 + float2(float(_241) * 0.000244140625, float(_232) * 0.000244140625))).x);
_241++;
_233++;
_230 += float((in.in_var_TEXCOORD3.z - 0.0030000000260770320892333984375) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_222 + float2(float(_243) * 0.000244140625, float(_234) * 0.000244140625))).x);
_243++;
continue;
}
}
float3 _270;
if ((_102 & 2) > 0)
float3 _272;
if ((_104 & 2) > 0)
{
_270 = _143.xyz * 2.0;
_272 = powr(_145.xyz, float3(0.4545454680919647216796875));
}
else
{
_270 = _143.xyz * ((float3(0.100000001490116119384765625) + _200) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_227 / float(_230)))));
_272 = _145.xyz * ((float3(0.100000001490116119384765625) + _202) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_229 / float(_232)))));
}
float4 _287;
if (_270.x > 1.0)
float4 _289;
if (_272.x > 1.0)
{
float4 _286 = float4(0.0, 0.0, 0.0, 1.0);
_286.x = _270.x;
_287 = _286;
float4 _288 = float4(0.0, 0.0, 0.0, 1.0);
_288.x = _272.x;
_289 = _288;
}
else
{
_287 = float4(0.0, 0.0, 0.0, 1.0);
_289 = float4(0.0, 0.0, 0.0, 1.0);
}
float4 _292;
if (_270.y > 1.0)
float4 _294;
if (_272.y > 1.0)
{
float4 _291 = _287;
_291.y = _270.y;
_292 = _291;
float4 _293 = _289;
_293.y = _272.y;
_294 = _293;
}
else
{
_292 = _287;
_294 = _289;
}
float4 _297;
if (_270.z > 1.0)
float4 _299;
if (_272.z > 1.0)
{
float4 _296 = _292;
_296.z = _270.z;
_297 = _296;
float4 _298 = _294;
_298.z = _272.z;
_299 = _298;
}
else
{
_297 = _292;
_299 = _294;
}
out.out_var_SV_Target0 = float4(_270, _143.w);
out.out_var_SV_Target1 = _297;
out.out_var_SV_Target0 = float4(_272, _145.w);
out.out_var_SV_Target1 = _299;
out.out_var_SV_Target2 = float4(in.in_var_TEXCOORD1, 1.0);
out.out_var_SV_Target3 = float4(in.in_var_TEXCOORD5, 1.0);
return out;

View File

@ -9,7 +9,7 @@ struct Scene
uint textureMode;
int animation;
uint flags;
uint pad2;
float float0;
};
struct type_StructuredBuffer_Scene
@ -31,7 +31,9 @@ struct type_Uniforms
{
float4x4 ViewProjection;
float4x4 NoTranslateView;
float4x4 ViewTransform;
float4x4 ShadowMapProjection;
float4 cameraPosition;
float time;
};
@ -58,35 +60,61 @@ 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 _103;
float3 _112;
if (scene._m0[gl_InstanceIndex].animation != (-1))
{
float3 _75;
_75 = float3(0.0);
for (int _78 = 0; _78 < 4; )
float3 _84;
_84 = float3(0.0);
for (int _87 = 0; _87 < 4; )
{
uint _84 = (8u * uint(_78)) & 31u;
_75 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _84) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _84) & 255u) * 0.0039215688593685626983642578125));
_78++;
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++;
continue;
}
_103 = _75;
_112 = _84;
}
else
{
_103 = in.in_var_TEXCOORD0;
_112 = in.in_var_TEXCOORD0;
}
float4 _116 = float4(_112, 1.0);
float3 _210;
float3 _211;
float3 _212;
float4 _213;
float4 _214;
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;
}
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 _107 = float4(_103, 1.0);
float4 _110 = scene._m0[gl_InstanceIndex].Model * _107;
float4x4 _145 = 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 _149 = float4(in.in_var_TEXCOORD1, 1.0);
out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3;
out.out_var_TEXCOORD1 = _110.xyz;
out.out_var_TEXCOORD2 = fast::normalize(_149 * _145).xyz;
out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _110;
out.out_var_TEXCOORD1 = _210;
out.out_var_TEXCOORD2 = _211;
out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _214;
out.out_var_TEXCOORD4 = gl_InstanceIndex;
out.out_var_TEXCOORD5 = (_149 * (_145 * transpose(Uniforms.NoTranslateView))).xyz;
out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _107);
out.out_var_TEXCOORD5 = _212;
out.gl_Position = _213;
return out;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

View File

@ -116,6 +116,7 @@ pub const ExternGameObject = struct {
displayRandRangeImgui("Acceleration", &emitter.particleAcceleration);
displayRandRangeImgui("Velocity", &emitter.particleVelocity);
displayRandRangeImgui("Life", &emitter.particleLife);
displayRandRangeImgui("Size", &emitter.particleSizeSpawn);
displayRandRangeImgui("spawnRate", &emitter.spawnRate);
if (emitter.gravity != null) {
@ -139,7 +140,8 @@ pub const ExternGameObject = struct {
editVector("gravity", &emitter.gravity.?);
}
_ = ig.inputInt("maaxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{});
_ = ig.inputInt("maxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{});
_ = ig.checkbox("showDebug", &emitter._showDebug);
}
ig.end();
}

View File

@ -68,6 +68,11 @@ const assetReferences = [_]assets.AssetImportReference{
"t_fox",
.{ .path = "gltf-samples/Fox/glTF/Texture.png" },
),
assets.MakeImportRefOptions(
"Texture",
"t_pixelSmoke",
.{ .path = "textures/PixelSmoke.png" },
),
assets.MakeImportRefOptions("Texture", "t_crate", .{
.path = "textures/Crate.png",
}),
@ -126,6 +131,8 @@ pub const ParticleObject = struct {
particle._showDebug = true;
particle.start();
particle.gravity = .{ .y = -9.8 };
var name = core.MakeName("t_pixelSmoke");
particle.texture = rend.getTexture(&name).?;
self.entity = e;