Add texture to cube

Description

Specifying color by vertex can be limiting. If we want to add more detail, we'd need to insert additional vertices.

Instead, we can apply a texture to our cube. The texture we'll use a 2-dimensional array the stores color information.

In this case we're creating a small texture with just four pixels. The glTexImage2D function lets us specify how we're uploading our data, and in this case we're giving it a 2x2 matrix of RGB values.

We also need to specify how the texture maps to our cube. In this case, we're mapping the corners of the texture to the corners of the cube face.

Screenshot

Commands

git clone git@github.com:atsheehan/iridium
cd iridium
git checkout b74553cee30ec05d953a2ebe45e5bf2330b1937c
cargo run --release

Code Changes

Modified shaders/cube.fragGitHub

@@ -1,8 +1,10 @@
11 #version 150
22
3- out vec3 color;
4- in vec3 vertex_color;
3+ out vec4 color;
4+ in vec2 vertex_tex_coord;
5+
6+ uniform sampler2D tex_sampler;
57
68 void main() {
7- color = vertex_color;
9+ color = texture(tex_sampler, vertex_tex_coord);
810 }
@@ -1,8 +1,10 @@
1 #version 150
2
3- out vec3 color;
4- in vec3 vertex_color;
 
 
5
6 void main() {
7- color = vertex_color;
8 }
@@ -1,8 +1,10 @@
1 #version 150
2
3+ out vec4 color;
4+ in vec2 vertex_tex_coord;
5+
6+ uniform sampler2D tex_sampler;
7
8 void main() {
9+ color = texture(tex_sampler, vertex_tex_coord);
10 }

Modified shaders/cube.vertGitHub

@@ -6,7 +6,7 @@
66 uniform vec3 position;
77 uniform float aspect_ratio = 1.0;
88
9- out vec3 vertex_color;
9+ out vec2 vertex_tex_coord;
1010
1111 void main() {
1212 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -73,13 +73,14 @@
7373 vertices[34] = near_bottom_left;
7474 vertices[35] = far_bottom_left;
7575
76- vec3 colors[6];
77- colors[0] = vec3(0.0, 1.0, 0.0);
78- colors[1] = vec3(1.0, 0.0, 0.0);
79- colors[2] = vec3(0.0, 0.0, 1.0);
80- colors[3] = vec3(1.0, 0.0, 1.0);
81- colors[4] = vec3(0.0, 1.0, 1.0);
82- colors[5] = vec3(1.0, 1.0, 0.0);
76+ vec2 texture_coordinates[6];
77+ texture_coordinates[0] = vec2(0.0, 0.0);
78+ texture_coordinates[1] = vec2(1.0, 0.0);
79+ texture_coordinates[2] = vec2(1.0, 1.0);
80+ texture_coordinates[3] = vec2(1.0, 1.0);
81+ texture_coordinates[4] = vec2(0.0, 1.0);
82+ texture_coordinates[5] = vec2(0.0, 0.0);
83+ vertex_tex_coord = texture_coordinates[gl_VertexID % 6];
8384
8485 mat4 world_to_clip_transform =
8586 mat4(1.0, 0.0, 0.0, 0.0,
@@ -94,6 +95,4 @@
9495 0.0, 0.0, 0.0, 1.0);
9596
9697 gl_Position = vec4(vertices[gl_VertexID], 1.0) * model_to_world_transform * world_to_clip_transform;
97-
98- vertex_color = colors[gl_VertexID / 6];
9998 }
@@ -6,7 +6,7 @@
6 uniform vec3 position;
7 uniform float aspect_ratio = 1.0;
8
9- out vec3 vertex_color;
10
11 void main() {
12 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -73,13 +73,14 @@
73 vertices[34] = near_bottom_left;
74 vertices[35] = far_bottom_left;
75
76- vec3 colors[6];
77- colors[0] = vec3(0.0, 1.0, 0.0);
78- colors[1] = vec3(1.0, 0.0, 0.0);
79- colors[2] = vec3(0.0, 0.0, 1.0);
80- colors[3] = vec3(1.0, 0.0, 1.0);
81- colors[4] = vec3(0.0, 1.0, 1.0);
82- colors[5] = vec3(1.0, 1.0, 0.0);
 
83
84 mat4 world_to_clip_transform =
85 mat4(1.0, 0.0, 0.0, 0.0,
@@ -94,6 +95,4 @@
94 0.0, 0.0, 0.0, 1.0);
95
96 gl_Position = vec4(vertices[gl_VertexID], 1.0) * model_to_world_transform * world_to_clip_transform;
97-
98- vertex_color = colors[gl_VertexID / 6];
99 }
@@ -6,7 +6,7 @@
6 uniform vec3 position;
7 uniform float aspect_ratio = 1.0;
8
9+ out vec2 vertex_tex_coord;
10
11 void main() {
12 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -73,13 +73,14 @@
73 vertices[34] = near_bottom_left;
74 vertices[35] = far_bottom_left;
75
76+ vec2 texture_coordinates[6];
77+ texture_coordinates[0] = vec2(0.0, 0.0);
78+ texture_coordinates[1] = vec2(1.0, 0.0);
79+ texture_coordinates[2] = vec2(1.0, 1.0);
80+ texture_coordinates[3] = vec2(1.0, 1.0);
81+ texture_coordinates[4] = vec2(0.0, 1.0);
82+ texture_coordinates[5] = vec2(0.0, 0.0);
83+ vertex_tex_coord = texture_coordinates[gl_VertexID % 6];
84
85 mat4 world_to_clip_transform =
86 mat4(1.0, 0.0, 0.0, 0.0,
@@ -94,6 +95,4 @@
95 0.0, 0.0, 0.0, 1.0);
96
97 gl_Position = vec4(vertices[gl_VertexID], 1.0) * model_to_world_transform * world_to_clip_transform;
 
 
98 }

