Compare commits

...

3 Commits
ramen ... main

Author SHA1 Message Date
mars f5f5ecb2e5 Make README slightly more professional 2023-03-23 17:37:48 -04:00
mars 3f9683c4e3 Remove outdated Bevy info from README 2023-03-23 17:28:40 -04:00
mars 17635f056e Update wgpu 2022-09-17 09:34:52 -06:00
14 changed files with 67 additions and 74 deletions

View File

@ -23,7 +23,7 @@ slab = "^0.4"
smallmap = "^1.0"
smallvec = "^1.0"
strum = { version = "0.24", features = ["derive"] }
wgpu = "^0.12"
wgpu = "^0.13"
winit = "0.26"
[dependencies.legion]
@ -31,7 +31,7 @@ version = "^0.4"
optional = true
[dependencies.naga]
version = "0.8.5"
version = "0.9"
features = ["wgsl-in", "glsl-in", "wgsl-out", "serialize", "deserialize"]
[[bin]]

View File

@ -7,7 +7,7 @@
> A repulsive reaper of all of human consciousness -- but mostly SIGGRAPH presentations.
> H.R Giger's irreconcilable reality... if H.R. Giger was a computer programmer.
Cyborg is a free-form rendering engine that we mash whatever we feel like into.
Cyborg is an experimental, GPU-driven rendering engine using Rust and wgpu.
It's a test bed for all sorts of modern rendering technology. Our goal is to take
techniques and features from modern game engines and reimplement them on our own, for
the sake of education, performance, and reusability. We wanna *make shit work.*
@ -16,16 +16,15 @@ We also want to give artists a playground for generating all sorts of unique
3D visuals -- custom shaders, procedurally generated meshes and textures,
and a focus on *interesting* visuals.
Realism is a non-goal!
Make shrooms obsolete.
Go wild.
Modularity and reusability are important. We wanna be able to unplug certain
Modularity and reusability are important. We want to be able to unplug certain
parts of the rendering pipeline, upgrade them, fix them, document them, commit
them, tag them, etc., then stick them back in in a different place to end up
with a different resulting image.
Cyborg is licensed under the GPL-3.0. Yes, this does mean that Bevy games using
Cyborg will be required to make their source code public. But it also means that
Cyborg is licensed under the GPL-3.0. Yes, this does mean that any software using
Cyborg will be required to make its source code public. But it also means that
new visuals added to Cyborg will become available to all other developers and
artists to use. Hopefully, this will expand the collective knowledge of how different
rendering effects work, and decrease the pressure on graphics programmers to
@ -37,10 +36,3 @@ gathered from countless programmers and individual projects.
> Resistance is futile.
>
> -- The Borg
Cyborg is based on [Bevy](https://bevyengine.org/), a "refreshingly simple"
game engine written in Rust. Bevy provides a lot of useful utilities like
ECS-based data parallelization and a modular plugin system. Cyborg is integrated
into the rest of the Bevy ecosystem, and can also work as a replacement Bevy's
provided rendering engine, giving Bevy games GPU-powered, procedurally-generated
content and access to modern rendering optimizations.

View File

@ -7,16 +7,16 @@ edition = "2021"
bytemuck = "^1.0"
crossbeam-channel = "^0.5"
cyborg = { path = "../", features = ["legion"] }
egui = "0.17.0"
egui-winit = "0.17.0"
egui_wgpu_backend = "0.17.0"
egui = "0.18"
egui-winit = "0.18.0"
egui_wgpu_backend = "0.18.0"
glam = { version = "0.20", features = ["serde"] }
gltf = { version = "1.0", features = ["utils"] }
legion = "^0.4"
parking_lot = "^0.11"
pollster = "0.2"
puffin = "^0.13"
puffin_egui = "0.14.0"
puffin_egui = "0.16.0"
rfd = "^0.8"
stl = "0.2.1"

View File

@ -60,10 +60,10 @@ impl Application {
.unwrap();
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
format: *surface.get_supported_formats(&adapter).first().unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Mailbox,
present_mode: wgpu::PresentMode::Fifo,
};
surface.configure(&device, &config);

View File

@ -1,30 +1,30 @@
struct CameraUniform {
eye: vec4<f32>;
vp: mat4x4<f32>;
eye: vec4<f32>,
vp: mat4x4<f32>,
};
struct VertexInput {
[[location(0)]] position: vec3<f32>;
[[location(1)]] tan_frame: u32;
@location(0) position: vec3<f32>,
@location(1) tan_frame: u32,
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] position: vec3<f32>;
[[location(1)]] color: vec3<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) position: vec3<f32>,
@location(1) color: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> camera: CameraUniform;
fn random(seed: u32, salt: f32) -> f32 {
return abs(sin((f32(seed & u32(0x11111)) * 0.7071 + salt) * 78.233));
}
[[stage(vertex)]]
@vertex
fn vs_main(
[[builtin(instance_index)]] mesh_idx: u32,
[[builtin(vertex_index)]] vertex_idx: u32,
@builtin(instance_index) mesh_idx: u32,
@builtin(vertex_index) vertex_idx: u32,
vertex: VertexInput,
) -> VertexOutput {
let world_pos = vertex.position;
@ -38,9 +38,9 @@ fn vs_main(
return out;
}
[[stage(fragment)]]
@fragment
fn fs_main(
frag: VertexOutput,
) -> [[location(0)]] vec4<f32> {
) -> @location(0) vec4<f32> {
return vec4<f32>(frag.color, 1.0);
}

View File

@ -2,32 +2,33 @@
#include skin.wgsl
struct SkinningUniform {
transform: mat4x4<f32>;
src_offset: u32;
dst_offset: u32;
count: u32;
transform: mat4x4<f32>,
src_offset: u32,
dst_offset: u32,
count: u32,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<storage,read> skinning_ubo: SkinningUniform;
[[group(0), binding(1)]]
@group(0) @binding(1)
var<storage,write> dst_vertices: SkinnedVertexArray;
[[group(0), binding(2)]]
@group(0) @binding(2)
var<storage,read> src_vertices: SkinnedVertexArray;
[[stage(compute), workgroup_size(64)]]
@compute
@workgroup_size(64)
fn cs_main(
[[builtin(global_invocation_id)]] global_invocation_id: vec3<u32>,
@builtin(global_invocation_id) global_invocation_id: vec3<u32>,
) {
let vertex_index = global_invocation_id.x;
if (vertex_index >= skinning_ubo.count) {
return;
}
let src_index = skinning_ubo.src_offset + vertex_index;
let dst_index = skinning_ubo.dst_offset + vertex_index;
let src_index = skinning_ubo.src_offset + vertex_index;
let dst_index = skinning_ubo.dst_offset + vertex_index;
let ptf = src_vertices.data[src_index].ptf;
let position = ptf.xyz;

View File

@ -1,6 +1,6 @@
struct TangentFrame {
normal: vec3<f32>;
tangent: vec3<f32>;
normal: vec3<f32>,
tangent: vec3<f32>
};
// https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/?like_comment=12

View File

@ -1,7 +1,7 @@
struct SkinnedVertex {
ptf: vec4<f32>;
ptf: vec4<f32>
};
struct SkinnedVertexArray {
data: array<SkinnedVertex>;
data: array<SkinnedVertex>
};

View File

@ -268,14 +268,14 @@ impl Renderer {
let mut rp = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target_views.output,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
store: true,
},
}],
})],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: target_views.depth,
depth_ops: Some(wgpu::Operations {

View File

@ -24,7 +24,7 @@ impl DebugPass {
target_info: ViewportInfo,
) -> Self {
// TODO hook into ShaderStore system
let shader = device.create_shader_module(&wgpu::include_wgsl!("debug_shader.wgsl"));
let shader = device.create_shader_module(wgpu::include_wgsl!("debug_shader.wgsl"));
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("DebugPass Pipeline Layout"),
@ -43,11 +43,11 @@ impl DebugPass {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
targets: &[Some(wgpu::ColorTargetState {
format: target_info.output_format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
}],
})],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::LineList,
@ -130,7 +130,7 @@ impl RenderPass for DebugPass {
self.device
.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
label: Some("DebugPass Render Bundle"),
color_formats: &[self.target_info.output_format],
color_formats: &[Some(self.target_info.output_format)],
depth_stencil: Some(wgpu::RenderBundleDepthStencil {
format: self.target_info.depth_format,
depth_read_only: false, // TODO optimize?

View File

@ -1,26 +1,26 @@
struct CameraUniform {
eye: vec4<f32>;
vp: mat4x4<f32>;
eye: vec4<f32>,
vp: mat4x4<f32>,
};
struct VertexInput {
[[location(0)]] position: vec3<f32>;
[[location(1)]] color: vec3<f32>;
@location(0) position: vec3<f32>,
@location(1) color: vec3<f32>
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] position: vec3<f32>;
[[location(1)]] color: vec3<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) position: vec3<f32>,
@location(1) color: vec3<f32>
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> camera: CameraUniform;
[[stage(vertex)]]
@vertex
fn vs_main(
[[builtin(instance_index)]] mesh_idx: u32,
[[builtin(vertex_index)]] vertex_idx: u32,
@builtin(instance_index) mesh_idx: u32,
@builtin(vertex_index) vertex_idx: u32,
vertex: VertexInput,
) -> VertexOutput {
let world_pos = vertex.position;
@ -32,9 +32,9 @@ fn vs_main(
return out;
}
[[stage(fragment)]]
@fragment
fn fs_main(
frag: VertexOutput,
) -> [[location(0)]] vec4<f32> {
) -> @location(0) vec4<f32> {
return vec4<f32>(frag.color, 1.0);
}

View File

@ -142,11 +142,11 @@ impl MeshPass {
let shader = shader_info.store.get(&shader_info.forward).unwrap();
let targets = &[wgpu::ColorTargetState {
let targets = &[Some(wgpu::ColorTargetState {
format: target_info.output_format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
}];
})];
let mut pipeline_desc = wgpu::RenderPipelineDescriptor {
label: Some("Opaque MeshPass Pipeline"),
@ -449,7 +449,7 @@ impl RenderPass for MeshPass {
mesh.vertex_count / 64 + 1
};
cmds.dispatch(workgroup_num as u32, 1, 1);
cmds.dispatch_workgroups(workgroup_num as u32, 1, 1);
}
}
}
@ -465,7 +465,7 @@ impl RenderPass for MeshPass {
self.device
.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
label: Some("Opaque Pass Render Bundle"),
color_formats: &[self.target_info.output_format],
color_formats: &[Some(self.target_info.output_format)],
depth_stencil: Some(wgpu::RenderBundleDepthStencil {
format: self.target_info.depth_format,
depth_read_only: false, // TODO optimize?

View File

@ -83,7 +83,7 @@ impl ShaderStore {
fn load_wgsl(&self, wgsl_source: String) -> Result<wgpu::ShaderModule, ShaderError> {
let shader = self
.device
.create_shader_module(&wgpu::ShaderModuleDescriptor {
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Owned(wgsl_source)),
});

View File

@ -58,10 +58,10 @@ impl WinitViewport {
.unwrap();
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
format: *surface.get_supported_formats(&adapter).first().unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Mailbox,
present_mode: wgpu::PresentMode::Fifo,
};
surface.configure(&device, &config);