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, 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); } }