マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

テクスチャマッピングしてみる

化け猫アイコンメーカーで作ったこの画像を使ってテクスチャマッピングしてみた。ついでにシェーダーで半分色反転させてみた


<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>