diff --git a/shaders/terrain-frag.glsl b/shaders/terrain-frag.glsl new file mode 100644 index 0000000..ef4a284 --- /dev/null +++ b/shaders/terrain-frag.glsl @@ -0,0 +1,9 @@ +#define lowp +#define mediump +#define highp +#line 0 +varying lowp vec3 vary_color; + +void main (void) { + gl_FragColor = vec4 (vary_color, 1.0); +} diff --git a/shaders/terrain-vert.glsl b/shaders/terrain-vert.glsl new file mode 100644 index 0000000..0cb4180 --- /dev/null +++ b/shaders/terrain-vert.glsl @@ -0,0 +1,15 @@ +#define lowp +#define mediump +#define highp +#line 0 +attribute highp vec4 attr_pos; +attribute lowp vec3 attr_color; + +uniform highp mat4 uni_mvp; + +varying lowp vec3 vary_color; + +void main (void) { + vary_color = attr_color; + gl_Position = uni_mvp * attr_pos; +} diff --git a/src/bin/terrain.rs b/src/bin/terrain.rs index 775fc82..28008fd 100644 --- a/src/bin/terrain.rs +++ b/src/bin/terrain.rs @@ -11,6 +11,10 @@ use anyhow::{ anyhow, Context, }; +use glam::{ + Mat4, + Vec3, +}; use sdl2::{ event::Event, keyboard::{Keycode, Scancode}, @@ -31,26 +35,64 @@ struct GraphicsContext { index_buffer: gpu_buffers::IndexBuffer, shader_program: shader::ShaderProgram, + shader_locations: ShaderLocations, +} + +struct ShaderLocations { attr_pos: u32, + attr_color: u32, + uni_mvp: i32, +} + +impl ShaderLocations { + pub fn new (shader_program: &shader::ShaderProgram) -> anyhow::Result + { + let attr = |name: &str| shader_program.get_attribute_location (&CString::new (name.as_bytes ())?).try_into ().context ("Attribute location negative"); + let uni = |name: &str| shader_program.get_uniform_location (&CString::new (name.as_bytes ())?).try_into ().context ("Uniform location bad"); + + Ok (Self { + attr_pos: attr ("attr_pos")?, + attr_color: attr ("attr_color")?, + uni_mvp: uni ("uni_mvp")?, + }) + } } fn draw_graphics (ctx: &GraphicsContext) { - let attr_pos = ctx.attr_pos; + let shader_locs = &ctx.shader_locations; + let attr_pos = shader_locs.attr_pos; + let attr_color = shader_locs.attr_color; + let uni_mvp = shader_locs.uni_mvp; ctx.window.gl_make_current (&ctx.gl_ctx).unwrap (); glezz::clear_color (0.392f32, 0.710f32, 0.965f32, 1.0f32); glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); + let screen_size = (960.0, 540.0); + + let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), screen_size.0 / screen_size.1, 0.125, 200.0); + + let view_mat = proj_mat * + Mat4::from_translation (Vec3::from ((0.0, 0.0, -20.0))); + + let mvp = view_mat; + + glezz::uniform_matrix_4fv (uni_mvp, &mvp); + ctx.shader_program.use_program (); glezz::enable_vertex_attrib_array (Some (attr_pos)); + glezz::enable_vertex_attrib_array (Some (attr_color)); ctx.vertex_buffer.bind (); ctx.index_buffer.bind (); unsafe { - gl::VertexAttribPointer (attr_pos, 2, gl::FLOAT, 0, 4 * 2, 0 as *const u8 as *const c_void); + let num_quads = 4 * 4; + let stride = 4 * 6; + gl::VertexAttribPointer (attr_pos, 3, gl::FLOAT, 0, stride, 0 as *const u8 as *const c_void); + gl::VertexAttribPointer (attr_color, 3, gl::FLOAT, 0, stride, (4 * 3) as *const u8 as *const c_void); - gl::DrawRangeElements (gl::TRIANGLES, 0, 6, 6, gl::UNSIGNED_INT, 0 as *const u8 as *const c_void); + gl::DrawRangeElements (gl::TRIANGLES, 0, num_quads * 4, num_quads as i32 * 6, gl::UNSIGNED_INT, 0 as *const u8 as *const c_void); } ctx.window.gl_swap_window (); @@ -85,43 +127,42 @@ fn main () -> anyhow::Result <()> { let mut event_pump = sdl_context.event_pump ().unwrap (); - let vertex_shader = shader::ShaderObject::from_source (gl::VERTEX_SHADER, b" -#define lowp -#define mediump -#define highp -#line 0 -attribute highp vec4 attr_pos; - -void main (void) { - gl_Position = attr_pos; -} - ").map_err (|e| anyhow! ("Can't create vertex shader: {}", e))?; + let shader_program = shader::shader_from_files ("shaders/terrain-vert.glsl", "shaders/terrain-frag.glsl"); + let shader_locations = ShaderLocations::new (&shader_program)?; - let fragment_shader = shader::ShaderObject::from_source (gl::FRAGMENT_SHADER, b" -#define lowp -#define mediump -#define highp -#line 0 -void main (void) { - gl_FragColor = vec4 (0.329, 0.431, 0.478, 1.0); -} - ").map_err (|e| anyhow! ("Can't create fragment shader: {}", e))?; + let mut vertexes = vec![]; + let mut indexes = vec![]; + let mut start_index = 0; - let shader_program = shader::ShaderProgram::new (&vertex_shader, &fragment_shader).map_err (|e| anyhow! ("Can't link shader program: {}", e))?; + for y in 0..4 { + for x in 0..4 { + let (r, g, b) = if (x + y) % 2 == 0 { + (0.4, 0.4, 0.4) + } + else { + (0.6, 0.6, 0.6) + }; + + let x = x as f32; + let y = y as f32; + let i = start_index; + + vertexes.extend (&[ + x + 0.0, y + 0.0, 0.0, r, g, b, + x + 1.0, y + 0.0, 0.0, r, g, b, + x + 1.0, y + 1.0, 0.0, r, g, b, + x + 0.0, y + 1.0, 0.0, r, g, b, + ]); + indexes.extend (&[ + i + 0, i + 1, i + 2, + i + 0, i + 2, i + 3, + ]); + start_index += 4; + } + } - let attr_pos = shader_program.get_attribute_location (&CString::new ("attr_pos".as_bytes ())?).try_into ()?; - - let vertex_buffer = gpu_buffers::VertexBuffer::from_slice (&[ - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - ]); - - let index_buffer = gpu_buffers::IndexBuffer::from_slice_u32 (&[ - 0, 1, 2, - 0, 2, 3 - ]); + let vertex_buffer = gpu_buffers::VertexBuffer::from_slice (&vertexes); + let index_buffer = gpu_buffers::IndexBuffer::from_slice_u32 (&indexes); let graphics_ctx = GraphicsContext { window, @@ -131,7 +172,7 @@ void main (void) { index_buffer, shader_program, - attr_pos, + shader_locations, }; 'running: loop {