Modified src/render.rsGitHub

@@ -1,6 +1,9 @@
1- use std::{ffi::CString, fmt::Display};
1+ use std::{
2+ ffi::{c_void, CString},
3+ fmt::Display,
4+ };
25
3- use gl::types::{GLchar, GLenum, GLint, GLuint};
6+ use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
47 use glutin::{
58 config::ConfigTemplateBuilder,
69 context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext, Version},
@@ -26,6 +29,7 @@
2629 surface: Surface<WindowSurface>,
2730 cube_program: Program,
2831 cube_vertex_array_id: GLuint,
32+ cube_texture_id: GLuint,
2933 }
3034
3135 impl Renderer {
@@ -78,6 +82,39 @@
7882 cube_vertex_array_id
7983 };
8084
85+ let cube_texture_id = unsafe {
86+ let mut cube_texture_id = 0;
87+ gl::GenTextures(1, &mut cube_texture_id);
88+ gl::BindTexture(gl::TEXTURE_2D, cube_texture_id);
89+
90+ const TEXTURE_WIDTH: usize = 2;
91+ const TEXTURE_HEIGHT: usize = 2;
92+ const VALUES_PER_PIXEL: usize = 3;
93+ const TEXTURE_SIZE: usize = TEXTURE_WIDTH * TEXTURE_HEIGHT * VALUES_PER_PIXEL;
94+
95+ #[rustfmt::skip]
96+ let data: [u8; TEXTURE_SIZE] = [
97+ 252, 244, 183,
98+ 137, 233, 51,
99+ 117, 21, 246,
100+ 157, 12, 112
101+ ];
102+
103+ gl::TexImage2D(
104+ gl::TEXTURE_2D,
105+ 0,
106+ gl::RGB8 as GLint,
107+ TEXTURE_WIDTH as GLsizei,
108+ TEXTURE_HEIGHT as GLsizei,
109+ 0,
110+ gl::RGB,
111+ gl::UNSIGNED_BYTE,
112+ data.as_ptr() as *const c_void,
113+ );
114+ gl::GenerateMipmap(gl::TEXTURE_2D);
115+ cube_texture_id
116+ };
117+
81118 unsafe {
82119 gl::ClearColor(0.6, 0.4, 0.8, 1.0);
83120 gl::Enable(gl::DEPTH_TEST);
@@ -89,6 +126,7 @@
89126 context,
90127 cube_program,
91128 cube_vertex_array_id,
129+ cube_texture_id,
92130 }
93131 }
94132
@@ -108,6 +146,7 @@
108146 unsafe {
109147 gl::UseProgram(self.cube_program.gl_id());
110148 gl::BindVertexArray(self.cube_vertex_array_id);
149+ gl::BindTexture(gl::TEXTURE_2D, self.cube_texture_id);
111150 gl::DrawArrays(gl::TRIANGLES, 0, 36);
112151 }
113152 }
@@ -1,6 +1,9 @@
1- use std::{ffi::CString, fmt::Display};
 
 
 
