feat: render with depth checking
This commit is contained in:
1 parent
a1aea8e2a5
commit
14fb61a4d5
5 files changed
+156
-111
No files matched your search
+100
-104
@@ -1,10 +1,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::alloc::Layout;
|
||||||
use crate::common::mesh::MeshRegistry;
|
use crate::common::mesh::MeshRegistry;
|
||||||
use crate::gpu::vertex3::Vertex3;
|
use crate::gpu::vertex3::Vertex3;
|
||||||
use crate::triangle;
|
use crate::triangle;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
|
|
||||||
use vulkano::command_buffer::allocator::{
|
use vulkano::command_buffer::allocator::{
|
||||||
StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
|
StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
|
||||||
};
|
};
|
||||||
@@ -17,12 +16,10 @@ use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
|||||||
use vulkano::device::{
|
use vulkano::device::{
|
||||||
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags,
|
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags,
|
||||||
};
|
};
|
||||||
use vulkano::image::view::ImageView;
|
use vulkano::image::view::{ImageView, ImageViewCreateInfo};
|
||||||
use vulkano::image::{Image, ImageUsage};
|
use vulkano::image::{Image, ImageAspects, ImageCreateInfo, ImageLayout, ImageSubresourceRange, ImageType, ImageUsage};
|
||||||
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions};
|
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions};
|
||||||
use vulkano::memory::allocator::{
|
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator};
|
||||||
AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator,
|
|
||||||
};
|
|
||||||
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
||||||
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
||||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
||||||
@@ -37,8 +34,9 @@ use vulkano::shader::ShaderModule;
|
|||||||
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
|
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano::{Validated, VulkanError, VulkanLibrary, swapchain, sync};
|
use vulkano::{Validated, VulkanError, VulkanLibrary, swapchain, sync};
|
||||||
use vulkano::descriptor_set::DescriptorSet;
|
use vulkano::format::{ClearValue, Format};
|
||||||
use vulkano::descriptor_set::layout::DescriptorSetLayout;
|
use vulkano::memory::MemoryType;
|
||||||
|
use vulkano::pipeline::graphics::depth_stencil::{DepthState, DepthStencilState};
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
use winit::event_loop::ActiveEventLoop;
|
use winit::event_loop::ActiveEventLoop;
|
||||||
@@ -63,7 +61,6 @@ struct VulkanContext {
|
|||||||
render_pass: Arc<RenderPass>,
|
render_pass: Arc<RenderPass>,
|
||||||
framebuffers: Vec<Arc<Framebuffer>>,
|
framebuffers: Vec<Arc<Framebuffer>>,
|
||||||
pipeline: Arc<GraphicsPipeline>,
|
pipeline: Arc<GraphicsPipeline>,
|
||||||
cmd_buffers: Vec<Arc<PrimaryAutoCommandBuffer>>,
|
|
||||||
mesh_registry: Arc<MeshRegistry>,
|
mesh_registry: Arc<MeshRegistry>,
|
||||||
instance_registry: Arc<InstanceRegistry>,
|
instance_registry: Arc<InstanceRegistry>,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
@@ -150,12 +147,18 @@ impl VulkanContext {
|
|||||||
format: swapchain.image_format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
load_op: Clear,
|
load_op: Clear,
|
||||||
store_op: Store,
|
store_op: Store
|
||||||
|
},
|
||||||
|
depth: {
|
||||||
|
format: Format::D16_UNORM,
|
||||||
|
samples: 1,
|
||||||
|
load_op: Clear,
|
||||||
|
store_op: DontCare,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pass: {
|
pass: {
|
||||||
color: [color],
|
color: [color],
|
||||||
depth_stencil: {},
|
depth_stencil: {depth},
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -164,7 +167,11 @@ impl VulkanContext {
|
|||||||
let frag_shader = triangle::load_fragment(device.clone())
|
let frag_shader = triangle::load_fragment(device.clone())
|
||||||
.map_err(|e| format!("Failed to load fragment shader: {e}"))?;
|
.map_err(|e| format!("Failed to load fragment shader: {e}"))?;
|
||||||
|
|
||||||
let framebuffers = Self::create_framebuffers(&images, &render_pass)?;
|
let framebuffers = Self::create_framebuffers(
|
||||||
|
mem_allocator.clone(),
|
||||||
|
&images,
|
||||||
|
&render_pass
|
||||||
|
)?;
|
||||||
|
|
||||||
let image_extents = swapchain.image_extent();
|
let image_extents = swapchain.image_extent();
|
||||||
|
|
||||||
@@ -206,17 +213,6 @@ impl VulkanContext {
|
|||||||
instance_registry.clone()
|
instance_registry.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
let cmd_buffers = Self::get_command_buffers(
|
|
||||||
&cmd_allocator,
|
|
||||||
&queue,
|
|
||||||
&pipeline,
|
|
||||||
&framebuffers,
|
|
||||||
&camera,
|
|
||||||
&camera_resources,
|
|
||||||
mesh_registry.clone(),
|
|
||||||
batches,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window,
|
window,
|
||||||
device,
|
device,
|
||||||
@@ -231,7 +227,6 @@ impl VulkanContext {
|
|||||||
frag_shader,
|
frag_shader,
|
||||||
framebuffers,
|
framebuffers,
|
||||||
pipeline,
|
pipeline,
|
||||||
cmd_buffers,
|
|
||||||
mesh_registry,
|
mesh_registry,
|
||||||
instance_registry,
|
instance_registry,
|
||||||
camera,
|
camera,
|
||||||
@@ -264,11 +259,11 @@ impl VulkanContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild command buffers
|
// Rebuild command buffers
|
||||||
let cmd_buffers = Self::get_command_buffers(
|
let cmd_buffer = Self::get_command_buffer(
|
||||||
&self.cmd_allocator,
|
&self.cmd_allocator,
|
||||||
&self.queue,
|
&self.queue,
|
||||||
&self.pipeline,
|
&self.pipeline,
|
||||||
&self.framebuffers,
|
self.framebuffers[image_idx as usize].clone(),
|
||||||
&self.camera,
|
&self.camera,
|
||||||
&self.camera_resources,
|
&self.camera_resources,
|
||||||
self.mesh_registry.clone(),
|
self.mesh_registry.clone(),
|
||||||
@@ -283,7 +278,7 @@ impl VulkanContext {
|
|||||||
.join(acquire_future)
|
.join(acquire_future)
|
||||||
.then_execute(
|
.then_execute(
|
||||||
self.queue.clone(),
|
self.queue.clone(),
|
||||||
cmd_buffers[image_idx as usize].clone(),
|
cmd_buffer.clone(),
|
||||||
)?
|
)?
|
||||||
.then_swapchain_present(
|
.then_swapchain_present(
|
||||||
self.queue.clone(),
|
self.queue.clone(),
|
||||||
@@ -350,9 +345,24 @@ impl VulkanContext {
|
|||||||
|
|
||||||
/// Creates a new [`Framebuffer`] for each swapchain image.
|
/// Creates a new [`Framebuffer`] for each swapchain image.
|
||||||
fn create_framebuffers(
|
fn create_framebuffers(
|
||||||
|
alloc: Arc<dyn MemoryAllocator>,
|
||||||
images: &Vec<Arc<Image>>,
|
images: &Vec<Arc<Image>>,
|
||||||
render_pass: &Arc<RenderPass>,
|
render_pass: &Arc<RenderPass>,
|
||||||
) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
|
) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
|
||||||
|
let depth_buffer = ImageView::new_default(
|
||||||
|
Image::new(
|
||||||
|
alloc.clone(),
|
||||||
|
ImageCreateInfo {
|
||||||
|
image_type: ImageType::Dim2d,
|
||||||
|
format: Format::D16_UNORM,
|
||||||
|
extent: images[0].extent(),
|
||||||
|
usage: ImageUsage::DEPTH_STENCIL_ATTACHMENT | ImageUsage::TRANSIENT_ATTACHMENT,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo::default()
|
||||||
|
)?
|
||||||
|
)?;
|
||||||
|
|
||||||
let framebuffers = images
|
let framebuffers = images
|
||||||
.iter()
|
.iter()
|
||||||
.map(|image| {
|
.map(|image| {
|
||||||
@@ -361,7 +371,7 @@ impl VulkanContext {
|
|||||||
Framebuffer::new(
|
Framebuffer::new(
|
||||||
render_pass.clone(),
|
render_pass.clone(),
|
||||||
FramebufferCreateInfo {
|
FramebufferCreateInfo {
|
||||||
attachments: vec![view],
|
attachments: vec![view, depth_buffer.clone()],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -413,7 +423,6 @@ impl VulkanContext {
|
|||||||
device.clone(),
|
device.clone(),
|
||||||
None,
|
None,
|
||||||
GraphicsPipelineCreateInfo {
|
GraphicsPipelineCreateInfo {
|
||||||
flags: Default::default(),
|
|
||||||
stages: stages.into_iter().collect(),
|
stages: stages.into_iter().collect(),
|
||||||
vertex_input_state: Some(vertex_input_state),
|
vertex_input_state: Some(vertex_input_state),
|
||||||
input_assembly_state: Some(InputAssemblyState::default()),
|
input_assembly_state: Some(InputAssemblyState::default()),
|
||||||
@@ -429,86 +438,80 @@ impl VulkanContext {
|
|||||||
)),
|
)),
|
||||||
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
||||||
subpass: Some(subpass.into()),
|
subpass: Some(subpass.into()),
|
||||||
|
depth_stencil_state: Some(DepthStencilState {
|
||||||
|
depth: Some(DepthState::simple()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
..GraphicsPipelineCreateInfo::layout(layout)
|
..GraphicsPipelineCreateInfo::layout(layout)
|
||||||
},
|
},
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`PrimaryAutoCommandBuffer`] for each swapchain image.
|
/// Creates a [`PrimaryAutoCommandBuffer`] for each swapchain image.
|
||||||
fn get_command_buffers(
|
fn get_command_buffer(
|
||||||
cmd_allocator: &Arc<StandardCommandBufferAllocator>,
|
cmd_allocator: &Arc<StandardCommandBufferAllocator>,
|
||||||
queue: &Arc<Queue>,
|
queue: &Arc<Queue>,
|
||||||
pipeline: &Arc<GraphicsPipeline>,
|
pipeline: &Arc<GraphicsPipeline>,
|
||||||
framebuffers: &Vec<Arc<Framebuffer>>,
|
framebuffer: Arc<Framebuffer>,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
camera_resources: &CameraResources,
|
camera_resources: &CameraResources,
|
||||||
mesh_registry: Arc<MeshRegistry>,
|
mesh_registry: Arc<MeshRegistry>,
|
||||||
render_batches: Vec<RenderBatch>,
|
render_batches: Vec<RenderBatch>,
|
||||||
) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> {
|
) -> Result<Arc<PrimaryAutoCommandBuffer>, Box<dyn Error>> {
|
||||||
let buffers = framebuffers
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
.iter()
|
cmd_allocator.clone(),
|
||||||
.filter_map(|framebuffer| {
|
queue.queue_family_index(),
|
||||||
let mut builder = AutoCommandBufferBuilder::primary(
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
cmd_allocator.clone(),
|
)
|
||||||
queue.queue_family_index(),
|
.expect("Couldn't create command buffer builder");
|
||||||
CommandBufferUsage::OneTimeSubmit,
|
|
||||||
)
|
|
||||||
.expect("Couldn't create command buffer builder");
|
|
||||||
|
|
||||||
unsafe {
|
builder
|
||||||
builder
|
.begin_render_pass(
|
||||||
.begin_render_pass(
|
RenderPassBeginInfo {
|
||||||
RenderPassBeginInfo {
|
clear_values: vec![
|
||||||
clear_values: vec![Some([0.1, 0.1, 0.1, 1.0].into())],
|
Some([0.1, 0.1, 0.1, 0.5].into()),
|
||||||
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
Some(1f32.into()),
|
||||||
},
|
],
|
||||||
SubpassBeginInfo {
|
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
||||||
contents: SubpassContents::Inline,
|
},
|
||||||
..Default::default()
|
SubpassBeginInfo {
|
||||||
},
|
contents: SubpassContents::Inline,
|
||||||
)
|
..Default::default()
|
||||||
.unwrap()
|
},
|
||||||
.set_viewport(
|
)?
|
||||||
0,
|
.set_viewport(
|
||||||
[camera.viewport()].into_iter().collect()
|
0,
|
||||||
)
|
[camera.viewport()].into_iter().collect()
|
||||||
.unwrap()
|
)?
|
||||||
.bind_descriptor_sets(
|
.bind_descriptor_sets(
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
pipeline.layout().clone(),
|
pipeline.layout().clone(),
|
||||||
0,
|
0,
|
||||||
camera_resources.descriptor_set().clone(),
|
camera_resources.descriptor_set().clone(),
|
||||||
)
|
)?
|
||||||
.unwrap()
|
.bind_pipeline_graphics(pipeline.clone())?
|
||||||
.bind_pipeline_graphics(pipeline.clone())
|
.bind_vertex_buffers(0, mesh_registry.vertex_buffer.as_ref().clone())?
|
||||||
.unwrap()
|
.bind_index_buffer(mesh_registry.index_buffer.as_ref().clone())?;
|
||||||
.bind_vertex_buffers(0, mesh_registry.vertex_buffer.as_ref().clone())
|
|
||||||
.unwrap()
|
|
||||||
.bind_index_buffer(mesh_registry.index_buffer.as_ref().clone())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
render_batches.iter().for_each(|batch| {
|
unsafe {
|
||||||
// Grab mesh information
|
render_batches.iter().for_each(|batch| {
|
||||||
let mesh = mesh_registry.get(&batch.mesh_id)
|
// Grab mesh information
|
||||||
.expect("Mesh does not exist in registry");
|
let mesh = mesh_registry.get(&batch.mesh_id)
|
||||||
|
.expect("Mesh does not exist in registry");
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.bind_vertex_buffers(1, batch.instance_buffer.clone())
|
.bind_vertex_buffers(1, batch.instance_buffer.clone())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.draw_indexed(mesh.index_count as u32, batch.instance_count, mesh.index_loc as u32, mesh.vertex_loc as i32, 0)
|
.draw_indexed(mesh.index_count as u32, batch.instance_count, mesh.index_loc as u32, mesh.vertex_loc as i32, 0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
builder
|
builder.end_render_pass(SubpassEndInfo::default())?;
|
||||||
.end_render_pass(SubpassEndInfo::default())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.build().ok()
|
let buffer = builder.build()?;
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(buffers)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles recreation logic for the [`Swapchain`] by using the current information and any new
|
/// Handles recreation logic for the [`Swapchain`] by using the current information and any new
|
||||||
@@ -532,7 +535,11 @@ impl VulkanContext {
|
|||||||
|
|
||||||
// Recreate the framebuffers, which depend on the swapchain.
|
// Recreate the framebuffers, which depend on the swapchain.
|
||||||
let new_framebuffers =
|
let new_framebuffers =
|
||||||
Self::create_framebuffers(&self.swapchain_images, &self.render_pass)?;
|
Self::create_framebuffers(
|
||||||
|
self.mem_allocator.clone(),
|
||||||
|
&self.swapchain_images,
|
||||||
|
&self.render_pass
|
||||||
|
)?;
|
||||||
|
|
||||||
self.framebuffers = new_framebuffers;
|
self.framebuffers = new_framebuffers;
|
||||||
|
|
||||||
@@ -553,19 +560,7 @@ impl VulkanContext {
|
|||||||
self.instance_registry.clone()
|
self.instance_registry.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
let command_buffers = Self::get_command_buffers(
|
|
||||||
&self.cmd_allocator,
|
|
||||||
&self.queue,
|
|
||||||
&new_pipeline,
|
|
||||||
&self.framebuffers,
|
|
||||||
&self.camera,
|
|
||||||
&self.camera_resources,
|
|
||||||
self.mesh_registry.clone(),
|
|
||||||
batches
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.pipeline = new_pipeline;
|
self.pipeline = new_pipeline;
|
||||||
self.cmd_buffers = command_buffers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -604,6 +599,7 @@ impl MainApplication {
|
|||||||
library,
|
library,
|
||||||
InstanceCreateInfo {
|
InstanceCreateInfo {
|
||||||
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
||||||
|
enabled_layers: vec!["VK_LAYER_KHRONOS_validation".to_string()],
|
||||||
enabled_extensions: required_extensions,
|
enabled_extensions: required_extensions,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ impl Camera {
|
|||||||
extents: impl Into<Vector2<u32>>
|
extents: impl Into<Vector2<u32>>
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let extents = extents.into();
|
let extents = extents.into();
|
||||||
let position = Vector3::new(-10.0, 10.0, -10.0);
|
let position = Vector3::new(-7.0, 7.0, -7.0);
|
||||||
let target = Vector3::zeros();
|
let target = Vector3::zeros();
|
||||||
|
|
||||||
// Traveling along this vector moves us toward the target.
|
// Traveling along this vector moves us toward the target.
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use vulkano::buffer::BufferContents;
|
||||||
use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer};
|
|
||||||
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter};
|
|
||||||
use crate::common::camera::Camera;
|
use crate::common::camera::Camera;
|
||||||
|
|
||||||
#[derive(BufferContents)]
|
#[derive(BufferContents)]
|
||||||
@@ -8,6 +6,7 @@ use crate::common::camera::Camera;
|
|||||||
pub struct CameraUniform {
|
pub struct CameraUniform {
|
||||||
pub view: [[f32; 4]; 4],
|
pub view: [[f32; 4]; 4],
|
||||||
pub proj: [[f32; 4]; 4],
|
pub proj: [[f32; 4]; 4],
|
||||||
|
pub position: [f32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Camera> for CameraUniform {
|
impl From<Camera> for CameraUniform {
|
||||||
@@ -24,6 +23,7 @@ impl From<&Camera> for CameraUniform {
|
|||||||
Self {
|
Self {
|
||||||
view: view.into(),
|
view: view.into(),
|
||||||
proj: proj.into(),
|
proj: proj.into(),
|
||||||
|
position: camera.position.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,48 @@
|
|||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
|
// Per-fragment - mesh dependent information.
|
||||||
|
layout(location = 0) in vec3 inFragPosition;
|
||||||
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
||||||
|
// Per-frame information - CameraUniform struct
|
||||||
|
layout(set = 0, binding = 0) uniform CameraUniform {
|
||||||
|
mat4 view;
|
||||||
|
mat4 projection;
|
||||||
|
vec3 position;
|
||||||
|
} camera;
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
// Default mesh color - no textures for now.
|
||||||
|
vec3 objectColor = vec3(0.1, 0.1, 0.1);
|
||||||
|
// Default light information - we aren't going to edit light information until we know more about it.
|
||||||
|
vec3 lightPosition = vec3(0.0, 10000.0, 0.0);
|
||||||
|
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
// Ambient lighting - literally just a base color percentage.
|
||||||
|
vec3 ambient = 0.1 * lightColor;
|
||||||
|
|
||||||
|
// Diffuse lighting - brighter on faces that catch more light.
|
||||||
|
// This is the dot product of the frag to the light, and the frag normal.
|
||||||
|
vec3 norm = normalize(inNormal);
|
||||||
|
vec3 lightDir = normalize(lightPosition - inFragPosition);
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * lightColor;
|
||||||
|
|
||||||
|
// Specular lighting - shiny spots corresponding to reflected light toward the camera.
|
||||||
|
// The direction from the fragment to the camera.
|
||||||
|
vec3 viewDirection = normalize(camera.position - inFragPosition);
|
||||||
|
// The direction of reflection of light - the inverse of the light to the surface.
|
||||||
|
vec3 reflectDirection = reflect(-lightDir, norm);
|
||||||
|
// The specular is basically like diffuse, plus an extra "specular strength". There's also a coarseness, which
|
||||||
|
// determines the size of the "dot" created from the shading itself.
|
||||||
|
float specStrength = 0.5;
|
||||||
|
int specCoarseness = 32;
|
||||||
|
float spec = pow(max(dot(viewDirection, reflectDirection), 0.0), specCoarseness);
|
||||||
|
vec3 specular = specStrength * spec * lightColor;
|
||||||
|
|
||||||
|
vec3 result = (ambient + diffuse + specular) * objectColor;
|
||||||
|
|
||||||
|
f_color = vec4(result, 1.0);
|
||||||
}
|
}
|
||||||
@@ -14,13 +14,21 @@ layout(location = 5) in vec4 transform_col4;
|
|||||||
layout(set = 0, binding = 0) uniform CameraUniform {
|
layout(set = 0, binding = 0) uniform CameraUniform {
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
|
vec3 position;
|
||||||
} camera;
|
} camera;
|
||||||
|
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
layout(location = 0) out vec3 outFragPosition;
|
||||||
|
layout(location = 1) out vec3 outNormal;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// We then multiply each vertex by its transform to find the correct location in the scene.
|
// We then multiply each vertex by its transform to find the correct location in the scene.
|
||||||
mat4 transform = mat4(transform_col1, transform_col2, transform_col3, transform_col4);
|
mat4 model = mat4(transform_col1, transform_col2, transform_col3, transform_col4);
|
||||||
|
|
||||||
mat4 mvp = camera.projection * camera.view * transform;
|
mat4 mvp = camera.projection * camera.view * model;
|
||||||
|
|
||||||
gl_Position = mvp * vec4(position, 1.0f);
|
gl_Position = mvp * vec4(position, 1.0f);
|
||||||
|
outFragPosition = vec3(model * vec4(position, 1.0));
|
||||||
|
outNormal = normal;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user