Browse Source

Things are starting to work

master
Thomas Forgione 10 months ago
parent
commit
d99fbe20bb
Signed by: Thomas Forgione <thomas@forgione.fr> GPG Key ID: 63D3E1A00D54FD76

+ 10
- 16
assets/shaders/default.frag View File

@@ -1,31 +1,25 @@
#version 140

uniform sampler2D tex;
uniform vec3 diffuse;
uniform sampler2D ambient_map;
uniform sampler2D diffuse_map;

in vec3 v_normal;
in vec2 v_texture_coordinates;

out vec4 color;

vec3 ambientLight = vec3(0.3,0.3,0.3);
vec3 directionnalLight = normalize(vec3(10,5,7));
vec3 directionnalLightFactor = vec3(0.6,0.6,0.6);
vec4 ambientLight = vec4(1.0,1.0,1.0,1.0);

void main() {

vec3 lambertComponent = dot(directionnalLight, v_normal) * directionnalLightFactor;
lambertComponent = max(vec3(0.0, 0.0, 0.0), lambertComponent);
color = texture(diffuse_map, v_texture_coordinates);
color.a = 1.0;

vec4 factor = vec4(ambientLight + lambertComponent, 1.0);

color = factor * vec4(diffuse, 1.0) * texture(tex, v_texture_coordinates);

if (color.a < 0.05) {
discard;
} else {
color.a = 1.0;
}
// if (color.a < 0.05) {
// discard;
// } else {
// color.a = 1.0;
// }

}


+ 1
- 3
assets/shaders/default.vert View File

@@ -2,7 +2,6 @@

uniform mat4 perspective;
uniform mat4 view;
uniform vec3 texture_size;

in vec3 position;
in vec2 texture_coordinates;
@@ -13,7 +12,6 @@ out vec3 v_normal;

void main() {
v_normal = normal;
v_texture_coordinates = vec2(texture_coordinates.x * texture_size.x, texture_coordinates.y * texture_size.y);

v_texture_coordinates = vec2(texture_coordinates.x, texture_coordinates.y);
gl_Position = perspective * view * vec4(position, 1.0);
}

+ 9
- 4
src/model/mod.rs View File

@@ -201,6 +201,11 @@ impl Model {
&self.vertices
}

/// Adds a new part with a specific material.
pub fn add_part(&mut self, material_name: Option<String>) {
self.parts.push(Part::new(material_name));
}

