化け猫アイコンメーカーで作ったこの画像を使ってテクスチャマッピングしてみた。ついでにシェーダーで半分色反転させてみた
<html> <head> <title></title> <script> window.onload = function() { var image = new Image(); image.src = "./bakeneko.png"; image.onload = function() { render(image); } } function render(image){ var canvas = document.getElementById("canvas"); var gl = canvas.getContext("experimental-webgl"); var vertexShader = createShader(gl, "2d-vertex-shader", gl.VERTEX_SHADER); var fragmentShader = createShader(gl, "2d-fragment-shader", gl.FRAGMENT_SHADER); program = createProgram(gl, vertexShader, fragmentShader); setTexCood(gl, program); setTexture(gl, image); setResolution(gl, program, canvas); setPosition(gl, program, image); gl.drawArrays(gl.TRIANGLES, 0, 6); } function setTexCood(gl, program){ var texCoordLocation = gl.getAttribLocation(program, "a_texCoord"); var texCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW); gl.enableVertexAttribArray(texCoordLocation); gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); } function setTexture(gl, image){ var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); 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.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); } function setResolution(gl, program, canvas){ var resolutionLocation = gl.getUniformLocation(program, "u_resolution"); gl.uniform2f(resolutionLocation, canvas.width, canvas.height); } function setPosition(gl, program, image){ var positionLocation = gl.getAttribLocation(program, "a_position"); var buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); setRectangle(gl, 0, 0, image.width, image.height); } function setRectangle(gl, x, y, width, height) { var x1 = x; var x2 = x + width; var y1 = y; var y2 = y + height; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW); } function createShader(gl, shaderId, type) { var shader = gl.createShader(type); var source = document.getElementById(shaderId).innerHTML; gl.shaderSource(shader, source); gl.compileShader(shader); return shader; } function createProgram(gl, vertexShader, fragmentShader){ var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { alert(gl.getShaderInfoLog(vertexShader)); alert(gl.getShaderInfoLog(fragmentShader)); } gl.useProgram(program); return program; } </script> <script id="2d-vertex-shader" type="x-shader/x-vertex"> attribute vec2 a_position; attribute vec2 a_texCoord; uniform vec2 u_resolution; varying vec2 v_texCoord; void main() { vec2 zeroToOne = a_position / u_resolution; vec2 zeroToTwo = zeroToOne * 2.0; vec2 clipSpace = zeroToTwo - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); v_texCoord = a_texCoord; } </script> <script id="2d-fragment-shader" type="x-shader/x-fragment"> precision mediump float; uniform sampler2D u_image; varying vec2 v_texCoord; void main() { if(v_texCoord.x > 0.5){ gl_FragColor = vec4(1.0, 1.0, 1.0, 2.0) - texture2D(u_image, v_texCoord); }else{ gl_FragColor = texture2D(u_image, v_texCoord); } } </script> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>