2
3- use gl::types::{GLchar, GLenum, GLint, GLuint};
4 use glutin::{
5 config::ConfigTemplateBuilder,
6 context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext, Version},
@@ -26,6 +29,7 @@
26 surface: Surface<WindowSurface>,
27 cube_program: Program,
28 cube_vertex_array_id: GLuint,
 
29 }
30
31 impl Renderer {
@@ -78,6 +82,39 @@
78 cube_vertex_array_id
79 };
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81 unsafe {
82 gl::ClearColor(0.6, 0.4, 0.8, 1.0);
83 gl::Enable(gl::DEPTH_TEST);
@@ -89,6 +126,7 @@
89 context,
90 cube_program,
91 cube_vertex_array_id,
 
92 }
93 }
94
@@ -108,6 +146,7 @@
108 unsafe {
109 gl::UseProgram(self.cube_program.gl_id());
110 gl::BindVertexArray(self.cube_vertex_array_id);
 
111 gl::DrawArrays(gl::TRIANGLES, 0, 36);
112 }
113 }
@@ -1,6 +1,9 @@
1+ use std::{
2+ ffi::{c_void, CString},
3+ fmt::Display,
4+ };
5
6+ use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
7 use glutin::{
8 config::ConfigTemplateBuilder,
9 context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext, Version},
@@ -26,6 +29,7 @@
29 surface: Surface<WindowSurface>,
30 cube_program: Program,
31 cube_vertex_array_id: GLuint,
32+ cube_texture_id: GLuint,
33 }
34
35 impl Renderer {
@@ -78,6 +82,39 @@
82 cube_vertex_array_id
83 };
84
85+ let cube_texture_id = unsafe {
86+ let mut cube_texture_id = 0;
87+ gl::GenTextures(1, &mut cube_texture_id);
88+ gl::BindTexture(gl::TEXTURE_2D, cube_texture_id);
89+
90+ const TEXTURE_WIDTH: usize = 2;
91+ const TEXTURE_HEIGHT: usize = 2;
92+ const VALUES_PER_PIXEL: usize = 3;
93+ const TEXTURE_SIZE: usize = TEXTURE_WIDTH * TEXTURE_HEIGHT * VALUES_PER_PIXEL;
94+
95+ #[rustfmt::skip]
96+ let data: [u8; TEXTURE_SIZE] = [
97+ 252, 244, 183,
98+ 137, 233, 51,
99+ 117, 21, 246,
100+ 157, 12, 112
101+ ];
102+
103+ gl::TexImage2D(
104+ gl::TEXTURE_2D,
105+ 0,
106+ gl::RGB8 as GLint,
107+ TEXTURE_WIDTH as GLsizei,
108+ TEXTURE_HEIGHT as GLsizei,
109+ 0,
110+ gl::RGB,
111+ gl::UNSIGNED_BYTE,
112+ data.as_ptr() as *const c_void,
113+ );
114+ gl::GenerateMipmap(gl::TEXTURE_2D);
115+ cube_texture_id
116+ };
117+
118 unsafe {
119 gl::ClearColor(0.6, 0.4, 0.8, 1.0);
120 gl::Enable(gl::DEPTH_TEST);
@@ -89,6 +126,7 @@
126 context,
127 cube_program,
128 cube_vertex_array_id,
129+ cube_texture_id,
130 }
131 }
132
@@ -108,6 +146,7 @@
146 unsafe {
147 gl::UseProgram(self.cube_program.gl_id());
148 gl::BindVertexArray(self.cube_vertex_array_id);
149+ gl::BindTexture(gl::TEXTURE_2D, self.cube_texture_id);
150 gl::DrawArrays(gl::TRIANGLES, 0, 36);
151 }
152 }