/// Creates a new texture coordinate in the model.
pub fn add_texture_coordinate(&mut self, v: Vector2<f64>) {
self.texture_coordinates.push(v);
@@ -253,7 +258,7 @@ impl Model {
impl Model {
/// Creates a render part from a model and one of its parts.
fn ref_render_part<'a>(&'a self, part: &'a Part, renderer: &Renderer) -> Result<RenderPart<RefPart>, ()> {
Ok(RenderPart::new_ref(&self, part, renderer))
Ok(RenderPart::new_ref(&self, part, renderer)?)
}

/// Creates a referenced render model from a model containing all of its parts.
@@ -268,12 +273,12 @@ impl Model {
for part in &self.parts {
render_parts.push(self.ref_render_part(part, renderer)?);
}
Ok(RenderModel::new(self.into(), render_parts))
Ok(RenderModel::new(self.into(), render_parts, renderer)?)
}

/// Creates a render part for a model and one of its parts.
fn copy_render_part(&self, part: &Part, renderer: &Renderer) -> Result<RenderPart<CopyPart>, ()> {
Ok(RenderPart::new_copy(&self, part, renderer))
Ok(RenderPart::new_copy(&self, part, renderer)?)
}

/// Creates an owned render model from a model containing all of its parts.
@@ -286,7 +291,7 @@ impl Model {
for part in &self.parts {
render_parts.push(self.copy_render_part(part, renderer)?);
}
Ok(RenderModel::new(self.into(), render_parts))
Ok(RenderModel::new(self.into(), render_parts, renderer)?)
}

/// Converts the model into a render model.

+ 9
- 10
src/parser/mtl.rs View File

@@ -1,7 +1,5 @@
//! The file parser for the materials of WaveFront OBJ.

use std::path::PathBuf;

use crate::model::{Material, Model};
use crate::parser::{Line, LineParser, Error, parse_values};

@@ -41,9 +39,14 @@ impl MtlParser {

impl LineParser for MtlParser {
fn parse_line(&mut self, line: Line, model: &mut Model) -> Result<(), Error> {

let content = line.content.trim_end();
let split = content.split_whitespace().collect::<Vec<_>>();

let mut path = line.filename.clone().unwrap();
path.pop();
path.push(&split[1..].join(" "));

if split.is_empty() {
return Ok(());
}
@@ -63,17 +66,13 @@ impl LineParser for MtlParser {
"Ke" => set!(self.current_material, emissive,
parse_values(&line, &split[1..], 3)?.into()),

"map_Ka" => set!(self.current_material, ambient_map,
Some(PathBuf::from(split[1..].join(" ")))),
"map_Ka" => set!(self.current_material, ambient_map, Some(path)),

"map_Kd" => set!(self.current_material, diffuse_map,
Some(PathBuf::from(split[1..].join(" ")))),
"map_Kd" => set!(self.current_material, diffuse_map, Some(path)),

"map_Ks" => set!(self.current_material, specular_map,
Some(PathBuf::from(split[1..].join(" ")))),
"map_Ks" => set!(self.current_material, specular_map, Some(path)),

"map_Ke" => set!(self.current_material, emissive_map,
Some(PathBuf::from(split[1..].join(" ")))),
"map_Ke" => set!(self.current_material, emissive_map, Some(path)),

"#" => (),
other => {

+ 4
- 0
src/parser/obj.rs View File

@@ -118,6 +118,10 @@ impl LineParser for ObjParser {
"vn" => self.parse_normal(&line, &split[1..], model),
"f" => self.parse_face(&line, &split[1..], model),
"mtllib" => self.parse_mtl(&line, &split[1..], model),
"usemtl" => {
model.add_part(Some(split[1..].join(" ")));
Ok(())
},
"#" => Ok(()),
other => {
let number = if let Some(line_number) = line.number {

+ 9
- 8
src/render/camera.rs View File

@@ -4,15 +4,16 @@ use crate::math::vector::Vector3;

/// Creates a look at matrix from the center, the target pointed by the camera and the up vector.
pub fn look_at(position: Vector3<f32>, target: Vector3<f32>, up: Vector3<f32>) -> [[f32; 4]; 4] {

let e3 = (position - target).normalized();
let e1 = up.cross_product(e3).normalized();
let e2 = e3.cross_product(e1);

[
[e1[0], e2[0], e3[0], position[0]],
[e1[1], e2[1], e3[0], position[1]],
[e1[1], e2[2], e3[0], position[2]],
[0.0, 0.0, 0.0, 1.0],
[e1[0], e2[0], e3[0], 0.0],
[e1[1], e2[1], e3[1], 0.0],
[e1[2], e2[2], e3[2], 0.0],
[-position.dot(e1), -position.dot(e2), -position.dot(e3), 1.0],
]
}

@@ -30,10 +31,10 @@ pub fn perspective(fov: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> [[f3
let d = - 2.0 * z_far * z_near / (z_far - z_near);

[
[ x, 0.0, 0.0, 0.0],
[0.0, y, 0.0, 0.0],
[0.0, 0.0, c, d],
[0.0, 0.0, -1.0, 0.0],
[ x, 0.0, 0.0, 0.0],
[0.0, y, 0.0, 0.0],
[0.0, 0.0, c, -1.0],
[0.0, 0.0, d, 0.0],
]

}

+ 43
- 11
src/render/model.rs View File

@@ -1,8 +1,10 @@
//! This model contains the equivalent struct of Model but for rendering.

use std::path::PathBuf;
use std::collections::HashMap;

use glium::{implement_vertex, VertexBuffer};
use glium::texture::SrgbTexture2d;

use crate::model::{Material, Part, Model};
use crate::render::renderer::Renderer;
@@ -113,25 +115,30 @@ impl<T: PartInfo> RenderPart<T> {
pub fn vertex_buffer(&self) -> &VertexBuffer<Vertex> {
&self.vertex_buffer
}

/// Returns the material name of the part, if any.
pub fn material_name(&self) -> &Option<String> {
self.part.material_name()
}
}

impl RenderPart<CopyPart> {
/// Creates a render part from a part of a model.
pub fn new_copy(model: &Model, part: &Part, renderer: &Renderer) -> RenderPart<CopyPart> {
RenderPart {
pub fn new_copy(model: &Model, part: &Part, renderer: &Renderer) -> Result<RenderPart<CopyPart>, ()> {
Ok(RenderPart {
part: Into::<CopyPart>::into(part),
vertex_buffer: renderer.build_vertex_buffer(&Self::vertices(model, part)),
}
vertex_buffer: renderer.build_vertex_buffer(&Self::vertices(model, part))?,
})
}
}

impl<'a> RenderPart<RefPart<'a>> {
/// Creates a render part from a part of a model.
pub fn new_ref(model: &Model, part: &'a Part, renderer: &Renderer) -> RenderPart<RefPart<'a>> {
RenderPart {
pub fn new_ref(model: &Model, part: &'a Part, renderer: &Renderer) -> Result<RenderPart<RefPart<'a>>, ()> {
Ok(RenderPart {
part: Into::<RefPart<'a>>::into(part),
vertex_buffer: renderer.build_vertex_buffer(&Self::vertices(model, part)),
}
vertex_buffer: renderer.build_vertex_buffer(&Self::vertices(model, part))?,
})
}
}

@@ -192,19 +199,44 @@ pub struct RenderModel<M: ModelInfo, P: PartInfo> {
/// The differents parts of the model.
parts: Vec<RenderPart<P>>,

/// The textures of the model.
textures: HashMap<PathBuf, SrgbTexture2d>,

}

impl<M: ModelInfo, P: PartInfo> RenderModel<M, P> {
/// Creates a new render model from its render parts.
pub fn new(model: M, parts: Vec<RenderPart<P>>) -> RenderModel<M, P> {
RenderModel {
pub fn new(model: M, parts: Vec<RenderPart<P>>, renderer: &Renderer) -> Result<RenderModel<M, P>, ()> {

let mut textures = HashMap::new();

for material in model.materials() {
for path in &[&material.1.ambient_map, &material.1.diffuse_map] {
if let Some(path) = path {
textures.insert(path.clone(), renderer.build_texture(path)?);
}
}
}

Ok(RenderModel {
model,
parts,
}
textures,
})
}

/// Returns a reference to the parts of the render model.
pub fn parts(&self) -> &Vec<RenderPart<P>> {
&self.parts
}

/// Returns a reference to the materials of the render model.
pub fn materials(&self) -> &HashMap<String, Material> {
self.model.materials()
}

/// Returns a reference to the textures of the render model.
pub fn textures(&self) -> &HashMap<PathBuf, SrgbTexture2d> {
&self.textures
}
}

+ 29
- 7
src/render/renderer.rs View File

@@ -1,5 +1,7 @@
//! This module contains the renderer struct, needed to render 3D models.

use std::path::{Path, PathBuf};

use image::{ImageBuffer, Rgba};

use glium::{Frame, Display, Program, VertexBuffer, Depth, DrawParameters, Surface, uniform};
@@ -7,6 +9,7 @@ use glium::texture::{RawImage2d, SrgbTexture2d};
use glium::draw_parameters::{DepthTest, Blend};
use glium::index::{NoIndices, PrimitiveType};

use crate::model::Material;
use crate::render::model::{Vertex, ModelInfo, PartInfo,RenderModel};
use crate::render::scene::Scene;
use crate::render::camera::RenderCamera;
@@ -69,21 +72,21 @@ impl Renderer {
}

/// Builds a vertex buffer from a vector of vertex.
pub fn build_vertex_buffer(&self, vertices: &Vec<Vertex>) -> VertexBuffer<Vertex> {
VertexBuffer::new(&self.display, vertices).unwrap()
pub fn build_vertex_buffer(&self, vertices: &Vec<Vertex>) -> Result<VertexBuffer<Vertex>, ()> {
Ok(VertexBuffer::new(&self.display, vertices).unwrap())
}

/// Creates a SrgbTexture from a path to an image.
pub fn build_texture(&self, path: &str) -> SrgbTexture2d {
pub fn build_texture<P: AsRef<Path>>(&self, path: P) -> Result<SrgbTexture2d, ()> {
let image = image::open(path).unwrap().to_rgba();
self.build_texture_from_buffer(image)
}

/// Creates a SrgbTexture from an image buffer.
pub fn build_texture_from_buffer(&self, buffer: ImageBuffer<Rgba<u8>, Vec<u8>>) -> SrgbTexture2d {
pub fn build_texture_from_buffer(&self, buffer: ImageBuffer<Rgba<u8>, Vec<u8>>) -> Result<SrgbTexture2d, ()> {
let dimensions = buffer.dimensions();
let buffer = RawImage2d::from_raw_rgba_reversed(&buffer.into_raw(), dimensions);
SrgbTexture2d::new(&self.display, buffer).ok().unwrap()
Ok(SrgbTexture2d::new(&self.display, buffer).ok().unwrap())
}

/// Creates a frame from the display.
@@ -128,15 +131,24 @@ impl Renderer {

for part in model.parts() {

let material = if let Some(material_name) = part.material_name() {
model.materials()[material_name].clone()
} else {
Material::new()
};

let ambient_map = self.find_texture(&material.ambient_map, model);
let diffuse_map = self.find_texture(&material.diffuse_map, model);

target.draw(
part.vertex_buffer(),
NoIndices(PrimitiveType::TrianglesList),
&self.program,
&uniform!(
hello: 0.0,
perspective: *perspective,
view: *view,
texture: &self.default_texture,
ambient_map: ambient_map,
diffuse_map: diffuse_map,
),
params,
).unwrap();
@@ -145,4 +157,14 @@ impl Renderer {

Ok(())
}

/// Returns the texture corresponding to the material, or the default texture.
pub fn find_texture<'a, M: ModelInfo, P: PartInfo>(&'a self, path: &Option<PathBuf>, model: &'a RenderModel<M, P>) -> &'a SrgbTexture2d {

path
.as_ref()
.map(|x| model.textures().get(x))
.unwrap_or(Some(&self.default_texture))
.unwrap_or(&self.default_texture)
}
}

+ 1
- 1
src/view.rs View File

@@ -84,7 +84,7 @@ fn main() {
info!("Vertex buffers built");

info!("Creating scene");
let camera = Camera::y_up([2.0, 2.0, 2.0], [0.0, 0.0, 0.0]);
let camera = Camera::y_up([1.0, 1.0, 1.0], [0.0, 0.0, 0.0]);
let mut scene = Scene::new();
scene.add_copy_model(render_model);


Loading…
Cancel
Save