Add texture support to the renderer
- Refactor to use the new model::Model struct - Implement blinn-phong shading - Add texture support for shaders
This commit is contained in:
parent
67f5913907
commit
0af4622525
5 changed files with 109 additions and 37 deletions
|
|
@ -1,11 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
in vec3 v_normal;
|
|
||||||
out vec4 color;
|
|
||||||
uniform vec3 light_dir;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float brightness = dot(normalize(v_normal), normalize(light_dir));
|
|
||||||
vec3 dark_color = vec3(0.6, 0.0, 0.0);
|
|
||||||
vec3 regular_color = vec3(1.0, 0.0, 0.0);
|
|
||||||
color = vec4(mix(dark_color, regular_color, brightness), 1.0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
in vec3 position;
|
|
||||||
in vec3 normal;
|
|
||||||
uniform mat4 model;
|
|
||||||
uniform mat4 view;
|
|
||||||
uniform mat4 projection;
|
|
||||||
out vec3 v_normal;
|
|
||||||
void main() {
|
|
||||||
mat4 modelview = view * model;
|
|
||||||
v_normal = transpose(inverse(mat3(modelview))) * normal;
|
|
||||||
gl_Position = projection * modelview * vec4(position, 1.0);
|
|
||||||
}
|
|
||||||
34
resources/shaders/gl_textured.frag
Normal file
34
resources/shaders/gl_textured.frag
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec3 v_normal;
|
||||||
|
in vec2 v_tex;
|
||||||
|
in vec3 v_position;
|
||||||
|
|
||||||
|
out vec4 frag_color;
|
||||||
|
|
||||||
|
uniform vec3 u_light;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec3 color; // base colour factor (acts as solid colour when no texture)
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Combine base texture (or constant white) with colour factor supplied by CPU.
|
||||||
|
vec3 base_col = texture(tex, v_tex).rgb * color;
|
||||||
|
|
||||||
|
vec3 ambient_color = base_col * 0.2;
|
||||||
|
vec3 diffuse_color = base_col * 0.6;
|
||||||
|
vec3 specular_color = vec3(1.0);
|
||||||
|
|
||||||
|
// u_light is the direction **from the light towards the fragment**.
|
||||||
|
float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);
|
||||||
|
|
||||||
|
vec3 camera_dir = normalize(-v_position);
|
||||||
|
vec3 half_dir = normalize(normalize(u_light) + camera_dir);
|
||||||
|
float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0);
|
||||||
|
|
||||||
|
vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color;
|
||||||
|
|
||||||
|
// Convert from linear to sRGB for display (approximate γ-correction)
|
||||||
|
result = pow(result, vec3(1.0 / 2.2));
|
||||||
|
|
||||||
|
frag_color = vec4(result, 1.0);
|
||||||
|
}
|
||||||
23
resources/shaders/gl_textured.vert
Normal file
23
resources/shaders/gl_textured.vert
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec3 position;
|
||||||
|
in vec3 normal;
|
||||||
|
in vec2 tex_coords;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform vec2 uv_offset;
|
||||||
|
uniform vec2 uv_scale;
|
||||||
|
|
||||||
|
out vec3 v_normal;
|
||||||
|
out vec2 v_tex;
|
||||||
|
out vec3 v_position;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 modelview = view * model;
|
||||||
|
v_normal = transpose(inverse(mat3(modelview))) * normal;
|
||||||
|
v_tex = tex_coords * uv_scale + uv_offset;
|
||||||
|
v_position = (modelview * vec4(position, 1.0)).xyz;
|
||||||
|
gl_Position = projection * modelview * vec4(position, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::camera::Camera;
|
use crate::camera::Camera;
|
||||||
use crate::ecs::{MeshHandle, Transform};
|
use crate::ecs::{ModelHandle, Transform};
|
||||||
use crate::model::Mesh;
|
use crate::model::{Model};
|
||||||
|
use glium::texture::{RawImage2d, SrgbTexture2d};
|
||||||
use glium::{uniform, Program, Surface};
|
use glium::{uniform, Program, Surface};
|
||||||
|
use glium::uniforms::{MinifySamplerFilter, MagnifySamplerFilter, SamplerWrapFunction};
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
use hecs::World;
|
use hecs::World;
|
||||||
use glium::glutin::surface::WindowSurface;
|
use glium::glutin::surface::WindowSurface;
|
||||||
|
|
@ -9,16 +11,25 @@ use glium::glutin::surface::WindowSurface;
|
||||||
pub struct GliumRenderer {
|
pub struct GliumRenderer {
|
||||||
display: glium::Display<WindowSurface>,
|
display: glium::Display<WindowSurface>,
|
||||||
program: Program,
|
program: Program,
|
||||||
pub meshes: Vec<Mesh>,
|
white_tex: SrgbTexture2d,
|
||||||
|
|
||||||
|
pub models: Vec<Model>,
|
||||||
|
|
||||||
params: glium::DrawParameters<'static>,
|
params: glium::DrawParameters<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GliumRenderer {
|
impl GliumRenderer {
|
||||||
pub fn new(display: glium::Display<WindowSurface>) -> anyhow::Result<Self> {
|
pub fn new(display: glium::Display<WindowSurface>) -> anyhow::Result<Self> {
|
||||||
const VERT: &str = include_str!("../resources/shaders/gl_solid_color.vert");
|
const VERT_SRC: &str = include_str!("../resources/shaders/gl_textured.vert");
|
||||||
const FRAG: &str = include_str!("../resources/shaders/gl_solid_color.frag");
|
const FRAG_SRC: &str = include_str!("../resources/shaders/gl_textured.frag");
|
||||||
|
|
||||||
let program = Program::from_source(&display, VERT, FRAG, None)?;
|
let program = Program::from_source(&display, VERT_SRC, FRAG_SRC, None)?;
|
||||||
|
|
||||||
|
let white_tex = {
|
||||||
|
let data = vec![255u8, 255u8, 255u8, 255u8];
|
||||||
|
let raw = RawImage2d::from_raw_rgba(data, (1, 1));
|
||||||
|
SrgbTexture2d::new(&display, raw)?
|
||||||
|
};
|
||||||
|
|
||||||
let params = glium::DrawParameters {
|
let params = glium::DrawParameters {
|
||||||
depth: glium::Depth {
|
depth: glium::Depth {
|
||||||
|
|
@ -29,7 +40,13 @@ impl GliumRenderer {
|
||||||
.. Default::default()
|
.. Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self { display, program, meshes: Vec::new(), params })
|
Ok(Self {
|
||||||
|
display,
|
||||||
|
program,
|
||||||
|
white_tex,
|
||||||
|
models: Vec::new(),
|
||||||
|
params,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_scene<S: Surface>(&self, world: &World, target: &mut S) {
|
fn draw_scene<S: Surface>(&self, world: &World, target: &mut S) {
|
||||||
|
|
@ -41,20 +58,41 @@ impl GliumRenderer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let light_dir: Vec3 = Vec3::new(-1.0, -1.0, -1.0).normalize();
|
// Direction from the light source (0,+Y) towards the scene.
|
||||||
|
let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize();
|
||||||
|
|
||||||
|
for (_, (tr, mh)) in world.query::<(&Transform, &ModelHandle)>().iter() {
|
||||||
|
let model = &self.models[mh.0];
|
||||||
|
let mesh = &model.mesh;
|
||||||
|
let mat = &model.material;
|
||||||
|
|
||||||
|
let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex);
|
||||||
|
|
||||||
|
let mut sampler = tex_ref.sampled();
|
||||||
|
sampler = sampler.wrap_function(SamplerWrapFunction::Repeat);
|
||||||
|
sampler = sampler.minify_filter(MinifySamplerFilter::Linear);
|
||||||
|
sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear);
|
||||||
|
|
||||||
|
let c = mat.base_color_factor;
|
||||||
|
|
||||||
for (_, (tr, mh)) in world.query::<(&Transform, &MeshHandle)>().iter() {
|
|
||||||
let mesh = &self.meshes[mh.0];
|
|
||||||
let uniforms = uniform! {
|
let uniforms = uniform! {
|
||||||
model: tr.matrix().to_cols_array_2d(),
|
model: tr.matrix().to_cols_array_2d(),
|
||||||
view: cam.view().to_cols_array_2d(),
|
view: cam.view().to_cols_array_2d(),
|
||||||
projection: cam.projection().to_cols_array_2d(),
|
projection: cam.projection().to_cols_array_2d(),
|
||||||
light_dir: [light_dir.x, light_dir.y, light_dir.z],
|
u_light: [light_dir.x, light_dir.y, light_dir.z],
|
||||||
|
tex: sampler,
|
||||||
|
color: [c[0], c[1], c[2]],
|
||||||
|
uv_offset: [mat.uv_offset.x, mat.uv_offset.y],
|
||||||
|
uv_scale: [mat.uv_scale.x, mat.uv_scale.y],
|
||||||
};
|
};
|
||||||
|
|
||||||
target
|
target.draw(
|
||||||
.draw(&mesh.vbuf, &mesh.ibuf, &self.program, &uniforms, &self.params)
|
&mesh.vbuf,
|
||||||
.unwrap();
|
&mesh.ibuf,
|
||||||
|
&self.program,
|
||||||
|
&uniforms,
|
||||||
|
&self.params,
|
||||||
|
).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue