engine: textures
parent
cb1e800279
commit
1636b9efcc
|
@ -0,0 +1 @@
|
|||
exports_files(["test-128px.png"])
|
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
|
@ -38,6 +38,7 @@ rust_binary(
|
|||
data = [
|
||||
"//engine/shaders:forward_vert",
|
||||
"//engine/shaders:forward_frag",
|
||||
"//assets:test-128px.png",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -2,9 +2,14 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(binding = 0) uniform sampler2D texSampler;
|
||||
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
//outColor = vec4(fragColor, 1.0);
|
||||
outColor = texture(texSampler, fragTexCoord);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ layout(push_constant) uniform UniformBufferObject {
|
|||
layout(location = 0) in vec3 pos;
|
||||
layout(location = 1) in vec3 color;
|
||||
layout(location = 2) in mat4 model;
|
||||
layout(location = 6) in vec2 tex;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
layout(location = 1) out vec2 fragTexCoord;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
|
@ -19,6 +21,8 @@ void main() {
|
|||
gl_Position = ubo.view * model * vec4(pos, 1.0);
|
||||
fragColor = color;
|
||||
|
||||
fragTexCoord = tex;
|
||||
|
||||
// Vulkanize
|
||||
gl_Position.y = -gl_Position.y;
|
||||
}
|
||||
|
|
|
@ -17,33 +17,55 @@ fn main() {
|
|||
|
||||
let mesh_cube = {
|
||||
let vertices = Arc::new(vec![
|
||||
data::Vertex::new([-0.5, -0.5, -0.5], [1.0, 0.0, 0.0]),
|
||||
data::Vertex::new([0.5, -0.5, -0.5], [0.0, 1.0, 0.0]),
|
||||
data::Vertex::new([0.5, 0.5, -0.5], [0.0, 0.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, -0.5], [1.0, 1.0, 1.0]),
|
||||
data::Vertex::new([-0.5, -0.5, 0.5], [1.0, 1.0, 1.0]),
|
||||
data::Vertex::new([0.5, -0.5, 0.5], [1.0, 1.0, 0.0]),
|
||||
data::Vertex::new([0.5, 0.5, 0.5], [0.0, 1.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, 0.5], [1.0, 0.0, 1.0]),
|
||||
data::Vertex::new([-0.5, -0.5, 0.5], [1.0, 1.0, 1.0], [1.0, 0.0]),
|
||||
data::Vertex::new([0.5, -0.5, 0.5], [1.0, 1.0, 0.0], [0.0, 0.0]),
|
||||
data::Vertex::new([0.5, 0.5, 0.5], [0.0, 1.0, 1.0], [0.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, 0.5], [1.0, 0.0, 1.0], [1.0, 1.0]),
|
||||
|
||||
data::Vertex::new([0.5, -0.5, -0.5], [1.0, 1.0, 1.0], [0.0, 1.0]),
|
||||
data::Vertex::new([0.5, 0.5, -0.5], [1.0, 1.0, 0.0], [1.0, 1.0]),
|
||||
data::Vertex::new([0.5, 0.5, 0.5], [0.0, 1.0, 1.0], [1.0, 0.0]),
|
||||
data::Vertex::new([0.5, -0.5, 0.5], [1.0, 0.0, 1.0], [0.0, 0.0]),
|
||||
|
||||
data::Vertex::new([-0.5, -0.5, -0.5], [1.0, 1.0, 1.0], [1.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, -0.5], [1.0, 1.0, 0.0], [0.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, 0.5], [0.0, 1.0, 1.0], [0.0, 0.0]),
|
||||
data::Vertex::new([-0.5, -0.5, 0.5], [1.0, 0.0, 1.0], [1.0, 0.0]),
|
||||
|
||||
data::Vertex::new([-0.5, -0.5, -0.5], [1.0, 1.0, 1.0], [0.0, 1.0]),
|
||||
data::Vertex::new([0.5, -0.5, -0.5], [1.0, 1.0, 0.0], [1.0, 1.0]),
|
||||
data::Vertex::new([0.5, -0.5, 0.5], [0.0, 1.0, 1.0], [1.0, 0.0]),
|
||||
data::Vertex::new([-0.5, -0.5, 0.5], [1.0, 0.0, 1.0], [0.0, 0.0]),
|
||||
|
||||
data::Vertex::new([-0.5, 0.5, -0.5], [1.0, 1.0, 1.0], [1.0, 1.0]),
|
||||
data::Vertex::new([0.5, 0.5, -0.5], [1.0, 1.0, 0.0], [0.0, 1.0]),
|
||||
data::Vertex::new([0.5, 0.5, 0.5], [0.0, 1.0, 1.0], [0.0, 0.0]),
|
||||
data::Vertex::new([-0.5, 0.5, 0.5], [1.0, 0.0, 1.0], [1.0, 0.0]),
|
||||
|
||||
data::Vertex::new([-0.5, -0.5, -0.5], [1.0, 1.0, 1.0], [0.0, 0.0]),
|
||||
data::Vertex::new([0.5, -0.5, -0.5], [1.0, 1.0, 0.0], [1.0, 0.0]),
|
||||
data::Vertex::new([0.5, 0.5, -0.5], [0.0, 1.0, 1.0], [1.0, 1.0]),
|
||||
data::Vertex::new([-0.5, 0.5, -0.5], [1.0, 0.0, 1.0], [0.0, 1.0]),
|
||||
]);
|
||||
let indices = Arc::new(vec![
|
||||
// bottom
|
||||
2, 1, 0, 0, 3, 2,
|
||||
// top
|
||||
4, 5, 6, 6, 7, 4,
|
||||
0, 1, 2, 2, 3, 0,
|
||||
|
||||
4, 5, 6, 6, 7, 4,
|
||||
8, 10, 9, 10, 8, 11,
|
||||
|
||||
12, 13, 14, 14, 15, 12,
|
||||
16, 18, 17, 18, 16, 19,
|
||||
|
||||
20, 22, 21, 22, 20, 23,
|
||||
|
||||
// left
|
||||
4, 7, 0, 0, 7, 3,
|
||||
// right
|
||||
5, 1, 6, 6, 1, 2,
|
||||
// front
|
||||
7, 6, 3, 3, 6, 2,
|
||||
// back
|
||||
5, 4, 1, 1, 4, 0,
|
||||
]);
|
||||
Arc::new(render::renderable::Mesh::new(vertices, indices))
|
||||
};
|
||||
|
||||
let path = &crate::util::file::resource_path(String::from("assets/test-128px.png"));
|
||||
let image = Arc::new(image::open(path).unwrap());
|
||||
let texture_cube = Arc::new(render::renderable::Texture::new(image));
|
||||
|
||||
let mut renderer = render::Renderer::initialize();
|
||||
|
||||
let mut cubes: Vec<Arc<Object>> = Vec::new();
|
||||
|
@ -53,7 +75,8 @@ fn main() {
|
|||
let transform = cgm::Matrix4::from_translation(cgm::Vector3::new((x as f32)*4.0, (y as f32)*4.0, (z as f32)*4.0));
|
||||
let cube = render::renderable::Object {
|
||||
mesh: mesh_cube.clone(),
|
||||
transform
|
||||
transform,
|
||||
texture: texture_cube.clone(),
|
||||
};
|
||||
cubes.push(Arc::new(cube));
|
||||
}
|
||||
|
|
|
@ -4,21 +4,64 @@ use std::sync::Mutex;
|
|||
use std::time;
|
||||
|
||||
use cgmath as cgm;
|
||||
use image;
|
||||
use image::GenericImageView;
|
||||
use vulkano::device as vd;
|
||||
use vulkano::buffer as vb;
|
||||
use vulkano::sync::GpuFuture;
|
||||
use vulkano::format as vf;
|
||||
use vulkano::image as vm;
|
||||
|
||||
use crate::render::vulkan::data;
|
||||
|
||||
pub trait Renderable {
|
||||
fn render_data(&self) -> Option<(Arc<Mesh>, cgm::Matrix4<f32>)> {
|
||||
fn render_data(&self) -> Option<(Arc<Mesh>, Arc<Texture>, cgm::Matrix4<f32>)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
struct VulkanData {
|
||||
vbuffer: Arc<vb::ImmutableBuffer<[data::Vertex]>>,
|
||||
ibuffer: Arc<vb::ImmutableBuffer<[u16]>>,
|
||||
pub struct Texture {
|
||||
image: Arc<image::DynamicImage>,
|
||||
|
||||
// vulkan cache
|
||||
vulkan: Mutex<Option<Arc<vm::ImmutableImage<vf::Format>>>>,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn new(
|
||||
image: Arc<image::DynamicImage>,
|
||||
) -> Self {
|
||||
Self {
|
||||
image,
|
||||
vulkan: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
pub fn vulkan_texture(
|
||||
&self,
|
||||
graphics_queue: Arc<vd::Queue>,
|
||||
) -> Arc<vm::ImmutableImage<vf::Format>> {
|
||||
let mut cache = self.vulkan.lock().unwrap();
|
||||
match &mut *cache {
|
||||
Some(data) => data.clone(),
|
||||
None => {
|
||||
let width = self.image.width();
|
||||
let height = self.image.height();
|
||||
let image_rgba = self.image.to_rgba();
|
||||
let (image_view, future) = vm::ImmutableImage::from_iter(
|
||||
image_rgba.into_raw().iter().cloned(),
|
||||
vm::Dimensions::Dim2d{ width, height },
|
||||
vf::Format::R8G8B8A8Unorm,
|
||||
graphics_queue.clone(),
|
||||
).unwrap();
|
||||
|
||||
future.flush().unwrap();
|
||||
|
||||
*cache = Some(image_view.clone());
|
||||
|
||||
image_view
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Mesh {
|
||||
|
@ -27,7 +70,12 @@ pub struct Mesh {
|
|||
|
||||
id: u64,
|
||||
// vulkan buffers cache
|
||||
vulkan: Mutex<Option<VulkanData>>,
|
||||
vulkan: Mutex<Option<MeshVulkanData>>,
|
||||
}
|
||||
|
||||
struct MeshVulkanData {
|
||||
vbuffer: Arc<vb::ImmutableBuffer<[data::Vertex]>>,
|
||||
ibuffer: Arc<vb::ImmutableBuffer<[u16]>>,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
|
@ -69,7 +117,7 @@ impl Mesh {
|
|||
vfuture.flush().unwrap();
|
||||
ifuture.flush().unwrap();
|
||||
|
||||
*cache = Some(VulkanData {
|
||||
*cache = Some(MeshVulkanData {
|
||||
vbuffer: vbuffer.clone(),
|
||||
ibuffer: ibuffer.clone(),
|
||||
});
|
||||
|
@ -96,11 +144,12 @@ impl Eq for Mesh {}
|
|||
|
||||
pub struct Object {
|
||||
pub mesh: Arc<Mesh>,
|
||||
pub texture: Arc<Texture>,
|
||||
pub transform: cgm::Matrix4<f32>,
|
||||
}
|
||||
|
||||
impl Renderable for Object {
|
||||
fn render_data(&self) -> Option<(Arc<Mesh>, cgm::Matrix4<f32>)> {
|
||||
Some((self.mesh.clone(), self.transform.clone()))
|
||||
fn render_data(&self) -> Option<(Arc<Mesh>, Arc<Texture>, cgm::Matrix4<f32>)> {
|
||||
Some((self.mesh.clone(), self.texture.clone(), self.transform.clone()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,17 @@ use cgmath as cgm;
|
|||
pub struct Vertex {
|
||||
pos: [f32; 3],
|
||||
color: [f32; 3],
|
||||
tex: [f32; 2],
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
pub fn new(pos: [f32; 3], color: [f32; 3]) -> Self {
|
||||
pub fn new(pos: [f32; 3], color: [f32; 3], tex: [f32; 2]) -> Self {
|
||||
Self {
|
||||
pos, color,
|
||||
pos, color, tex,
|
||||
}
|
||||
}
|
||||
}
|
||||
vulkano::impl_vertex!(Vertex, pos, color);
|
||||
vulkano::impl_vertex!(Vertex, pos, color, tex);
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct Instance {
|
||||
|
|
|
@ -161,8 +161,10 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
|||
|
||||
// Sort renderables by mesh.
|
||||
let mut meshes: HashMap<Arc<renderable::Mesh>, Vec<cgm::Matrix4<f32>>> = HashMap::new();
|
||||
let mut textures: HashMap<Arc<renderable::Mesh>, Arc<renderable::Texture>> = HashMap::new();
|
||||
for r in renderables {
|
||||
if let Some((mesh, transform)) = r.render_data() {
|
||||
if let Some((mesh, texture, transform)) = r.render_data() {
|
||||
textures.entry(mesh.clone()).or_insert(texture);
|
||||
let entry = meshes.entry(mesh.clone()).or_insert(vec![]);
|
||||
entry.push(transform);
|
||||
}
|
||||
|
@ -171,6 +173,7 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
|||
let device = self.surface_binding().device.clone();
|
||||
let queue = self.surface_binding().graphics_queue.clone();
|
||||
let rp = self.swapchain_binding().render_pass.clone();
|
||||
|
||||
let pipeline = self.pipeline.as_ref().unwrap().get_pipeline().clone();
|
||||
|
||||
for (mesh, transforms) in meshes {
|
||||
|
@ -188,9 +191,13 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
|||
).unwrap();
|
||||
future.flush().unwrap();
|
||||
|
||||
let texture = textures.get(&mesh).unwrap().clone();
|
||||
let image = texture.vulkan_texture(queue.clone());
|
||||
let ds = self.pipeline.as_mut().unwrap().make_descriptor_set(image);
|
||||
|
||||
let (vbuffer, ibuffer) = mesh.vulkan_buffers(queue.clone());
|
||||
builder = builder.draw_indexed(pipeline.clone(), &vc::DynamicState::none(),
|
||||
vec![vbuffer.clone(), instancebuffer], ibuffer.clone(), (), ubo).unwrap();
|
||||
vec![vbuffer.clone(), instancebuffer], ibuffer.clone(), ds, ubo).unwrap();
|
||||
|
||||
buffers.push(Box::new(builder.build().unwrap()));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ use vulkano::framebuffer as vf;
|
|||
use vulkano::pipeline as vp;
|
||||
use vulkano::pipeline::shader as vps;
|
||||
use vulkano::pipeline::vertex as vpv;
|
||||
use vulkano::sampler as vs;
|
||||
use vulkano::image as vm;
|
||||
|
||||
use crate::render::vulkan::data;
|
||||
use crate::render::vulkan::shaders;
|
||||
|
@ -20,12 +22,13 @@ type VulkanoDescriptorSet = dyn vdd::DescriptorSet + Send + Sync;
|
|||
|
||||
pub trait Pipeline {
|
||||
fn get_pipeline(&self) -> Arc<VulkanoPipeline>;
|
||||
fn make_descriptor_set(&mut self, buffer: Box<dyn vb::BufferAccess + Send + Sync>) -> Arc<VulkanoDescriptorSet>;
|
||||
fn make_descriptor_set(&mut self, texture_image: Arc<vm::ImmutableImage<Format>>) -> Arc<VulkanoDescriptorSet>;
|
||||
}
|
||||
|
||||
pub struct Forward {
|
||||
pipeline: Arc<VulkanoPipeline>,
|
||||
descriptor_set_pool: vdd::FixedSizeDescriptorSetsPool,
|
||||
device: Arc<vd::Device>,
|
||||
}
|
||||
|
||||
impl Forward {
|
||||
|
@ -35,7 +38,7 @@ impl Forward {
|
|||
render_pass: Arc<dyn vf::RenderPassAbstract + Send + Sync>,
|
||||
) -> Forward {
|
||||
let vertex_shader = shaders::ShaderDefinition {
|
||||
name: "forward_vert.spv".to_string(),
|
||||
name: "engine/shaders/forward_vert.spv".to_string(),
|
||||
ty: vps::GraphicsShaderType::Vertex,
|
||||
inputs: vec![
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
|
@ -50,12 +53,20 @@ impl Forward {
|
|||
location: 2..6, format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("model")),
|
||||
},
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
location: 6..7, format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("tex")),
|
||||
},
|
||||
],
|
||||
outputs: vec![
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
location: 0..1, format: Format::R32G32B32Sfloat,
|
||||
name: Some(Cow::Borrowed("fragColor")),
|
||||
}
|
||||
},
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
location: 1..2, format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("fragTexCoord")),
|
||||
},
|
||||
],
|
||||
uniforms: vec![],
|
||||
push_constants: vec![
|
||||
|
@ -71,13 +82,17 @@ impl Forward {
|
|||
}.load_into(device.clone()).expect("could not load vertex shader");
|
||||
|
||||
let fragment_shader = shaders::ShaderDefinition {
|
||||
name: "forward_frag.spv".to_string(),
|
||||
name: "engine/shaders/forward_frag.spv".to_string(),
|
||||
ty: vps::GraphicsShaderType::Fragment,
|
||||
inputs: vec![
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
location: 0..1, format: Format::R32G32B32Sfloat,
|
||||
name: Some(Cow::Borrowed("fragColor")),
|
||||
}
|
||||
},
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
location: 1..2, format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("fragTexCoord")),
|
||||
},
|
||||
],
|
||||
outputs: vec![
|
||||
vps::ShaderInterfaceDefEntry {
|
||||
|
@ -85,7 +100,23 @@ impl Forward {
|
|||
name: Some(Cow::Borrowed("outColor")),
|
||||
}
|
||||
],
|
||||
uniforms: vec![],
|
||||
uniforms: vec![
|
||||
vdD::DescriptorDesc {
|
||||
ty: vdD::DescriptorDescTy::CombinedImageSampler(vdD::DescriptorImageDesc {
|
||||
sampled: true,
|
||||
dimensions: vdD::DescriptorImageDescDimensions::TwoDimensional,
|
||||
format: None,
|
||||
multisampled: false,
|
||||
array_layers: vdD::DescriptorImageDescArray::NonArrayed,
|
||||
}),
|
||||
array_count: 1,
|
||||
readonly: true,
|
||||
stages: vdD::ShaderStages {
|
||||
fragment: true,
|
||||
..vdD::ShaderStages::none()
|
||||
},
|
||||
},
|
||||
],
|
||||
push_constants: vec![],
|
||||
}.load_into(device.clone()).expect("could not load fragment shader");
|
||||
|
||||
|
@ -127,7 +158,8 @@ impl Forward {
|
|||
|
||||
Forward {
|
||||
pipeline,
|
||||
descriptor_set_pool
|
||||
descriptor_set_pool,
|
||||
device
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,9 +169,10 @@ impl Pipeline for Forward {
|
|||
self.pipeline.clone()
|
||||
}
|
||||
|
||||
fn make_descriptor_set(&mut self, buffer: Box<dyn vb::BufferAccess + Send + Sync>) -> Arc<VulkanoDescriptorSet> {
|
||||
fn make_descriptor_set(&mut self, texture_image: Arc<vm::ImmutableImage<Format>>) -> Arc<VulkanoDescriptorSet> {
|
||||
let image_sampler = vs::Sampler::simple_repeat_linear(self.device.clone());
|
||||
Arc::new(self.descriptor_set_pool.next()
|
||||
.add_buffer(buffer).unwrap()
|
||||
.add_sampled_image(texture_image.clone(), image_sampler).unwrap()
|
||||
.build().unwrap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ pub fn resource_path(name: String) -> path::PathBuf {
|
|||
fn stringify(x: std::io::Error) -> String { format!("IO error: {}", x) }
|
||||
|
||||
match Runfiles::create().map_err(stringify) {
|
||||
Err(_) => path::Path::new(".").join("shaders").join(name),
|
||||
Ok(r) => r.rlocation(format!("abrasion/engine/shaders/{}", name))
|
||||
Err(_) => path::Path::new(".").join(name),
|
||||
Ok(r) => r.rlocation(format!("abrasion/{}", name))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue