Ejercicio 7: Texturas
El ejercicio
En este ejercicio, se busca recrear una lata de Coca-Cola, un Hershey's kisses y balones de futbol, utilizando primitivas 3D y texturas.
Creación en Blender
Para la creación de la geometria y la ubicación de las coordenadas de textura, se utilizara el programa Blender. En este, se creo una primitiva de cilindro.
Posteriormente, le asignaremos la textura. Para este ejercicio utilizaremos la siguiente imagen:
En Blender, se realiza un proceso conocido como UV Unwrap. En este proceso se le asigna a cada vertice de la geometria, una coordenada en el espacio 2D de la imagen. Esto se puede realizar manualmente, o utilizando varios procesos automaticos de Blender. para este caso, se realiza una proyección cilindrica, esto nos permite poner cada punto en el cilindro sobre la imagen de forma uniforme.
En el visor de Blender podemos ver ya el resultado de la textura sobre la geometria:
Importación a WebGL
Despues de tener nuestro modelo con su textura en Blender, lo exportamos en formato OBJ. Con la ayuda de este loader, cargamos la información del archivo OBJ al programa de JavaScript. Este contiene la posición de los vertices y las coordenadas UV de la textura.
Para poder utilizar la textura en WebGL, debemos añadir un nuevo atributo a nuestro Vertex Shader donde guardemos las coordenadas de la textura.
attribute vec4 a_position;
attribute vec2 a_texcoord;
uniform mat4 u_matrix;
varying vec2 v_texcoord;
void main() {
gl_Position = u_matrix * a_position;
v_texcoord = a_texcoord;
}
Por ultimo, cambiaremos el fragment shader para que utilice la textura y la samplee de acuerdo a las coordenadas descritas.
precision mediump float;
varying vec2 v_texcoord;
// The texture.
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texcoord);
}
Ahora, en el momento de incialización del programa. Tenemos que informarle a WebGL de los atributos que vamos a utilizar de los shaders:
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["3d-vertex-shader", "3d-fragment-shader"]);
// Informacion de los vertices
var positionLocation = gl.getAttribLocation(program, "a_position");
var texcoordLocation = gl.getAttribLocation(program, "a_texcoord");
// Textura
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
var textureLocation = gl.getUniformLocation(program, "u_texture");
Creamos la textura cargando la imagen y la asociamos con WebGL:
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
//Cargar imagen
var image = new Image();
image.src = "https://raw.githubusercontent.com/sebastian-mc/Ejercicio4_CVI/master/img/cocacola.jpg";
image.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image);
//En este caso la imagen no es cuadrada, por lo que tenemos que realizar procedimientos especiales.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
Por ultimo, dibujamos la geometria:
// Make a view matrix from the camera matrix.
var viewMatrix = m4.inverse(cameraMatrix);
var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);
var matrix = m4.xRotate(viewProjectionMatrix, modelXRotationRadians);
matrix = m4.yRotate(matrix, modelYRotationRadians);
gl.uniformMatrix4fv(matrixLocation, false, matrix);
gl.uniform1i(textureLocation, 0);
gl.drawArrays(gl.TRIANGLES, 0, 91);
Cuando realice esto, la figura no se mostraba de la manera que Blender lo hacia:
parecia que parte de la geometria se perdio. Despues de varios intentos, intente utilizar el modo TRIANGLE_STRIP en vez de TRIANGLES. Esto mejoro el resultado, sin embargo todavia se presentaba geometria faltante.
Resultado final
El demo del ejercicio se puede ver en este fiddle.
Tiempo dedicado
Para este ejercicio, había planeado un tiempo de 4 horas. Sin embargo, se realizo en 7 horas, ya que tomo mucho tiempo encontrar herramientas que facilitaran la creación de las coordenadas de textura.