Last active
February 22, 2018 11:56
-
-
Save mickvangelderen/5b077dd1f46bb456daae500a12ff0a23 to your computer and use it in GitHub Desktop.
My understanding of what happens when you activate texture units and bind textures in OpenGL.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(nonzero)] | |
extern crate core; | |
mod gl { | |
use core::nonzero::NonZero; | |
#[derive(Debug)] | |
pub struct Context { | |
texture_id_counter: u32, | |
active_texture_unit_index: TextureUnitIndex, | |
texture_units: Vec<TextureUnit>, | |
textures: Vec<Texture>, | |
} | |
impl Context { | |
pub fn new() -> Self { | |
let texture_units = (0..2).map(|_| TextureUnit::default()).collect(); | |
let textures = (0..4).map(|_| Texture::default()).collect(); | |
Context { | |
texture_id_counter: 0, | |
active_texture_unit_index: TextureUnitIndex(0), | |
texture_units, | |
textures, | |
} | |
} | |
pub fn gen_texture(&mut self) -> Option<TextureId> { | |
if (self.texture_id_counter as usize) < self.textures.len() { | |
self.texture_id_counter += 1; | |
NonZero::new(self.texture_id_counter).map(TextureId) | |
} | |
else { | |
None | |
} | |
} | |
pub fn active_texture(&mut self, index: usize) { | |
if index >= self.texture_units.len() { | |
panic!("Invalid texture unit index."); | |
} | |
self.active_texture_unit_index = TextureUnitIndex(index); | |
} | |
pub fn bind_texture(&mut self, target: TextureTarget, texture_id: &TextureId) { | |
let active_texture_unit = &mut self.texture_units[self.active_texture_unit_index.0]; | |
match target { | |
TextureTarget::T1D => active_texture_unit.target_1d = Some(TextureId(texture_id.0)), | |
TextureTarget::T2D => active_texture_unit.target_2d = Some(TextureId(texture_id.0)), | |
} | |
} | |
// fn active_texture_unit(&self) -> &TextureUnit { | |
// &self.texture_units[self.active_texture_unit_index.0] | |
// } | |
pub fn tex_parameter_i(&mut self, target: TextureTarget, param: TextureParameterI, value: i32) { | |
let texture_id = { | |
// Can't use self.active_texture_unit here :'( because that burrows self. | |
let active_texture_unit = &self.texture_units[self.active_texture_unit_index.0]; | |
match target { | |
TextureTarget::T1D => &active_texture_unit.target_1d, | |
TextureTarget::T2D => &active_texture_unit.target_2d, | |
} | |
}; | |
match *texture_id { | |
Some(ref texture_id) => { | |
let texture = &mut self.textures[texture_id.0.get() as usize - 1]; | |
match param { | |
TextureParameterI::WrapR => texture.wrap_r = value as u32, | |
TextureParameterI::WrapS => texture.wrap_s = value as u32, | |
} | |
} | |
None => panic!("No texture id bound to target {:?} for active unit {:?}.", target, self.active_texture_unit_index), | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct TextureId(NonZero<u32>); | |
#[derive(Debug)] | |
pub enum TextureTarget { | |
T1D, | |
T2D, | |
} | |
#[derive(Debug)] | |
pub enum TextureParameterI { | |
WrapR, | |
WrapS, | |
} | |
#[derive(Debug)] | |
pub struct TextureUnitIndex(usize); | |
#[derive(Debug)] | |
pub struct TextureUnit { | |
target_1d: Option<TextureId>, | |
target_2d: Option<TextureId>, | |
} | |
impl Default for TextureUnit { | |
fn default() -> Self { | |
TextureUnit { | |
target_1d: None, | |
target_2d: None, | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct Texture { | |
wrap_r: u32, | |
wrap_s: u32, | |
// ... | |
} | |
impl Default for Texture { | |
fn default() -> Self { | |
Texture { | |
wrap_r: 0, | |
wrap_s: 0, | |
} | |
} | |
} | |
} | |
// #[test] | |
fn main() { | |
let mut context = gl::Context::new(); | |
let tex_1 = context.gen_texture().unwrap(); | |
let tex_2 = context.gen_texture().unwrap(); | |
// Texture unit 0 is active by default. | |
context.bind_texture(gl::TextureTarget::T1D, &tex_1); | |
context.tex_parameter_i(gl::TextureTarget::T1D, gl::TextureParameterI::WrapR, 1); | |
context.bind_texture(gl::TextureTarget::T2D, &tex_2); | |
context.tex_parameter_i(gl::TextureTarget::T2D, gl::TextureParameterI::WrapR, 2); | |
context.tex_parameter_i(gl::TextureTarget::T2D, gl::TextureParameterI::WrapS, 3); | |
loop { | |
// Set up framebuffer. | |
// Use program. | |
// Bind Textures. | |
context.active_texture(0); | |
context.bind_texture(gl::TextureTarget::T1D, &tex_1); | |
context.active_texture(1); | |
context.bind_texture(gl::TextureTarget::T2D, &tex_2); | |
// Render. | |
break; | |
} | |
// We care about two things: | |
// 1. configuring texture parameters and uploading image data | |
// 2. binding textures to specific texture units so that shaders can access the textures through samplers. | |
println!("{:#?}", &context); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment