migrated windowless

pull/140/head
Ben Hansen 3 years ago
parent b4dd4654e4
commit 7094e5dd91

427
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,23 +0,0 @@
[package]
name = "instancing"
version = "0.1.0"
authors = ["Ben Hansen <bhbenjaminhansen@gmail.com>"]
edition = "2018"
[dependencies]
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
cgmath = "0.17"
env_logger = "0.7"
futures = "0.3"
image = "0.23"
log = "0.4"
tobj = "2.0"
wgpu = "0.7"
winit = "0.22"
[build-dependencies]
anyhow = "1.0"
fs_extra = "1.2"
glob = "0.3"
shaderc = "0.7"

@ -1,97 +0,0 @@
use anyhow::*;
use fs_extra::copy_items;
use fs_extra::dir::CopyOptions;
use glob::glob;
use std::env;
use std::fs::{read_to_string, write};
use std::path::PathBuf;
struct ShaderData {
src: String,
src_path: PathBuf,
spv_path: PathBuf,
kind: shaderc::ShaderKind,
}
impl ShaderData {
pub fn load(src_path: PathBuf) -> Result<Self> {
let extension = src_path
.extension()
.context("File has no extension")?
.to_str()
.context("Extension cannot be converted to &str")?;
let kind = match extension {
"vert" => shaderc::ShaderKind::Vertex,
"frag" => shaderc::ShaderKind::Fragment,
"comp" => shaderc::ShaderKind::Compute,
_ => bail!("Unsupported shader: {}", src_path.display()),
};
let src = read_to_string(src_path.clone())?;
let spv_path = src_path.with_extension(format!("{}.spv", extension));
Ok(Self {
src,
src_path,
spv_path,
kind,
})
}
}
fn main() -> Result<()> {
// Collect all shaders recursively within /src/
let mut shader_paths = [
glob("./src/**/*.vert")?,
glob("./src/**/*.frag")?,
glob("./src/**/*.comp")?,
];
// This could be parallelized
let shaders = shader_paths
.iter_mut()
.flatten()
.map(|glob_result| ShaderData::load(glob_result?))
.collect::<Vec<Result<_>>>()
.into_iter()
.collect::<Result<Vec<_>>>()?;
let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?;
// This can't be parallelized. The [shaderc::Compiler] is not
// thread safe. Also, it creates a lot of resources. You could
// spawn multiple processes to handle this, but it would probably
// be better just to only compile shaders that have been changed
// recently.
for shader in shaders {
// This tells cargo to rerun this script if something in /src/ changes.
println!(
"cargo:rerun-if-changed={}",
shader.src_path.as_os_str().to_str().unwrap()
);
let compiled = compiler.compile_into_spirv(
&shader.src,
shader.kind,
&shader.src_path.to_str().unwrap(),
"main",
None,
)?;
write(shader.spv_path, compiled.as_binary_u8())?;
}
// This tells cargo to rerun this script if something in /res/ changes.
println!("cargo:rerun-if-changed=res/*");
let out_dir = env::var("OUT_DIR")?;
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("res/");
match copy_items(&paths_to_copy, out_dir, &copy_options) {
Ok(_) => {}
Err(e) => println!("{}", e),
}
Ok(())
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

@ -1,14 +0,0 @@
# Blender MTL File: 'cube.blend'
# Material Count: 1
newmtl Material.001
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump cube-normal.png
map_Kd cube-diffuse.jpg

File diff suppressed because it is too large Load Diff

@ -1,8 +0,0 @@
#version 450
layout(location=0) in vec3 v_color;
layout(location=0) out vec4 f_color;
void main() {
f_color = vec4(v_color, 1.0);
}

@ -1,27 +0,0 @@
#version 450
layout(location=0) in vec3 a_position;
layout(location=0) out vec3 v_color;
layout(set=0, binding=0)
uniform Uniforms {
vec3 u_view_position;
mat4 u_view_proj;
};
layout(set=1, binding=0)
uniform Light {
vec3 u_position;
vec3 u_color;
};
// Let's keep our light smaller than our other objects
float scale = 0.25;
void main() {
vec3 v_position = a_position * scale + u_position;
gl_Position = u_view_proj * vec4(v_position, 1);
v_color = u_color;
}

@ -1,40 +0,0 @@
#version 450
layout(location=0) in vec2 v_tex_coords;
layout(location=1) in vec3 v_position; // UPDATED!
layout(location=2) in vec3 v_light_position; // NEW!
layout(location=3) in vec3 v_view_position; // NEW!
layout(location=0) out vec4 f_color;
layout(set = 0, binding = 0) uniform texture2D t_diffuse;
layout(set = 0, binding = 1) uniform sampler s_diffuse;
layout(set = 0, binding = 2) uniform texture2D t_normal;
layout(set = 0, binding = 3) uniform sampler s_normal;
layout(set = 2, binding = 0) uniform Light {
vec3 light_position;
vec3 light_color;
};
void main() {
vec4 object_color = texture(sampler2D(t_diffuse, s_diffuse), v_tex_coords);
vec4 object_normal = texture(sampler2D(t_normal, s_normal), v_tex_coords);
float ambient_strength = 0.1;
vec3 ambient_color = light_color * ambient_strength;
vec3 normal = normalize(object_normal.rgb * 2.0 - 1.0); // UPDATED!
vec3 light_dir = normalize(v_light_position - v_position); // UPDATED!
float diffuse_strength = max(dot(normal, light_dir), 0.0);
vec3 diffuse_color = light_color * diffuse_strength;
vec3 view_dir = normalize(v_view_position - v_position); // UPDATED!
vec3 half_dir = normalize(view_dir + light_dir);
float specular_strength = pow(max(dot(normal, half_dir), 0.0), 32);
vec3 specular_color = specular_strength * light_color;
vec3 result = (ambient_color + diffuse_color + specular_color) * object_color.xyz;
f_color = vec4(result, object_color.a);
}

@ -1,55 +0,0 @@
#version 450
layout(location=0) in vec3 a_position;
layout(location=1) in vec2 a_tex_coords;
layout(location=2) in vec3 a_normal;
layout(location=3) in vec3 a_tangent;
layout(location=4) in vec3 a_bitangent;
layout(location=0) out vec2 v_tex_coords;
layout(location=1) out vec3 v_position;
layout(location=2) out vec3 v_light_position;
layout(location=3) out vec3 v_view_position;
layout(set=0, binding=0)
uniform Uniforms {
vec3 u_view_position;
mat4 u_view_proj;
};
layout(location=5) in vec4 model_matrix_0;
layout(location=6) in vec4 model_matrix_1;
layout(location=7) in vec4 model_matrix_2;
layout(location=8) in vec4 model_matrix_3;
// NEW!
layout(set=1, binding=0) uniform Light {
vec3 light_position;
vec3 light_color;
};
void main() {
v_tex_coords = a_tex_coords;
mat3 normal_matrix = mat3(transpose(inverse(model_matrix)));
vec3 normal = normalize(normal_matrix * a_normal);
vec3 tangent = normalize(normal_matrix * a_tangent);
vec3 bitangent = normalize(normal_matrix * a_bitangent);
// UDPATED!
mat3 tangent_matrix = transpose(mat3(
tangent,
bitangent,
normal
));
vec4 model_space = model_matrix * vec4(a_position, 1.0);
v_position = model_space.xyz;
// NEW!
v_position = tangent_matrix * model_space.xyz;
v_light_position = tangent_matrix * light_position;
v_view_position = tangent_matrix * u_view_position;
gl_Position = u_view_proj * model_space;
}

@ -7,12 +7,12 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
image = "0.22"
raw-window-handle = "0.1"
winit = "0.20.0-alpha3"
image = "0.23"
raw-window-handle = "0.3"
winit = "0.24"
shaderc = "0.7"
cgmath = "0.17"
wgpu = "0.5.0"
cgmath = "0.18"
wgpu = "0.7"
futures = "0.3.4"
[[bin]]

@ -1,14 +1,14 @@
async fn run() {
let adapter = wgpu::Adapter::request(
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let adapter = instance.request_adapter(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: None,
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();
let (device, queue) = adapter.request_device(&Default::default()).await;
let (device, queue) = adapter.request_device(&Default::default(), None).await.unwrap();
let texture_size = 256u32;
let texture_desc = wgpu::TextureDescriptor {
@ -17,7 +17,6 @@ async fn run() {
height: texture_size,
depth: 1,
},
array_layer_count: 1,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
@ -26,7 +25,7 @@ async fn run() {
label: None,
};
let texture = device.create_texture(&texture_desc);
let texture_view = texture.create_default_view();
let texture_view = texture.create_view(&Default::default());
// we need to store this for later
let u32_size = std::mem::size_of::<u32>() as u32;
@ -38,6 +37,7 @@ async fn run() {
// this tells wpgu that we want to read this buffer from the cpu
| wgpu::BufferUsage::MAP_READ,
label: None,
mapped_at_creation: false,
};
let output_buffer = device.create_buffer(&output_buffer_desc);
@ -62,31 +62,42 @@ async fn run() {
None,
)
.unwrap();
let vs_data = wgpu::read_spirv(std::io::Cursor::new(vs_spirv.as_binary_u8())).unwrap();
let fs_data = wgpu::read_spirv(std::io::Cursor::new(fs_spirv.as_binary_u8())).unwrap();
let vs_module = device.create_shader_module(&vs_data);
let fs_module = device.create_shader_module(&fs_data);
let vs_data = wgpu::util::make_spirv(vs_spirv.as_binary_u8());
let fs_data = wgpu::util::make_spirv(fs_spirv.as_binary_u8());
let vs_module = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Vertex Shader"),
source: vs_data,
flags: wgpu::ShaderFlags::default(),
});
let fs_module = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Fragment Shader"),
source: fs_data,
flags: wgpu::ShaderFlags::default(),
});
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"),
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
layout: &render_pipeline_layout,
label: Some("Render Pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &vs_module,
entry_point: "main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
targets: &[wgpu::ColorTargetState {
format: texture_desc.format,
alpha_blend: wgpu::BlendState::REPLACE,
color_blend: wgpu::BlendState::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@ -96,20 +107,12 @@ async fn run() {
// Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
polygon_mode: wgpu::PolygonMode::Fill,
},
color_states: &[wgpu::ColorStateDescriptor {
format: texture_desc.format,
color_blend: wgpu::BlendDescriptor::REPLACE,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
}],
depth_stencil: None,
vertex_state: wgpu::VertexStateDescriptor {
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[],
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
});
let mut encoder =
@ -117,16 +120,18 @@ async fn run() {
{
let render_pass_desc = wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &texture_view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
@ -141,32 +146,38 @@ async fn run() {
wgpu::TextureCopyView {
texture: &texture,
mip_level: 0,
array_layer: 0,
origin: wgpu::Origin3d::ZERO,
},
wgpu::BufferCopyView {
buffer: &output_buffer,
offset: 0,
bytes_per_row: u32_size * texture_size,
rows_per_image: texture_size,
layout: wgpu::TextureDataLayout {
offset: 0,
bytes_per_row: u32_size * texture_size,
rows_per_image: texture_size,
},
},
texture_desc.size,
);
queue.submit(&[encoder.finish()]);
// NOTE: We have to create the mapping THEN device.poll(). If we don't
// the application will freeze.
let mapping = output_buffer.map_read(0, output_buffer_size);
device.poll(wgpu::Maintain::Wait);
let result = mapping.await.unwrap();
let data = result.as_slice();
queue.submit(Some(encoder.finish()));
use image::{ImageBuffer, Rgba};
let buffer = ImageBuffer::<Rgba<u8>, _>::from_raw(texture_size, texture_size, data).unwrap();
buffer.save("image.png").unwrap();
{
let buffer_slice = output_buffer.slice(..);
// NOTE: We have to create the mapping THEN device.poll() before await
// the future. Otherwise the application will freeze.
let mapping = buffer_slice.map_async(wgpu::MapMode::Read);
device.poll(wgpu::Maintain::Wait);
mapping.await.unwrap();
let data = buffer_slice.get_mapped_range();
use image::{ImageBuffer, Rgba};
let buffer = ImageBuffer::<Rgba<u8>, _>::from_raw(texture_size, texture_size, data).unwrap();
buffer.save("image.png").unwrap();
}
output_buffer.unmap();
}
fn main() {

Loading…
Cancel
Save