Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
E
Efficient Realtime Rendering of Complex Closed Form Implicit Surfaces Using Modern RTX Enabled GPUs
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
John Hunter
Efficient Realtime Rendering of Complex Closed Form Implicit Surfaces Using Modern RTX Enabled GPUs
Commits
6bdd6c04
Unverified
Commit
6bdd6c04
authored
2 years ago
by
John Hunter
Browse files
Options
Downloads
Patches
Plain Diff
various overhauls to data formats
parent
fc455c91
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/frag.glsl
+14
-3
14 additions, 3 deletions
src/frag.glsl
src/gui.rs
+47
-6
47 additions, 6 deletions
src/gui.rs
src/main.rs
+158
-105
158 additions, 105 deletions
src/main.rs
src/objects.rs
+119
-0
119 additions, 0 deletions
src/objects.rs
with
338 additions
and
114 deletions
src/frag.glsl
+
14
−
3
View file @
6bdd6c04
#version 450
#version 450
layout
(
location
=
0
)
in
vec3
fragColor
;
layout
(
location
=
0
)
in
vec3
normal
;
layout
(
location
=
0
)
out
vec4
f_color
;
layout
(
location
=
0
)
out
vec4
f_color
;
const
vec3
light
=
normalize
(
vec3
(
4
,
6
,
8
));
layout
(
set
=
0
,
binding
=
0
)
uniform
Data
{
vec4
[
32
]
pos
;
vec4
[
32
]
col
;
uint
light_count
;
}
uniforms
;
void
main
(){
void
main
(){
f_color
=
vec4
(
vec3
(
dot
(
fragColor
,
light
))
*
.
5
+
.
5
,
1
.);
vec3
accum
=
vec3
(
0
.,
0
.,
0
.);
for
(
int
i
=
0
;
i
<
uniforms
.
light_count
;
i
++
)
{
accum
+=
uniforms
.
col
[
i
].
xyz
*
((
dot
(
normalize
(
normal
),
uniforms
.
pos
[
i
].
xyz
)
*
.
5
)
+
.
5
);
}
f_color
=
vec4
(
accum
,
1
.);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/gui.rs
+
47
−
6
View file @
6bdd6c04
use
egui
::{
Color32
,
Frame
,
Id
,
ScrollArea
,
TextEdit
,
TextStyle
};
use
egui
::{
plot
::{
Line
,
Plot
,
PlotPoints
},
Color32
,
Frame
,
Id
,
ScrollArea
,
TextEdit
,
TextStyle
,
};
use
egui_winit_vulkano
::
Gui
;
use
egui_winit_vulkano
::
Gui
;
use
crate
::
objects
::{
Light
,
Mesh
};
fn
sized_text
(
ui
:
&
mut
egui
::
Ui
,
text
:
impl
Into
<
String
>
,
size
:
f32
)
{
fn
sized_text
(
ui
:
&
mut
egui
::
Ui
,
text
:
impl
Into
<
String
>
,
size
:
f32
)
{
ui
.label
(
egui
::
RichText
::
new
(
text
)
.size
(
size
));
ui
.label
(
egui
::
RichText
::
new
(
text
)
.size
(
size
));
}
}
...
@@ -17,6 +22,11 @@ Vulkan(o) is hard, that I know...
...
@@ -17,6 +22,11 @@ Vulkan(o) is hard, that I know...
pub
struct
GState
{
pub
struct
GState
{
pub
cursor_sensitivity
:
f32
,
pub
cursor_sensitivity
:
f32
,
pub
move_speed
:
f32
,
pub
move_speed
:
f32
,
pub
meshes
:
Vec
<
Mesh
>
,
pub
lights
:
Vec
<
Light
>
,
pub
fps
:
[
f64
;
128
],
}
}
impl
Default
for
GState
{
impl
Default
for
GState
{
...
@@ -24,6 +34,11 @@ impl Default for GState {
...
@@ -24,6 +34,11 @@ impl Default for GState {
Self
{
Self
{
cursor_sensitivity
:
1.0
,
cursor_sensitivity
:
1.0
,
move_speed
:
1.0
,
move_speed
:
1.0
,
meshes
:
vec!
[],
lights
:
vec!
[],
fps
:
[
0.0
;
128
],
}
}
}
}
}
}
...
@@ -40,11 +55,37 @@ pub fn gui_up(gui: &mut Gui, state: &mut GState) {
...
@@ -40,11 +55,37 @@ pub fn gui_up(gui: &mut Gui, state: &mut GState) {
sized_text
(
ui
,
"Settings"
,
32.0
);
sized_text
(
ui
,
"Settings"
,
32.0
);
});
});
ui
.separator
();
ui
.separator
();
ui
.vertical_centered
(|
ui
|
{
egui
::
ScrollArea
::
vertical
()
.show
(
ui
,
|
ui
|
{
//ui.heading("Camera Control");
ui
.vertical_centered
(|
ui
|
{
ui
.add
(
egui
::
Slider
::
new
(
&
mut
state
.cursor_sensitivity
,
0.0
..=
2.0
)
.text
(
"Mouse Sensitivity"
));
ui
.heading
(
"Camera Control"
);
ui
.add
(
egui
::
Slider
::
new
(
&
mut
state
.move_speed
,
0.0
..=
2.0
)
.text
(
"Movement Speed"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
state
.cursor_sensitivity
,
0.0
..=
2.0
)
.text
(
"Mouse Sensitivity"
));
});
ui
.add
(
egui
::
Slider
::
new
(
&
mut
state
.move_speed
,
0.0
..=
2.0
)
.text
(
"Movement Speed"
));
ui
.heading
(
"Meshes"
);
for
mesh
in
&
mut
state
.meshes
{
ui
.label
(
mesh
.name
.clone
());
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.pos.x
,
-
100.0
..=
100.0
)
.text
(
"Position.x"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.pos.y
,
-
100.0
..=
100.0
)
.text
(
"Position.y"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.pos.z
,
-
100.0
..=
100.0
)
.text
(
"Position.z"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.rot.x
.0
,
0.0
..=
360.0
)
.text
(
"Rotation.x"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.rot.y
.0
,
0.0
..=
360.0
)
.text
(
"Rotation.y"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
mesh
.rot.z
.0
,
0.0
..=
360.0
)
.text
(
"Rotation.z"
));
}
ui
.heading
(
"Lights"
);
for
light
in
&
mut
state
.lights
{
ui
.label
(
"Light"
);
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.pos.x
,
-
100.0
..=
100.0
)
.text
(
"Position.x"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.pos.y
,
-
100.0
..=
100.0
)
.text
(
"Position.y"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.pos.z
,
-
100.0
..=
100.0
)
.text
(
"Position.z"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.colour.x
,
0.0
..=
1.0
)
.text
(
"Colour.r"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.colour.y
,
0.0
..=
1.0
)
.text
(
"Colour.g"
));
ui
.add
(
egui
::
Slider
::
new
(
&
mut
light
.colour.z
,
0.0
..=
1.0
)
.text
(
"Colour.b"
));
}
let
fps
:
PlotPoints
=
state
.fps
.iter
()
.enumerate
()
.map
(|(
x
,
y
)|
[
x
as
f64
,
*
y
])
.collect
::
<
Vec
<
_
>>
()
.into
();
let
line
=
Line
::
new
(
fps
);
ui
.heading
(
"FPS"
);
Plot
::
new
(
"fps"
)
.view_aspect
(
2.0
)
.show
(
ui
,
|
plot_ui
|
plot_ui
.line
(
line
));
});
});
});
});
});
});
}
}
This diff is collapsed.
Click to expand it.
src/main.rs
+
158
−
105
View file @
6bdd6c04
...
@@ -24,13 +24,19 @@ use obj::{LoadConfig, ObjData};
...
@@ -24,13 +24,19 @@ use obj::{LoadConfig, ObjData};
use
rodio
::{
source
::
Source
,
Decoder
,
OutputStream
};
use
rodio
::{
source
::
Source
,
Decoder
,
OutputStream
};
use
std
::
io
::
Cursor
;
use
std
::
io
::
Cursor
;
use
std
::{
sync
::
Arc
,
time
::
Instant
};
use
std
::{
sync
::
Arc
,
time
::
Instant
};
use
vulkano
::
buffer
::
CpuBufferPool
;
use
vulkano
::
command_buffer
::
allocator
::
StandardCommandBufferAllocator
;
use
vulkano
::
command_buffer
::
allocator
::
StandardCommandBufferAllocator
;
use
vulkano
::
descriptor_set
::
allocator
::
StandardDescriptorSetAllocator
;
use
vulkano
::
descriptor_set
::{
PersistentDescriptorSet
,
WriteDescriptorSet
};
use
vulkano
::
device
::
DeviceOwned
;
use
vulkano
::
format
::
Format
;
use
vulkano
::
format
::
Format
;
use
vulkano
::
image
::
AttachmentImage
;
use
vulkano
::
image
::
AttachmentImage
;
use
vulkano
::
memory
::
allocator
::
StandardMemoryAllocator
;
use
vulkano
::
memory
::
allocator
::
{
MemoryUsage
,
StandardMemoryAllocator
}
;
use
vulkano
::
pipeline
::
graphics
::
depth_stencil
::
DepthStencilState
;
use
vulkano
::
pipeline
::
graphics
::
depth_stencil
::
DepthStencilState
;
use
vulkano
::
pipeline
::
graphics
::
rasterization
::
CullMode
;
use
vulkano
::
pipeline
::
graphics
::
rasterization
::
CullMode
;
use
vulkano
::
pipeline
::
graphics
::
rasterization
::
FrontFace
::
Clockwise
;
use
vulkano
::
pipeline
::
graphics
::
rasterization
::
FrontFace
::
Clockwise
;
use
vulkano
::
pipeline
::
PipelineBindPoint
;
use
vulkano
::
shader
::
ShaderModule
;
use
vulkano
::
swapchain
::{
PresentMode
,
SwapchainPresentInfo
};
use
vulkano
::
swapchain
::{
PresentMode
,
SwapchainPresentInfo
};
use
vulkano
::
VulkanLibrary
;
use
vulkano
::
VulkanLibrary
;
use
winit
::
event
::{
DeviceEvent
,
DeviceId
,
ElementState
,
MouseButton
,
VirtualKeyCode
};
use
winit
::
event
::{
DeviceEvent
,
DeviceId
,
ElementState
,
MouseButton
,
VirtualKeyCode
};
...
@@ -70,8 +76,12 @@ use winit::{
...
@@ -70,8 +76,12 @@ use winit::{
window
::{
Window
,
WindowBuilder
},
window
::{
Window
,
WindowBuilder
},
};
};
use
crate
::
gui
::
*
;
mod
gui
;
mod
gui
;
use
crate
::
gui
::
*
;
mod
objects
;
use
crate
::
objects
::
*
;
pub
type
MemoryAllocator
=
StandardMemoryAllocator
;
fn
main
()
{
fn
main
()
{
// The first step of any Vulkan program is to create an instance.
// The first step of any Vulkan program is to create an instance.
...
@@ -81,7 +91,7 @@ fn main() {
...
@@ -81,7 +91,7 @@ fn main() {
// All the window-drawing functionalities are part of non-core extensions that we need
// All the window-drawing functionalities are part of non-core extensions that we need
// to enable manually. To do so, we ask the `vulkano_win` crate for the list of extensions
// to enable manually. To do so, we ask the `vulkano_win` crate for the list of extensions
// required to draw to a window.
// required to draw to a window.
let
library
=
VulkanLibrary
::
new
()
.
unwrap
(
);
let
library
=
VulkanLibrary
::
new
()
.
expect
(
"Vulkan is not installed???"
);
let
required_extensions
=
vulkano_win
::
required_extensions
(
&
library
);
let
required_extensions
=
vulkano_win
::
required_extensions
(
&
library
);
// Now creating the instance.
// Now creating the instance.
...
@@ -284,50 +294,6 @@ fn main() {
...
@@ -284,50 +294,6 @@ fn main() {
.unwrap
()
.unwrap
()
};
};
const
OBJ
:
&
[
u8
]
=
include_bytes!
(
"bunny.obj"
);
let
buny
=
ObjData
::
load_buf_with_config
(
OBJ
,
LoadConfig
::
default
())
.unwrap
();
let
polys
=
&
buny
.objects
[
0
]
.groups
[
0
]
.polys
;
let
memory_allocator
=
Arc
::
new
(
StandardMemoryAllocator
::
new_default
(
device
.clone
()));
// We now create a buffer that will store the shape of our triangle.
// We use #[repr(C)] here to force rustc to not do anything funky with our data, although for this
// particular example, it doesn't actually change the in-memory representation.
#[repr(C)]
#[derive(Clone,
Copy,
Debug,
Default,
Zeroable,
Pod)]
struct
Vertex
{
position
:
[
f32
;
3
],
normal
:
[
f32
;
3
],
}
impl_vertex!
(
Vertex
,
position
,
normal
);
let
vertices
=
polys
.iter
()
.flat_map
(|
p
|
{
p
.0
.iter
()
.map
(|
v
|
Vertex
{
position
:
buny
.position
[
v
.0
],
normal
:
v
.2
.and_then
(|
vt
|
Some
(
buny
.normal
[
vt
]))
.unwrap_or
([
0.0
,
0.0
,
0.0
]),
})
.collect
::
<
Vec
<
Vertex
>>
()
})
.collect
::
<
Vec
<
Vertex
>>
();
let
vertex_buffer
=
CpuAccessibleBuffer
::
from_iter
(
&
memory_allocator
,
BufferUsage
{
vertex_buffer
:
true
,
..
BufferUsage
::
empty
()
},
false
,
vertices
,
)
.unwrap
();
// The next step is to create the shaders.
// The next step is to create the shaders.
//
//
// The raw shader creation API provided by the vulkano library is unsafe for various
// The raw shader creation API provided by the vulkano library is unsafe for various
...
@@ -344,7 +310,7 @@ fn main() {
...
@@ -344,7 +310,7 @@ fn main() {
//
//
// A more detailed overview of what the `shader!` macro generates can be found in the
// A more detailed overview of what the `shader!` macro generates can be found in the
// `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/
// `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/
mod
vs
{
mod
mesh_
vs
{
vulkano_shaders
::
shader!
{
vulkano_shaders
::
shader!
{
ty
:
"vertex"
,
ty
:
"vertex"
,
src
:
"
src
:
"
...
@@ -363,7 +329,7 @@ fn main() {
...
@@ -363,7 +329,7 @@ fn main() {
void main() {
void main() {
mat4 worldview = pc.view * pc.world;
mat4 worldview = pc.view * pc.world;
v_normal = normalize(transpose(inverse(mat3(worldview))) * normal);
v_normal =
normal; //
normalize(transpose(inverse(mat3(worldview))) * normal);
gl_Position = pc.proj * worldview * vec4(position*1000.0, 1.0);
gl_Position = pc.proj * worldview * vec4(position*1000.0, 1.0);
}
}
"
,
"
,
...
@@ -375,19 +341,26 @@ fn main() {
...
@@ -375,19 +341,26 @@ fn main() {
}
}
}
}
mod
fs
{
mod
mesh_
fs
{
vulkano_shaders
::
shader!
{
vulkano_shaders
::
shader!
{
ty
:
"fragment"
,
ty
:
"fragment"
,
path
:
"src/frag.glsl"
path
:
"src/frag.glsl"
,
types_meta
:
{
use
bytemuck
::{
Pod
,
Zeroable
};
#[derive(Clone,
Copy,
Zeroable,
Pod,
Debug)]
},
}
}
}
}
let
vs
=
vs
::
load
(
device
.clone
())
.unwrap
();
let
mesh_vs
=
mesh_
vs
::
load
(
device
.clone
())
.unwrap
();
let
fs
=
fs
::
load
(
device
.clone
())
.unwrap
();
let
mesh_fs
=
mesh_
fs
::
load
(
device
.clone
())
.unwrap
();
/*let uniform_buffer =
/*let uniform_buffer =
CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/
CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/
let
memory_allocator
=
Arc
::
new
(
MemoryAllocator
::
new_default
(
device
.clone
()));
// At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
// At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
// implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this
// implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this
// manually.
// manually.
...
@@ -439,33 +412,6 @@ fn main() {
...
@@ -439,33 +412,6 @@ fn main() {
)
)
.unwrap
();
.unwrap
();
// Before we draw we have to create what is called a pipeline. This is similar to an OpenGL
// program, but much more specific.
let
pipeline
=
GraphicsPipeline
::
start
()
// We have to indicate which subpass of which render pass this pipeline is going to be used
// in. The pipeline will only be usable from this particular subpass.
.render_pass
(
Subpass
::
from
(
render_pass
.clone
(),
0
)
.unwrap
())
// We need to indicate the layout of the vertices.
.vertex_input_state
(
BuffersDefinition
::
new
()
.vertex
::
<
Vertex
>
())
// The content of the vertex buffer describes a list of triangles.
.input_assembly_state
(
InputAssemblyState
::
new
())
// A Vulkan shader can in theory contain multiple entry points, so we have to specify
// which one.
.vertex_shader
(
vs
.entry_point
(
"main"
)
.unwrap
(),
())
// Use a resizable viewport set to draw over the entire window
.viewport_state
(
ViewportState
::
viewport_dynamic_scissor_irrelevant
())
// See `vertex_shader`.
.fragment_shader
(
fs
.entry_point
(
"main"
)
.unwrap
(),
())
.depth_stencil_state
(
DepthStencilState
::
simple_depth_test
())
.rasterization_state
(
RasterizationState
{
front_face
:
Fixed
(
Clockwise
),
cull_mode
:
Fixed
(
CullMode
::
Back
),
..
RasterizationState
::
default
()
})
// Now that our builder is filled, we call `build()` to obtain an actual pipeline.
.build
(
device
.clone
())
.unwrap
();
// Dynamic viewports allow us to recreate just the viewport when the window is resized
// Dynamic viewports allow us to recreate just the viewport when the window is resized
// Otherwise we would have to recreate the whole pipeline.
// Otherwise we would have to recreate the whole pipeline.
let
mut
viewport
=
Viewport
{
let
mut
viewport
=
Viewport
{
...
@@ -479,8 +425,10 @@ fn main() {
...
@@ -479,8 +425,10 @@ fn main() {
//
//
// Since we need to draw to multiple images, we are going to create a different framebuffer for
// Since we need to draw to multiple images, we are going to create a different framebuffer for
// each image.
// each image.
let
mut
framebuffers
=
window_size_dependent_setup
(
let
([
mut
mesh_pipeline
],
mut
framebuffers
)
=
window_size_dependent_setup
(
&
memory_allocator
,
&
memory_allocator
,
&
mesh_vs
,
&
mesh_fs
,
&
images
,
&
images
,
render_pass
.clone
(),
render_pass
.clone
(),
&
mut
viewport
,
&
mut
viewport
,
...
@@ -524,9 +472,18 @@ fn main() {
...
@@ -524,9 +472,18 @@ fn main() {
stream_handle.play_raw(source.convert_samples()).unwrap();
stream_handle.play_raw(source.convert_samples()).unwrap();
*/
*/
let
rotation_start
=
Instant
::
now
();
let
mut
render_start
=
Instant
::
now
();
let
descriptor_set_allocator
=
StandardDescriptorSetAllocator
::
new
(
device
.clone
());
//let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone());
let
uniform_buffer
=
CpuBufferPool
::
<
mesh_fs
::
ty
::
Data
>
::
new
(
memory_allocator
.clone
(),
BufferUsage
{
uniform_buffer
:
true
,
..
BufferUsage
::
empty
()
},
MemoryUsage
::
Upload
,
);
// Create an egui GUI
// Create an egui GUI
let
mut
gui
=
Gui
::
new_with_subpass
(
let
mut
gui
=
Gui
::
new_with_subpass
(
...
@@ -561,6 +518,19 @@ fn main() {
...
@@ -561,6 +518,19 @@ fn main() {
d
:
false
,
d
:
false
,
};
};
gstate
.meshes
.push
(
load_obj
(
&
memory_allocator
,
&
mut
Cursor
::
new
(
PLATONIC_SOLIDS
[
0
]
.1
),
PLATONIC_SOLIDS
[
0
]
.0
.to_string
(),
));
gstate
.lights
.push
(
Light
::
new
([
4.
,
6.
,
8.
],
[
1.
,
1.
,
8.
],
0.01
));
gstate
.lights
.push
(
Light
::
new
([
-
4.
,
6.
,
-
8.
],
[
8.
,
4.
,
1.
],
0.01
));
event_loop
.run
(
move
|
event
,
_
,
control_flow
|
{
event_loop
.run
(
move
|
event
,
_
,
control_flow
|
{
if
let
Event
::
WindowEvent
{
event
:
we
,
..
}
=
&
event
{
if
let
Event
::
WindowEvent
{
event
:
we
,
..
}
=
&
event
{
if
!
gui
.update
(
we
)
{
if
!
gui
.update
(
we
)
{
...
@@ -613,12 +583,23 @@ fn main() {
...
@@ -613,12 +583,23 @@ fn main() {
..
..
}
=>
{
}
=>
{
if
looking
{
if
looking
{
camforward
.x
-=
Deg
(
delta
.1
as
f32
)
*
gstate
.cursor_sensitivity
;
camforward
.x
-=
Deg
(
delta
.1
as
f32
)
*
gstate
.cursor_sensitivity
*
0.3
;
camforward
.y
+=
Deg
(
delta
.0
as
f32
)
*
gstate
.cursor_sensitivity
;
camforward
.y
+=
Deg
(
delta
.0
as
f32
)
*
gstate
.cursor_sensitivity
*
0.3
;
camforward
.x
=
camforward
.x
+
Deg
(
360f32
)
%
Deg
(
360f32
);
camforward
.y
=
camforward
.y
+
Deg
(
360f32
)
%
Deg
(
360f32
);
}
}
//println!("AXISM {:?}", delta);
//println!("AXISM {:?}", delta);
}
}
Event
::
RedrawEventsCleared
=>
{
Event
::
RedrawEventsCleared
=>
{
for
i
in
1
..
gstate
.fps
.len
()
{
gstate
.fps
[
i
-
1
]
=
gstate
.fps
[
i
];
}
gstate
.fps
[
gstate
.fps
.len
()
-
1
]
=
1.0
/
(
Instant
::
now
()
-
render_start
)
.as_secs_f64
();
render_start
=
Instant
::
now
();
// Do not draw frame when screen dimensions are zero.
// Do not draw frame when screen dimensions are zero.
// On Windows, this can occur from minimizing the application.
// On Windows, this can occur from minimizing the application.
let
window
=
surface
.object
()
.unwrap
()
.downcast_ref
::
<
Window
>
()
.unwrap
();
let
window
=
surface
.object
()
.unwrap
()
.downcast_ref
::
<
Window
>
()
.unwrap
();
...
@@ -653,8 +634,10 @@ fn main() {
...
@@ -653,8 +634,10 @@ fn main() {
swapchain
=
new_swapchain
;
swapchain
=
new_swapchain
;
// Because framebuffers contains an Arc on the old swapchain, we need to
// Because framebuffers contains an Arc on the old swapchain, we need to
// recreate framebuffers as well.
// recreate framebuffers as well.
framebuffers
=
window_size_dependent_setup
(
([
mesh_pipeline
],
framebuffers
)
=
window_size_dependent_setup
(
&
memory_allocator
,
&
memory_allocator
,
&
mesh_vs
,
&
mesh_fs
,
&
new_images
,
&
new_images
,
render_pass
.clone
(),
render_pass
.clone
(),
&
mut
viewport
,
&
mut
viewport
,
...
@@ -664,7 +647,7 @@ fn main() {
...
@@ -664,7 +647,7 @@ fn main() {
//println!("{:?}", right);
//println!("{:?}", right);
let
uniform_data
=
{
let
mut
push_constants
=
{
if
looking
{
if
looking
{
if
keys
.w
{
if
keys
.w
{
campos
-=
Matrix3
::
from_angle_y
(
camforward
.y
)
campos
-=
Matrix3
::
from_angle_y
(
camforward
.y
)
...
@@ -718,7 +701,7 @@ fn main() {
...
@@ -718,7 +701,7 @@ fn main() {
*
Matrix4
::
from_scale
(
scale
);
*
Matrix4
::
from_scale
(
scale
);
//*Matrix4::from_angle_z(Deg(180f32));
//*Matrix4::from_angle_z(Deg(180f32));
let
pc
=
vs
::
ty
::
PushConstantData
{
let
pc
=
mesh_
vs
::
ty
::
PushConstantData
{
world
:
Matrix4
::
identity
()
.into
(),
world
:
Matrix4
::
identity
()
.into
(),
view
:
view
.into
(),
view
:
view
.into
(),
proj
:
proj
.into
(),
proj
:
proj
.into
(),
...
@@ -735,13 +718,35 @@ fn main() {
...
@@ -735,13 +718,35 @@ fn main() {
pc
pc
};
};
//let layout = pipeline.layout().set_layouts().get(0).unwrap();
let
uniform_buffer_subbuffer
=
{
/*let set = PersistentDescriptorSet::new(
let
mut
pos
=
[[
0f32
;
4
];
32
];
&memory_allocator,
let
mut
col
=
[[
0f32
;
4
];
32
];
for
(
i
,
light
)
in
gstate
.lights
.iter
()
.enumerate
()
{
pos
[
i
][
0
]
=
light
.pos.x
;
pos
[
i
][
1
]
=
light
.pos.y
;
pos
[
i
][
2
]
=
light
.pos.z
;
col
[
i
][
0
]
=
light
.colour.x
;
col
[
i
][
1
]
=
light
.colour.y
;
col
[
i
][
2
]
=
light
.colour.z
;
}
let
uniform_data
=
mesh_fs
::
ty
::
Data
{
pos
,
col
,
light_count
:
gstate
.lights
.len
()
as
u32
,
};
uniform_buffer
.from_data
(
uniform_data
)
.unwrap
()
};
let
layout
=
mesh_pipeline
.layout
()
.set_layouts
()
.get
(
0
)
.unwrap
();
let
set
=
PersistentDescriptorSet
::
new
(
&
descriptor_set_allocator
,
layout
.clone
(),
layout
.clone
(),
[
WriteDescriptorSet
::
buffer
(
0
,
uniform_buffer_subbuffer
)],
[
WriteDescriptorSet
::
buffer
(
0
,
uniform_buffer_subbuffer
)],
)
)
.unwrap();
*/
.unwrap
();
// Before we can draw on the output, we have to *acquire* an image from the swapchain. If
// Before we can draw on the output, we have to *acquire* an image from the swapchain. If
// no image is available (which happens if you submit draw commands too quickly), then the
// no image is available (which happens if you submit draw commands too quickly), then the
...
@@ -816,19 +821,31 @@ fn main() {
...
@@ -816,19 +821,31 @@ fn main() {
// The last two parameters contain the list of resources to pass to the shaders.
// The last two parameters contain the list of resources to pass to the shaders.
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
.set_viewport
(
0
,
[
viewport
.clone
()])
.set_viewport
(
0
,
[
viewport
.clone
()])
.bind_pipeline_graphics
(
pipeline
.clone
())
.bind_pipeline_graphics
(
mesh_
pipeline
.clone
())
/*
.bind_descriptor_sets(
.bind_descriptor_sets
(
PipelineBindPoint
::
Graphics
,
PipelineBindPoint
::
Graphics
,
pipeline.layout().clone(),
mesh_
pipeline
.layout
()
.clone
(),
0
,
0
,
set
,
set
,
)*/
);
.bind_vertex_buffers
(
0
,
vertex_buffer
.clone
())
.push_constants
(
pipeline
.layout
()
.clone
(),
0
,
uniform_data
)
for
object
in
&
gstate
.meshes
{
.draw
(
vertex_buffer
.len
()
as
u32
,
1
,
0
,
0
)
push_constants
.world
=
.unwrap
()
(
Matrix4
::
from_translation
(
object
.pos
-
Point3
::
origin
())
// We leave the render pass. Note that if we had multiple
*
Matrix4
::
from
(
object
.rot
)
// subpasses we could have called `next_subpass` to jump to the next subpass.
*
object
.scale
)
.into
();
builder
.bind_vertex_buffers
(
0
,
object
.vertices
.clone
())
.bind_index_buffer
(
object
.indices
.clone
())
.push_constants
(
mesh_pipeline
.layout
()
.clone
(),
0
,
push_constants
)
.draw_indexed
(
object
.indices
.len
()
as
u32
,
1
,
0
,
0
,
0
)
.unwrap
();
}
// We leave the render pass. Note that if we had multiple
// subpasses we could have called `next_subpass` to jump to the next subpass.
builder
.next_subpass
(
SubpassContents
::
SecondaryCommandBuffers
)
.next_subpass
(
SubpassContents
::
SecondaryCommandBuffers
)
.unwrap
()
.unwrap
()
.execute_commands
(
cb
)
.execute_commands
(
cb
)
...
@@ -879,10 +896,12 @@ fn main() {
...
@@ -879,10 +896,12 @@ fn main() {
/// This method is called once during initialization, then again whenever the window is resized
/// This method is called once during initialization, then again whenever the window is resized
fn
window_size_dependent_setup
(
fn
window_size_dependent_setup
(
allocator
:
&
StandardMemoryAllocator
,
allocator
:
&
StandardMemoryAllocator
,
mesh_vs
:
&
ShaderModule
,
mesh_fs
:
&
ShaderModule
,
images
:
&
[
Arc
<
SwapchainImage
>
],
images
:
&
[
Arc
<
SwapchainImage
>
],
render_pass
:
Arc
<
RenderPass
>
,
render_pass
:
Arc
<
RenderPass
>
,
viewport
:
&
mut
Viewport
,
viewport
:
&
mut
Viewport
,
)
->
Vec
<
Arc
<
Framebuffer
>>
{
)
->
([
Arc
<
GraphicsPipeline
>
;
1
],
Vec
<
Arc
<
Framebuffer
>>
)
{
let
dimensions
=
images
[
0
]
.dimensions
()
.width_height
();
let
dimensions
=
images
[
0
]
.dimensions
()
.width_height
();
viewport
.dimensions
=
[
dimensions
[
0
]
as
f32
,
dimensions
[
1
]
as
f32
];
viewport
.dimensions
=
[
dimensions
[
0
]
as
f32
,
dimensions
[
1
]
as
f32
];
...
@@ -891,7 +910,7 @@ fn window_size_dependent_setup(
...
@@ -891,7 +910,7 @@ fn window_size_dependent_setup(
)
)
.unwrap
();
.unwrap
();
images
let
framebuffers
=
images
.iter
()
.iter
()
.map
(|
image
|
{
.map
(|
image
|
{
let
view
=
ImageView
::
new_default
(
image
.clone
())
.unwrap
();
let
view
=
ImageView
::
new_default
(
image
.clone
())
.unwrap
();
...
@@ -904,5 +923,39 @@ fn window_size_dependent_setup(
...
@@ -904,5 +923,39 @@ fn window_size_dependent_setup(
)
)
.unwrap
()
.unwrap
()
})
})
.collect
::
<
Vec
<
_
>>
()
.collect
::
<
Vec
<
_
>>
();
// Before we draw we have to create what is called a pipeline. This is similar to an OpenGL
// program, but much more specific.
let
mesh_pipeline
=
GraphicsPipeline
::
start
()
// We have to indicate which subpass of which render pass this pipeline is going to be used
// in. The pipeline will only be usable from this particular subpass.
.render_pass
(
Subpass
::
from
(
render_pass
.clone
(),
0
)
.unwrap
())
// We need to indicate the layout of the vertices.
.vertex_input_state
(
BuffersDefinition
::
new
()
.vertex
::
<
Vertex
>
())
// The content of the vertex buffer describes a list of triangles.
.input_assembly_state
(
InputAssemblyState
::
new
())
// A Vulkan shader can in theory contain multiple entry points, so we have to specify
// which one.
.vertex_shader
(
mesh_vs
.entry_point
(
"main"
)
.unwrap
(),
())
.viewport_state
(
ViewportState
::
viewport_fixed_scissor_irrelevant
([
Viewport
{
origin
:
[
0.0
,
0.0
],
dimensions
:
[
dimensions
[
0
]
as
f32
,
dimensions
[
1
]
as
f32
],
depth_range
:
0.0
..
1.0
,
},
]))
// See `vertex_shader`.
.fragment_shader
(
mesh_fs
.entry_point
(
"main"
)
.unwrap
(),
())
.depth_stencil_state
(
DepthStencilState
::
simple_depth_test
())
.rasterization_state
(
RasterizationState
{
front_face
:
Fixed
(
Clockwise
),
cull_mode
:
Fixed
(
CullMode
::
Back
),
..
RasterizationState
::
default
()
})
// Now that our builder is filled, we call `build()` to obtain an actual pipeline.
.build
(
allocator
.device
()
.clone
())
.unwrap
();
([
mesh_pipeline
],
framebuffers
)
}
}
This diff is collapsed.
Click to expand it.
src/objects.rs
0 → 100644
+
119
−
0
View file @
6bdd6c04
use
std
::{
collections
::
HashMap
,
io
::
Read
,
sync
::
Arc
};
use
bytemuck
::{
Pod
,
Zeroable
};
use
cgmath
::{
Deg
,
Euler
,
Matrix3
,
Point3
,
SquareMatrix
,
Vector3
};
use
obj
::{
LoadConfig
,
ObjData
};
use
vulkano
::{
buffer
::{
BufferUsage
,
CpuAccessibleBuffer
},
impl_vertex
,
};
use
crate
::
MemoryAllocator
;
pub
const
PLATONIC_SOLIDS
:
[(
&
str
,
&
[
u8
]);
1
]
=
[(
"Buny"
,
include_bytes!
(
"bunny.obj"
))];
// We now create a buffer that will store the shape of our triangle.
// We use #[repr(C)] here to force rustc to not do anything funky with our data, although for this
// particular example, it doesn't actually change the in-memory representation.
#[repr(C)]
#[derive(Clone,
Copy,
Debug,
Default,
Zeroable,
Pod)]
pub
struct
Vertex
{
position
:
[
f32
;
3
],
normal
:
[
f32
;
3
],
}
impl_vertex!
(
Vertex
,
position
,
normal
);
#[derive(Debug)]
pub
struct
Mesh
{
pub
name
:
String
,
pub
vertices
:
Arc
<
CpuAccessibleBuffer
<
[
Vertex
]
>>
,
pub
indices
:
Arc
<
CpuAccessibleBuffer
<
[
u32
]
>>
,
pub
pos
:
Point3
<
f32
>
,
pub
rot
:
Euler
<
Deg
<
f32
>>
,
pub
scale
:
f32
,
}
pub
fn
load_obj
(
memory_allocator
:
&
MemoryAllocator
,
input
:
&
mut
dyn
Read
,
name
:
String
)
->
Mesh
{
let
object
=
ObjData
::
load_buf_with_config
(
input
,
LoadConfig
::
default
())
.unwrap
();
let
mut
vertices
=
vec!
[];
let
mut
indices
=
vec!
[];
let
mut
temp_hash_map
=
HashMap
::
<
(
u32
,
u32
),
u32
>
::
new
();
// We're gonna have to remap all the indices that OBJ uses. Annoying.
// Get each pair of vertex position to vertex normal and assign it a new index. This might duplicate
// vertices or normals but each *pair* needs a unique index
// Uses the hash map to check that we're not duplicating unnecessarily
for
g
in
&
object
.objects
[
0
]
.groups
{
for
p
in
&
g
.polys
{
for
v
in
&
p
.0
{
//println!("{:?}", v);
let
mapping
=
((
v
.0
)
as
u32
,
(
v
.2
.unwrap_or
(
0
))
as
u32
);
if
let
Some
(
&
exist
)
=
&
temp_hash_map
.get
(
&
mapping
)
{
//println!("{:?}", exist);
indices
.push
(
exist
);
}
else
{
vertices
.push
(
Vertex
{
position
:
object
.position
[
mapping
.0
as
usize
],
normal
:
object
.normal
[
mapping
.1
as
usize
],
});
temp_hash_map
.insert
(
mapping
,
(
vertices
.len
()
-
1
)
as
u32
);
indices
.push
((
vertices
.len
()
-
1
)
as
u32
);
}
}
}
}
let
vertex_buffer
=
CpuAccessibleBuffer
::
from_iter
(
memory_allocator
,
BufferUsage
{
vertex_buffer
:
true
,
..
BufferUsage
::
empty
()
},
false
,
vertices
,
)
.unwrap
();
let
index_buffer
=
CpuAccessibleBuffer
::
from_iter
(
memory_allocator
,
BufferUsage
{
index_buffer
:
true
,
..
BufferUsage
::
empty
()
},
false
,
indices
,
)
.unwrap
();
Mesh
{
vertices
:
vertex_buffer
,
indices
:
index_buffer
,
pos
:
Point3
{
x
:
0.
,
y
:
0.
,
z
:
0.
,
},
rot
:
Euler
::
new
(
Deg
(
0.
),
Deg
(
0.
),
Deg
(
0.
)),
scale
:
1.
,
name
,
}
}
#[derive(Debug)]
pub
struct
Light
{
pub
pos
:
Point3
<
f32
>
,
pub
colour
:
Vector3
<
f32
>
,
}
impl
Light
{
pub
fn
new
(
pos
:
[
f32
;
3
],
colour
:
[
f32
;
3
],
intensity
:
f32
)
->
Light
{
let
c
:
Vector3
<
f32
>
=
colour
.into
();
Light
{
pos
:
pos
.into
(),
colour
:
c
*
intensity
,
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment