added raymarching demo for testing
This commit is contained in:
@@ -58,9 +58,16 @@ fn main() {
|
|||||||
let mut compiler = shaderc::Compiler::new().expect("Unable to create shader compiler");
|
let mut compiler = shaderc::Compiler::new().expect("Unable to create shader compiler");
|
||||||
for shader in shaders {
|
for shader in shaders {
|
||||||
println!("cargo:rerun-if-changed={}", shader.src_path.as_os_str().to_str().unwrap());
|
println!("cargo:rerun-if-changed={}", shader.src_path.as_os_str().to_str().unwrap());
|
||||||
let compiled = compiler.compile_into_spirv(&shader.source, shader.kind, &shader.src_path.to_str().unwrap(), "main", Some(&options)).unwrap();
|
let compiled = compiler.compile_into_spirv(&shader.source, shader.kind, &shader.src_path.to_str().unwrap(), "main", Some(&options))
|
||||||
|
.expect("Shader error:");
|
||||||
write(shader.spv_path, compiled.as_binary_u8()).unwrap();
|
write(shader.spv_path, compiled.as_binary_u8()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rebuild if any of the cginc change
|
||||||
|
for path_str in glob("./src/shaders/**/*.cginc").unwrap() {
|
||||||
|
let path = path_str.unwrap();
|
||||||
|
println!("cargo:rerun-if-changed={}", path.as_os_str().to_str().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use winit::event::Event;
|
use winit::event::Event;
|
||||||
use winit::{window::Window, dpi::PhysicalSize, event::WindowEvent};
|
use winit::{window::Window, dpi::PhysicalSize};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
use crate::vertex::Vertex;
|
use crate::vertex::Vertex;
|
||||||
@@ -9,11 +9,14 @@ use crate::camera::Camera;
|
|||||||
use crate::uniforms::Uniforms;
|
use crate::uniforms::Uniforms;
|
||||||
use crate::camera_controller::CameraController;
|
use crate::camera_controller::CameraController;
|
||||||
|
|
||||||
|
|
||||||
|
// A B
|
||||||
|
// C D
|
||||||
const VERTICES: &[Vertex] = &[
|
const VERTICES: &[Vertex] = &[
|
||||||
Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] },
|
Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] }, // A
|
||||||
Vertex { position: [ 1.0, 1.0, 0.0], uv: [1.0, 0.0] },
|
Vertex { position: [ 1.0, 1.0, 0.0], uv: [1.0, 0.0] }, // B
|
||||||
Vertex { position: [ 1.0,-1.0, 0.0], uv: [1.0, 1.0] },
|
Vertex { position: [ 1.0,-1.0, 0.0], uv: [1.0, 1.0] }, // C
|
||||||
Vertex { position: [-1.0,-1.0, 0.0], uv: [0.0, 1.0] },
|
Vertex { position: [-1.0,-1.0, 0.0], uv: [0.0, 1.0] }, // D
|
||||||
];
|
];
|
||||||
|
|
||||||
const INDICES: &[u16] = &[
|
const INDICES: &[u16] = &[
|
||||||
@@ -156,7 +159,7 @@ impl App {
|
|||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
visibility: wgpu::ShaderStage::VERTEX,
|
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Buffer {
|
ty: wgpu::BindingType::Buffer {
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
has_dynamic_offset: false,
|
has_dynamic_offset: false,
|
||||||
@@ -213,9 +216,9 @@ impl App {
|
|||||||
|
|
||||||
// Cam
|
// Cam
|
||||||
let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32;
|
let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32;
|
||||||
let camera = Camera::new((0.0, 0.0, 2.0).into(), (0.0, 0.0, -1.0).into(), aspect);
|
let camera = Camera::new(aspect, 45.0);
|
||||||
let mut uniforms = Uniforms::new();
|
let mut uniforms = Uniforms::new();
|
||||||
uniforms.update_projection_matrix(&camera);
|
uniforms.update(&camera);
|
||||||
let camera_controller = CameraController::new();
|
let camera_controller = CameraController::new();
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
@@ -260,7 +263,7 @@ impl App {
|
|||||||
self.camera_controller.update_camera(&mut self.camera, delta_time);
|
self.camera_controller.update_camera(&mut self.camera, delta_time);
|
||||||
|
|
||||||
// Update projection matrix buffer
|
// Update projection matrix buffer
|
||||||
self.uniforms.update_projection_matrix(&self.camera);
|
self.uniforms.update(&self.camera);
|
||||||
self.queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[self.uniforms]));
|
self.queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[self.uniforms]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -20,13 +20,13 @@ pub struct Camera {
|
|||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
|
|
||||||
pub fn new(position: Point3<f32>, forward: Vector3<f32>, aspect: f32) -> Self {
|
pub fn new(aspect: f32, fov: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
position,
|
position: (0.0, 0.0, 0.0).into(),
|
||||||
forward,
|
forward: (0.0, 0.0, 1.0).into(),
|
||||||
up: Vector3::unit_y(),
|
up: Vector3::unit_y(),
|
||||||
aspect,
|
aspect,
|
||||||
fovy: 45.0,
|
fovy: fov,
|
||||||
znear: 0.1,
|
znear: 0.1,
|
||||||
zfar: 100.0
|
zfar: 100.0
|
||||||
}
|
}
|
||||||
@@ -36,9 +36,11 @@ impl Camera {
|
|||||||
self.aspect = aspect;
|
self.aspect = aspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn projection_matrix(&self) -> Matrix4<f32> {
|
pub fn proj_matrix(&self) -> Matrix4<f32> {
|
||||||
let view = Matrix4::look_to_rh(self.position, self.forward, self.up);
|
return OPENGL_TO_WGPU_MATRIX * cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar);
|
||||||
let proj = cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar);
|
}
|
||||||
return OPENGL_TO_WGPU_MATRIX * proj * view;
|
|
||||||
|
pub fn view_matrix(&self) -> Matrix4<f32> {
|
||||||
|
return OPENGL_TO_WGPU_MATRIX * Matrix4::look_to_rh(self.position, self.forward, self.up);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
// Returns nearest distance to and object id from given point
|
||||||
|
vec2 map(in vec3 pos)
|
||||||
|
{
|
||||||
|
vec2 d1 = vec2(sdPlane(pos), 1);
|
||||||
|
vec2 d2 = vec2(sdSphere(pos - vec3(0.0, 2.0, 0.0)), 2);
|
||||||
|
vec2 d3 = vec2(sdSphere(pos - vec3(2.0, 1.2, 2.0)), 3);
|
||||||
|
return sdUnion(sdUnion(d1, d2), d3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns distance to and object id that has been intersected by ray
|
||||||
|
vec2 intersect(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
float depth = NEAR;
|
||||||
|
for(int i=0;i<MAX_STEPS;i++)
|
||||||
|
{
|
||||||
|
// Travel through map
|
||||||
|
vec2 dist = map(ro + rd * depth);
|
||||||
|
if(dist.x < EPSILON)
|
||||||
|
{
|
||||||
|
// Hit something
|
||||||
|
return vec2(depth, dist.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move further
|
||||||
|
depth += dist.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing found
|
||||||
|
return vec2(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 estimateNormal(vec3 p)
|
||||||
|
{
|
||||||
|
return normalize(vec3(
|
||||||
|
map(vec3(p.x + EPSILON, p.y, p.z)).x - map(vec3(p.x - EPSILON, p.y, p.z)).x,
|
||||||
|
map(vec3(p.x, p.y + EPSILON, p.z)).x - map(vec3(p.x, p.y - EPSILON, p.z)).x,
|
||||||
|
map(vec3(p.x, p.y, p.z + EPSILON)).x - map(vec3(p.x, p.y, p.z - EPSILON)).x
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 raymarch(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
// Light dir
|
||||||
|
vec3 ld = normalize(vec3(-0.5, 2.0, -0.2));
|
||||||
|
|
||||||
|
vec2 result = intersect(ro, rd);
|
||||||
|
if(result.y > 0.0)
|
||||||
|
{
|
||||||
|
// Calculate intersection point, normal vector and reflection vector
|
||||||
|
vec3 pos = ro + rd * result.x;
|
||||||
|
vec3 nor = estimateNormal(pos);
|
||||||
|
vec3 ref = reflect(rd, nor);
|
||||||
|
|
||||||
|
// Light
|
||||||
|
vec3 light = vec3(1);
|
||||||
|
|
||||||
|
float dif = clamp( dot( nor, ld ), 0.0, 1.0 );
|
||||||
|
light += 2.20*dif*vec3(1.30,1.00,0.70);
|
||||||
|
|
||||||
|
vec3 hal = normalize( ld-rd );
|
||||||
|
float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
|
||||||
|
spe *= dif;
|
||||||
|
spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,ld),0.0,1.0),5.0);
|
||||||
|
light += 5.00*spe*vec3(1.30,1.00,0.70);
|
||||||
|
|
||||||
|
//float diffuse = max(dot(norm, -ld), 0);
|
||||||
|
//color *= diffuse;
|
||||||
|
|
||||||
|
//vec3 ldr = normalize(reflect(-ld, norm));
|
||||||
|
//float specular = max(dot(ldr, rd), 0.0);
|
||||||
|
//specular = pow(specular, 3);
|
||||||
|
//color += vec3(0.2) * specular;
|
||||||
|
|
||||||
|
//float scatter = pow(1.0-dot(rd, -norm), 2);
|
||||||
|
|
||||||
|
// Calculate color
|
||||||
|
vec3 color = vec3(0);
|
||||||
|
if(result.y == 1) color = vec3(0.0, 0.1, 0.01);
|
||||||
|
else if(result.y == 2) color = vec3(0.5, 0.7, 0.05);
|
||||||
|
else if(result.y == 3) color = vec3(0.0, 0.2, 0.7);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
color *= light;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return vec3(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-3
@@ -1,13 +1,28 @@
|
|||||||
// shader.frag
|
// shader.frag
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
// Variables
|
||||||
layout(location=0) in vec2 vert_uv;
|
layout(location=0) in vec2 vert_uv;
|
||||||
layout(location=0) out vec4 frag_color;
|
layout(location=0) out vec4 out_color;
|
||||||
|
|
||||||
layout(set=0, binding=0) uniform texture2D tex;
|
layout(set=0, binding=0) uniform texture2D tex;
|
||||||
layout(set=0, binding=1) uniform sampler tex_smp;
|
layout(set=0, binding=1) uniform sampler tex_smp;
|
||||||
|
|
||||||
|
// Defines
|
||||||
|
#define PI 3.141592
|
||||||
|
#define EPSILON 0.01
|
||||||
|
#define NEAR 0.01
|
||||||
|
#define MAX_STEPS 200
|
||||||
|
|
||||||
|
// Include
|
||||||
|
#include "shapes.cginc"
|
||||||
|
#include "raymarching.cginc"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
frag_color = texture(sampler2D(tex, tex_smp), vert_uv);
|
// Calculate ray
|
||||||
|
vec3 ro = vec3(0.0, 2, -6.0); // Ray origin
|
||||||
|
vec3 rd = normalize(vec3(vert_uv - vec2(0.5, 0.5), 1.001)); // Ray direction
|
||||||
|
|
||||||
|
// Render
|
||||||
|
out_color = vec4(raymarch(ro, rd), 1);
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,14 @@ layout(location=0) out vec2 vert_uv;
|
|||||||
|
|
||||||
layout(set=1, binding=0) uniform Uniforms
|
layout(set=1, binding=0) uniform Uniforms
|
||||||
{
|
{
|
||||||
mat4 view_projection;
|
mat4 view; // world to camera
|
||||||
|
mat4 proj; // camera to screen
|
||||||
|
mat4 proj_inv; // screen to camera
|
||||||
|
vec3 cam_pos; // camera position
|
||||||
};
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vert_uv = in_uv;
|
vert_uv = in_uv;
|
||||||
gl_Position = view_projection * vec4(in_position, 1.0);
|
gl_Position = vec4(in_position, 1.0);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
float sdSphere(in vec3 pos)
|
||||||
|
{
|
||||||
|
return length(pos) - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdPlane(in vec3 pos)
|
||||||
|
{
|
||||||
|
return pos.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 sdUnion(vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
return (a.x < b.x) ? a : b;
|
||||||
|
}
|
||||||
+16
-7
@@ -4,20 +4,29 @@ use crate::camera::Camera;
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct Uniforms {
|
pub struct Uniforms {
|
||||||
view_proj: [[f32; 4]; 4],
|
view: [[f32; 4]; 4],
|
||||||
|
proj: [[f32; 4]; 4],
|
||||||
|
proj_inv: [[f32; 4]; 4],
|
||||||
|
cam_pos: [f32; 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Uniforms {
|
impl Uniforms {
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self::default()
|
||||||
view_proj: cgmath::Matrix4::identity().into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_projection_matrix(&mut self, camera: &Camera) {
|
pub fn update(&mut self, camera: &Camera) {
|
||||||
self.view_proj = camera.projection_matrix().into();
|
let view = camera.view_matrix();
|
||||||
|
let proj = camera.proj_matrix();
|
||||||
|
let proj_inv = proj.invert().unwrap();
|
||||||
|
let cam_pos = camera.position;
|
||||||
|
|
||||||
|
self.view = view.into();
|
||||||
|
self.proj = proj.into();
|
||||||
|
self.proj_inv = proj_inv.into();
|
||||||
|
self.cam_pos = cam_pos.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user