Skip to content

Instantly share code, notes, and snippets.

@mickvangelderen
Last active February 22, 2018 11:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mickvangelderen/5b077dd1f46bb456daae500a12ff0a23 to your computer and use it in GitHub Desktop.
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.
#![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