From: Bernie Innocenti Date: Sat, 6 May 2017 23:33:13 +0000 (-0400) Subject: Add a sea shaded cubes, just because. No big deal (yet). X-Git-Tag: v0.7.0~4 X-Git-Url: https://codewiz.org/gitweb?p=mandelwow.git;a=commitdiff_plain;h=c298ca511683f329dfedd18bf9490520586cf8cf Add a sea shaded cubes, just because. No big deal (yet). --- diff --git a/cube.rs b/cube.rs index de5315b..916b868 100644 --- a/cube.rs +++ b/cube.rs @@ -1,6 +1,6 @@ use std::f32; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct Cube { pub xmin: f32, pub ymin: f32, @@ -9,3 +9,10 @@ pub struct Cube { pub ymax: f32, pub zmax: f32, } + +// Returns a unit Cube centered in the origin. +impl Default for Cube { + fn default() -> Cube { + Cube { xmin: -0.5, ymin: -0.5, zmin: -0.5, xmax: 0.5, ymax: 0.5, zmax: 0.5f32 } + } +} diff --git a/lib.rs b/lib.rs index 8fd85f4..aaf2b3c 100644 --- a/lib.rs +++ b/lib.rs @@ -8,7 +8,10 @@ extern crate sdl2; pub mod bounding_box; pub mod cube; pub mod mandelwow; +pub mod shaded_cube; pub mod sound; pub mod support; +pub use bounding_box::BoundingBox; pub use cube::Cube; +pub use shaded_cube::ShadedCube; diff --git a/main.rs b/main.rs index c58cf55..e16ba9d 100644 --- a/main.rs +++ b/main.rs @@ -6,7 +6,8 @@ extern crate glium; extern crate glutin; extern crate image; -use cgmath::{Euler, Matrix4, Rad, Vector3}; +use cgmath::{Euler, Matrix4, One, Rad, Vector3}; +use cgmath::conv::array4x4; use glium::{DisplayBuild, Surface}; use glutin::ElementState::Pressed; use glutin::Event::KeyboardInput; @@ -82,6 +83,7 @@ fn main() { let mandelwow_program = mandelwow::program(&display); let bounding_box_program = bounding_box::solid_fill_program(&display); + let shaded_program = shaded_cube::shaded_program(&display); let mut camera = support::camera::CameraState::new(); let mut t: f32 = 0.0; @@ -99,6 +101,27 @@ fn main() { zmax: 1.1, }; let mandelwow_bbox = bounding_box::BoundingBox::new(&display, &bounds, &bounding_box_program); + let shaded_cube = ShadedCube::new(&display, &Cube::default(), &shaded_program); + + const SEA_XSIZE: usize = 24; + const SEA_ZSIZE: usize = 20; + let sea_xmin = -14.0f32; + let sea_xmax = 14.0f32; + let sea_zmin = -2.0f32; + let sea_zmax = -26.0f32; + let sea_xstep = (sea_xmax - sea_xmin) / (SEA_XSIZE as f32); + let sea_zstep = (sea_zmax - sea_zmin) / (SEA_ZSIZE as f32); + + let mut sea = [[Matrix4::one(); SEA_ZSIZE]; SEA_XSIZE]; + for x in 0..SEA_XSIZE { + for z in 0..SEA_ZSIZE { + sea[x][z] = Matrix4::from_translation(Vector3{ + x: sea_xmin + (x as f32) * sea_xstep, + y: -3.0, + z: sea_zmin + (z as f32) * sea_zstep, + }); + } + } set_main_loop_callback(|| { camera.update(); @@ -124,7 +147,7 @@ fn main() { let z_trans = -2.0; // Send the model back a little bit so it fits the screen. let model2 = Matrix4::from_translation(Vector3::unit_z() * z_trans) * rotation; - let model = cgmath::conv::array4x4(model2); + let model = array4x4(model2); // Draw the bounding box before the fractal, when the Z-buffer is still clear, // so the lines behind the semi-translucent areas will be drawn. @@ -137,6 +160,17 @@ fn main() { mandelwow_bbox.draw(&mut frame, &uniforms); } + for x in 0..SEA_XSIZE { + for z in 0..SEA_ZSIZE { + let uniforms = uniform! { + model: array4x4(sea[x][z]), + view: camera.get_view(), + perspective: camera.get_perspective(), + }; + shaded_cube.draw(&mut frame, &uniforms); + } + } + mandelwow::draw(&display, &mut frame, &mandelwow_program, model, &camera, &bounds, wow); frame.finish().unwrap(); diff --git a/shaded.frag b/shaded.frag new file mode 100644 index 0000000..e48c837 --- /dev/null +++ b/shaded.frag @@ -0,0 +1,9 @@ +#version 300 es +precision lowp float; + +in vec4 color; +out vec4 color_out; + +void main() { + color_out = color; +} diff --git a/shaded.vert b/shaded.vert new file mode 100644 index 0000000..4f3035c --- /dev/null +++ b/shaded.vert @@ -0,0 +1,22 @@ +#version 300 es +precision lowp float; + +in vec3 position; +in vec3 normal; +out vec4 color; + +uniform mat4 perspective; +uniform mat4 view; +uniform mat4 model; + +void main() { + mat4 modelview = view * model; + mat4 m = perspective * modelview; + vec3 dark = vec3(0.0, 0.0, 0.1); + vec3 bright = vec3(0.0, 0.0, 0.9); + vec3 u_light = vec3(-0.5, -0.5, -1.); + vec3 v_normal = transpose(inverse(mat3(model))) * normal; + float brightness = max(dot(normalize(v_normal), normalize(u_light)), 0.0); + color = vec4(mix(dark, bright, brightness), 1.0); + gl_Position = m * vec4(position, 1.0); +} diff --git a/shaded_cube.rs b/shaded_cube.rs new file mode 100644 index 0000000..fb4fb1d --- /dev/null +++ b/shaded_cube.rs @@ -0,0 +1,184 @@ +use cube::Cube; +use glium; +use glium::{Display, Program, Surface}; +use glium::index::{IndexBuffer, PrimitiveType}; + +pub fn shaded_program(display: &Display) -> Program { + let vertex_shader_src = include_str!("shaded.vert"); + let fragment_shader_src = include_str!("shaded.frag"); + return Program::from_source(display, vertex_shader_src, fragment_shader_src, None).unwrap(); +} + +#[derive(Copy, Clone)] +struct Vertex { + position: [f32; 3], + normal: [f32; 3], +} +implement_vertex!(Vertex, position, normal); + +pub struct ShadedCube<'a> { + vertexes: glium::VertexBuffer, + program: &'a Program, + indices: IndexBuffer, +} + +impl<'a> ShadedCube<'a> { + pub fn new(display: &Display, c: &Cube, program: &'a Program) -> ShadedCube<'a> { + // x---> + // 4 ──────┐ 5 + // ╱┆ ╱│ + // 0 ┌─────┐1 │ + // y │ 7+┄┄│┄┄+ 6 + // | │╱ │ ╱ / + // v └─────┘ z + // 3 2 + let vertex_data = [ + // Front face + Vertex { position: [c.xmin, c.ymin, c.zmin], normal: [ 0., 0., 1.] }, // 0 + Vertex { position: [c.xmax, c.ymin, c.zmin], normal: [ 0., 0., 1.] }, // 1 + Vertex { position: [c.xmax, c.ymax, c.zmin], normal: [ 0., 0., 1.] }, // 2 + Vertex { position: [c.xmin, c.ymax, c.zmin], normal: [ 0., 0., 1.] }, // 3 + + // Back face + Vertex { position: [c.xmin, c.ymax, c.zmax], normal: [ 0., 0., -1.] }, // 7 + Vertex { position: [c.xmax, c.ymax, c.zmax], normal: [ 0., 0., -1.] }, // 6 + Vertex { position: [c.xmax, c.ymin, c.zmax], normal: [ 0., 0., -1.] }, // 5 + Vertex { position: [c.xmin, c.ymin, c.zmax], normal: [ 0., 0., -1.] }, // 4 + + // Right face + Vertex { position: [c.xmax, c.ymin, c.zmin], normal: [ -1., 0., 0.] }, // 1 + Vertex { position: [c.xmax, c.ymin, c.zmax], normal: [ -1., 0., 0.] }, // 5 + Vertex { position: [c.xmax, c.ymax, c.zmax], normal: [ -1., 0., 0.] }, // 6 + Vertex { position: [c.xmax, c.ymax, c.zmin], normal: [ -1., 0., 0.] }, // 2 + + // Left face + Vertex { position: [c.xmin, c.ymin, c.zmin], normal: [ 1., 0., 0.] }, // 0 + Vertex { position: [c.xmin, c.ymax, c.zmin], normal: [ 1., 0., 0.] }, // 3 + Vertex { position: [c.xmin, c.ymax, c.zmax], normal: [ 1., 0., 0.] }, // 7 + Vertex { position: [c.xmin, c.ymin, c.zmax], normal: [ 1., 0., 0.] }, // 4 + + // Top face + Vertex { position: [c.xmin, c.ymin, c.zmin], normal: [ 0., 1., 0.] }, // 0 + Vertex { position: [c.xmin, c.ymin, c.zmax], normal: [ 0., 1., 0.] }, // 4 + Vertex { position: [c.xmax, c.ymin, c.zmax], normal: [ 0., 1., 0.] }, // 5 + Vertex { position: [c.xmax, c.ymin, c.zmin], normal: [ 0., 1., 0.] }, // 1 + + // Bottom face + Vertex { position: [c.xmax, c.ymax, c.zmin], normal: [ 0., -1., 0.] }, // 2 + Vertex { position: [c.xmax, c.ymax, c.zmax], normal: [ 0., -1., 0.] }, // 6 + Vertex { position: [c.xmin, c.ymax, c.zmax], normal: [ 0., -1., 0.] }, // 7 + Vertex { position: [c.xmin, c.ymax, c.zmin], normal: [ 0., -1., 0.] }, // 3 + ]; + const INDICES: &[u16] = &[ + 0, 1, 2, 0, 2, 3, // Front + 4, 5, 6, 4, 6, 7, // Back + 8, 9, 10, 8, 10, 11, // Right + 12, 13, 14, 12, 14, 15, // Left + 16, 17, 18, 16, 18, 19, // Top + 20, 21, 22, 20, 22, 23u16 // Bottom + ]; + + ShadedCube { + vertexes: glium::VertexBuffer::new(display, &vertex_data).unwrap(), + program: program, + indices: IndexBuffer::new(display, PrimitiveType::TrianglesList, INDICES).unwrap(), + } + } + + pub fn draw(&self, frame: &mut glium::Frame, uniforms: &U) + where U: glium::uniforms::Uniforms { + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + ..Default::default() + }, + blend: glium::Blend::alpha_blending(), + ..Default::default() + }; + frame.draw(&self.vertexes, &self.indices, &self.program, uniforms, ¶ms).unwrap(); + } +} + +/* +pub fn draw(display: &Display, + frame: &mut glium::Frame, + program: &Program, + uniforms: &U, + cube: &Cube) where U: glium::uniforms::Uniforms { + + implement_vertex!(Vertex, position, normal); + + #[derive(Copy, Clone)] + struct Normal { normal: [f32; 3] } + implement_vertex!(Normal, normal); + + // x---> + // 4 ──────┐ 5 + // ╱┆ ╱│ + // 0 ┌─────┐1 │ + // y │ 7+┄┄│┄┄+ 6 + // | │╱ │ ╱ / + // v └─────┘ z + // 3 2 + let cube = [ + // Front face + Vertex { position: [cube.xmin, cube.ymin, cube.zmin], normal: [ 0., 0., 1.] }, // 0 + Vertex { position: [cube.xmax, cube.ymin, cube.zmin], normal: [ 0., 0., 1.] }, // 1 + Vertex { position: [cube.xmax, cube.ymax, cube.zmin], normal: [ 0., 0., 1.] }, // 2 + Vertex { position: [cube.xmin, cube.ymax, cube.zmin], normal: [ 0., 0., 1.] }, // 3 + + // Back face + Vertex { position: [cube.xmin, cube.ymax, cube.zmax], normal: [ 0., 0., -1.] }, // 7 + Vertex { position: [cube.xmax, cube.ymax, cube.zmax], normal: [ 0., 0., -1.] }, // 6 + Vertex { position: [cube.xmax, cube.ymin, cube.zmax], normal: [ 0., 0., -1.] }, // 5 + Vertex { position: [cube.xmin, cube.ymin, cube.zmax], normal: [ 0., 0., -1.] }, // 4 + + // Right face + Vertex { position: [cube.xmax, cube.ymin, cube.zmin], normal: [ -1., 0., 0.] }, // 1 + Vertex { position: [cube.xmax, cube.ymin, cube.zmax], normal: [ -1., 0., 0.] }, // 5 + Vertex { position: [cube.xmax, cube.ymax, cube.zmax], normal: [ -1., 0., 0.] }, // 6 + Vertex { position: [cube.xmax, cube.ymax, cube.zmin], normal: [ -1., 0., 0.] }, // 2 + + // Left face + Vertex { position: [cube.xmin, cube.ymin, cube.zmin], normal: [ 1., 0., 0.] }, // 0 + Vertex { position: [cube.xmin, cube.ymax, cube.zmin], normal: [ 1., 0., 0.] }, // 3 + Vertex { position: [cube.xmin, cube.ymax, cube.zmax], normal: [ 1., 0., 0.] }, // 7 + Vertex { position: [cube.xmin, cube.ymin, cube.zmax], normal: [ 1., 0., 0.] }, // 4 + + // Top face + Vertex { position: [cube.xmin, cube.ymin, cube.zmin], normal: [ 0., 1., 0.] }, // 0 + Vertex { position: [cube.xmin, cube.ymin, cube.zmax], normal: [ 0., 1., 0.] }, // 4 + Vertex { position: [cube.xmax, cube.ymin, cube.zmax], normal: [ 0., 1., 0.] }, // 5 + Vertex { position: [cube.xmax, cube.ymin, cube.zmin], normal: [ 0., 1., 0.] }, // 1 + + // Bottom face + Vertex { position: [cube.xmax, cube.ymax, cube.zmin], normal: [ 0., -1., 0.] }, // 2 + Vertex { position: [cube.xmax, cube.ymax, cube.zmax], normal: [ 0., -1., 0.] }, // 6 + Vertex { position: [cube.xmin, cube.ymax, cube.zmax], normal: [ 0., -1., 0.] }, // 7 + Vertex { position: [cube.xmin, cube.ymax, cube.zmin], normal: [ 0., -1., 0.] }, // 3 + ]; + let vb = glium::VertexBuffer::new(display, &cube).unwrap(); + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + ..Default::default() + }, + blend: glium::Blend::alpha_blending(), + ..Default::default() + }; + + let front_indices = IndexBuffer::new(display, PrimitiveType::TrianglesList, + &[ 0, 1, 2, 0, 2, 3, // Front + 4, 5, 6, 4, 6, 7, // Back + 8, 9, 10, 8, 10, 11, // Right + 12, 13, 14, 12, 14, 15, // Left + 16, 17, 18, 16, 18, 19, // Top + 20, 21, 22, 20, 22, 23u16, // Bottom + ]).unwrap(); + frame.draw(&vb, &front_indices, program, uniforms, ¶ms).unwrap(); +} + +*/