Practical 5 - Elements of solution¶
This page provides elements of solution for the Texturing practical.
Exercise 1: Wrapping and filtering¶
The interpretation of these texturing parameters was discussed in class, come back to us for more information.
Exercise 2: Load models with explicit texture coordinates¶
First take a look at the cube.obj
file:
o cube
mtllib cube.mtl
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
g cube
usemtl cube
s 1
f 1/1/1 2/2/1 3/3/1
f 3/3/1 2/2/1 4/4/1
...
Eight vertex positions (v
) are defined, as well as four vertex texture coordinates (vt
) and six vertex normals (vn
).
Faces (f
) are then defined using three indices per vertex for the position, texture coordinate and normal, respectively.
For instance, the second vertex of the second triangle is defined at (0.5, -0.5, 0.5)
,
with the texture coordinate (1.0, 0.0)
and the normal (0.0, 0.0, 1.0)
.
Look at the load
function in core.py
. When normals and texture coordinates are defined in a mesh file,
in addition to positions, all these data are automatically added to the attributes dictionary.
Thus, the loader will always send the following attributes:
in vec3 position;
in vec3 normal;
in vec2 tex_coord;
Make sure you modified your vertex shader with the attribute tex_coord
provided by the loader.
Regarding the texture file, the image filename (here cube.png
) is defined in the cube.mtl
material file refered in cube.obj
.
Note that you can easily overload the texture image (with potentially artistic results when texture coordinates are not matched with the image…):
load(file, shader, tex_file="flowers.png")
Exercise 3: Phong and Texture¶
No solution for this exercise. The aim is to combine previous solutions for Phong illumination (see Practical 4 - Elements of solution) and what you have just done with texturing.
Tips would be:
write a new shader merging
phong.[vert|frag]
andtexture.[vert|frag]
.the illumination color and texture can simply be multiplied (an addition could induce saturation, i.e. color components overflowing 1.0 thus clipped at 1.0). Other options use
mix
, see the next exercise.do not forget to add a light in your scene (yes, some of you did forget!)
Exercise 3: Multi-texturing¶
When loading a mesh file, texture coordinates are usually defined. If you define your own object, you have to do it yourself and then add these texture coordinates to your attributes dictionnary so that they will be sent to the vertex shader. Also, setup two textures and send them as two uniforms to your shaders.
class MultiTexturedPlane(Textured):
""" Simple multi-textured object """
def __init__(self, shader, tex_file1, tex_file2):
# setup plane mesh to be textured
base_coords = ((-1, -1, 0), (1, -1, 0), (1, 1, 0), (-1, 1, 0))
indices = np.array((0, 1, 2, 0, 2, 3), np.uint32)
tex_coords = ((0,0), (1,0), (1,1), (0,1))
mesh = Mesh(shader, attributes=dict(position=base_coords, tex_coord=tex_coords), index=indices)
# setup & upload two textures to GPU
texture1 = Texture(tex_file1)
texture2 = Texture(tex_file2)
super().__init__(mesh, diffuse_map=texture1, second_texture=texture2)
Note that the texture coordinates are here shared for the two texture images; this is an example, not the standard.
Also note that here the texture images are exactly mapped to the square: the image vertices are mapped on the square vertices. Try different texture coordinates, and test different images to understand the texture coordinate system (where is up and down?).
In the fragment shader, one texture sampler is defined for each image. There are many ways to combine the two texture colors to compute the output color of the fragment:
test simple operators like addition (watch out for overflows) or multiplication
a common combination when one of the images contains transparent texels (as in
flowers.png
) is linear interpolation with the GLSLmix
function. Find out its definition.
#version 330 core
uniform sampler2D diffuse_map;
uniform sampler2D second_texture;
in vec2 frag_tex_coords;
out vec4 out_color;
void main() {
vec4 color1 = texture(diffuse_map, frag_tex_coords);
vec4 color2 = texture(second_texture, frag_tex_coords);
// out_color = color1 * color2;
out_color = mix(color1, color2, color2.a); // analyse what is done here!
}