150 lines
4.5 KiB
Rust
150 lines
4.5 KiB
Rust
use macroquad::prelude::{self as mq, UniformDesc};
|
|
|
|
#[macroquad::main("Normal Shading")]
|
|
async fn main() {
|
|
let vertex = include_str!("shader.vert");
|
|
let fragment = include_str!("shader.frag");
|
|
|
|
let material = mq::load_material(
|
|
mq::ShaderSource::Glsl { vertex, fragment },
|
|
mq::MaterialParams {
|
|
pipeline_params: mq::PipelineParams {
|
|
depth_test: mq::Comparison::LessOrEqual,
|
|
depth_write: true,
|
|
..Default::default()
|
|
},
|
|
uniforms: vec![UniformDesc::new(
|
|
"render_normals_bool",
|
|
mq::UniformType::Int1,
|
|
)],
|
|
..Default::default()
|
|
},
|
|
)
|
|
.unwrap();
|
|
material.set_uniform("render_normals_bool", 1);
|
|
|
|
loop {
|
|
mq::clear_background(mq::GRAY);
|
|
mq::set_camera(&mq::Camera3D {
|
|
position: mq::vec3(4.0, 4.0, 4.0),
|
|
target: mq::vec3(0.0, 0.0, 0.0),
|
|
up: mq::vec3(0.0, 1.0, 0.0),
|
|
..Default::default()
|
|
});
|
|
|
|
mq::gl_use_material(&material);
|
|
|
|
draw_cuboid(mq::vec3(3.0, 0.0, 0.0), mq::vec3(1.0, 2.0, 3.0), mq::RED);
|
|
|
|
mq::gl_use_default_material();
|
|
mq::set_default_camera();
|
|
mq::next_frame().await;
|
|
}
|
|
}
|
|
|
|
pub fn generate_normals_smooth(vertexes: &mut Vec<mq::Vertex>, indices: &[u16]) {
|
|
for v in vertexes.iter_mut() {
|
|
v.normal = mq::vec4(0.0, 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
for i in 0..(indices.len() / 3) {
|
|
let idx0 = indices[i * 3 + 0] as usize;
|
|
let idx1 = indices[i * 3 + 1] as usize;
|
|
let idx2 = indices[i * 3 + 2] as usize;
|
|
|
|
let pos0 = vertexes[idx0].position;
|
|
let pos1 = vertexes[idx1].position;
|
|
let pos2 = vertexes[idx2].position;
|
|
|
|
let side1 = pos1 - pos0;
|
|
let side2 = pos2 - pos0;
|
|
let normal = side1.cross(side2);
|
|
|
|
let normal_vec4 = mq::vec4(normal.x, normal.y, normal.z, 0.0);
|
|
|
|
vertexes[idx0].normal = vertexes[idx0].normal + normal_vec4;
|
|
vertexes[idx1].normal = vertexes[idx1].normal + normal_vec4;
|
|
vertexes[idx2].normal = vertexes[idx2].normal + normal_vec4;
|
|
}
|
|
|
|
for v in vertexes.iter_mut() {
|
|
v.normal.z = 0.0;
|
|
let normalized = v.normal.normalize();
|
|
v.normal = normalized;
|
|
}
|
|
}
|
|
pub fn draw_cuboid(center: mq::Vec3, size: mq::Vec3, color: mq::Color) {
|
|
use mq::{Vec2, Vec3, Vertex};
|
|
let hs = size * 0.5;
|
|
let mut positions = [
|
|
Vec3::new(-hs.x, -hs.y, -hs.z),
|
|
Vec3::new(hs.x, -hs.y, -hs.z),
|
|
Vec3::new(hs.x, hs.y, -hs.z),
|
|
Vec3::new(-hs.x, hs.y, -hs.z),
|
|
Vec3::new(-hs.x, -hs.y, hs.z),
|
|
Vec3::new(hs.x, -hs.y, hs.z),
|
|
Vec3::new(hs.x, hs.y, hs.z),
|
|
Vec3::new(-hs.x, hs.y, hs.z),
|
|
];
|
|
for i in 0..positions.len() {
|
|
positions[i] += center;
|
|
}
|
|
|
|
let faces = [
|
|
([0, 1, 2, 3], Vec3::new(0.0, 0.0, -1.0)), // Back
|
|
([5, 4, 7, 6], Vec3::new(0.0, 0.0, 1.0)), // Front
|
|
([4, 0, 3, 7], Vec3::new(-1.0, 0.0, 0.0)), // Left
|
|
([1, 5, 6, 2], Vec3::new(1.0, 0.0, 0.0)), // Right
|
|
([3, 2, 6, 7], Vec3::new(0.0, 1.0, 0.0)), // Up
|
|
([4, 5, 1, 0], Vec3::new(0.0, -1.0, 0.0)), // Down
|
|
];
|
|
|
|
let uvs = [
|
|
Vec2::new(0.0, 0.0),
|
|
Vec2::new(1.0, 0.0),
|
|
Vec2::new(1.0, 1.0),
|
|
Vec2::new(0.0, 1.0),
|
|
];
|
|
|
|
let mut vertices = [Vertex {
|
|
position: mq::Vec3::ZERO,
|
|
uv: mq::Vec2::ZERO,
|
|
color: color.into(),
|
|
normal: mq::Vec4::ZERO,
|
|
}; 24];
|
|
|
|
let mut vi = 0;
|
|
for (face, normal) in faces.iter() {
|
|
for (j, &corner) in face.iter().enumerate() {
|
|
let pos = positions[corner];
|
|
vertices[vi] = Vertex {
|
|
position: mq::vec3(pos.x, pos.y, pos.z),
|
|
uv: mq::vec2(uvs[j].x, uvs[j].y),
|
|
color: color.into(),
|
|
normal: mq::vec4(normal.x, normal.y, normal.z, 0.0),
|
|
};
|
|
vi += 1;
|
|
}
|
|
}
|
|
|
|
let mut indices = [0u16; 36];
|
|
for i in 0..6 {
|
|
let base = (i * 4) as u16;
|
|
let offset = i * 6;
|
|
indices[offset + 0] = base;
|
|
indices[offset + 1] = base + 1;
|
|
indices[offset + 2] = base + 2;
|
|
indices[offset + 3] = base;
|
|
indices[offset + 4] = base + 2;
|
|
indices[offset + 5] = base + 3;
|
|
}
|
|
generate_normals_smooth(&mut vertices.into(), &indices);
|
|
|
|
unsafe {
|
|
mq::get_internal_gl()
|
|
.quad_gl
|
|
.draw_mode(mq::DrawMode::Triangles);
|
|
mq::get_internal_gl().quad_gl.geometry(&vertices, &indices);
|
|
}
|
|
}
|