コンピュータグラフィックス 演習


[注意]
この課題は、「コンピュータグラフィックス」の受講者にとって最終課題となります。 この課題に対して仕様を満たした成果物を期限内に提出しないと、無条件で失格となりますので注意して下さい。


作成したプログラムが正しく動作することを確認したら、それぞれの 提出先に提出しなさい。

提出した後は、正しく提出されていることを http://nw.tsuda.ac.jp/class/cg/local/handin/ で必ず確認しておいて下さい。

課題提出〆切は2018年9月13日12:00です 。

課題12a: WebGL (Origial Work)

提出ファイル学生番号.html (たとえば g15900.html)
コメント欄:なし
提出先: 「宿題提出Web:コンピュータグラフィックス:課題12a」 http://nw.tsuda.ac.jp/class/cg/local/handin/up.php?id=kadai12a

テクスチャを平行投影した曲面が回転するHTMLファイルをWebGLで記述せよ。 曲面は平行光源または点光源から照らすこと。 ファイル名は"学生番号.html"とする。

以下の条件を満たさないものは提出とは認めない。

サンプルは http://nw.tsuda.ac.jp/class/cg/local/2018kadai12a/ans12a.html にあります。



ans12a.html
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <script src="lib/webgl-utils.js"></script>
  <script src="lib/webgl-debug.js"></script>
  <script src="lib/cuon-utils.js"></script>
  <script src="lib/cuon-matrix.js"></script>
  <script src="tsuda-webgl.js"></script>
  <script language="JavaScript" type="text/javascript">
    //<![CDATA
var VSHADER_SOURCE = "\
attribute vec4 a_Position;\n\
attribute vec4 a_Normal;\n\
attribute vec2 a_TexCoord;\n\
uniform mat4 u_MvpMatrix;\n\
uniform mat4 u_NormalMatrix;\n\
uniform vec3 u_LightColor;\n\
uniform vec3 u_LightDirection;\n\
uniform vec3 u_AmbientLight;\n\
varying vec2 v_TexCoord;\n\
varying vec4 v_Brightness;\n\
void main() {\n\
    gl_Position = u_MvpMatrix * a_Position;\n\
    vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n\
    float nDotL = max(dot(u_LightDirection,normal),0.0);\n\
    v_TexCoord = a_TexCoord;\n\
    v_Brightness = vec4(u_LightColor * nDotL + u_AmbientLight,1.0);\n\
}\n\
";
var FSHADER_SOURCE = "\
precision mediump float;\n\
uniform sampler2D u_Sampler;\n\
varying vec2 v_TexCoord;\n\
varying vec4 v_Brightness;\n\
void main() {\n\
    vec4 color = texture2D(u_Sampler,v_TexCoord);\n\
    vec3 c = color.rgb * v_Brightness.rgb;\n\
    gl_FragColor = vec4(c.rgb,color.a);\n\
}\n\
";
tsuda.texCoord = function(texCoord,vertices,idx,minX,minY,maxX,maxY,minS,minT,maxS,maxT) {
  var dx = (vertices[idx*3] - minX) / (maxX-minX);
  var dy = (vertices[idx*3+1] - minY) / (maxY-minY);
  texCoord[idx*2] = dx * (maxS-minS) + minS;
  texCoord[idx*2+1] = dy * (maxT-minT) + minT;
}

function main() {
    var app = tsuda.initWebGL("mycanvas",VSHADER_SOURCE,FSHADER_SOURCE);
    if (!app) return;
    var canvas = app.canvas;
    var gl = app.gl;

    var vertices = new Float32Array([
  // x, y, z
  0.8,  1.0,  0.5,  // 0
  0.1,  1.0,  0.5,  // 1
 -0.1,  1.0,  0.5,  // 2
 -0.8,  1.0,  0.5,  // 3
 -1.0,  0.8,  0.5,  // 4
 -1.0, -0.8,  0.5,  // 5
 -0.8, -1.0,  0.5,  // 6
  0.8, -1.0,  0.5,  // 7
  1.0, -0.8,  0.5,  // 8
  1.0,  0.8,  0.5,  // 9

  0.4,  0.5,  1.0,  // 10
 -0.4,  0.5,  1.0,  // 11
 -0.5,  0.4,  1.0,  // 12
 -0.5, -0.4,  1.0,  // 13
 -0.4, -0.5,  1.0,  // 14
  0.4, -0.5,  1.0,  // 15
  0.5, -0.4,  1.0,  // 16
  0.5,  0.4,  1.0,  // 17

  0.0,  0.0,  1.3,  // 18  nose
  0.6,  2.0,  0.0,  // 19  left year
 -0.6,  2.0,  0.0,  // 20  right year

  0.82,  1.02, -0.0,  // 21
  0.12,  1.02, -0.0,  // 22
 -0.12,  1.02, -0.0,  // 23
 -0.82,  1.02, -0.0,  // 24
 -1.02,  0.82, -0.0,  // 25
 -1.02, -0.82, -0.0,  // 26
 -0.82, -1.02, -0.0,  // 27
  0.82, -1.02, -0.0,  // 28
  1.02, -0.82, -0.0,  // 29
  1.02,  0.82, -0.0   // 30

]);
    var indices = new Uint8Array([
// forward
   0, 1,10,   1, 2,10,
   2,11,10,   2, 3,11,
   3, 4,11,   4,12,11,
   4, 5,12,   5,13,12,
   5, 6,13,   6,14,13,
   6, 7,14,   7,15,14,
   7, 8,15,   8,16,15,
   8, 9,16,   9,17,16,
   9, 0,17,   0,10,17,

  10,11,18,  11,12,18,
  12,13,18,  13,14,18,
  14,15,18,  15,16,18,
  16,17,18,  17,10,18,

// middle
   0,19, 1,   0,21,19,
//   21,22,19,  
             22, 1,19,
   1,22,23,   1,23, 2,
   2,20, 3,   2,23,20,
//  23,24,20,  
             24, 3,20,
   3,24,25,   3,25, 4,
   4,25,26,   4,26, 5,
   5,26,27,   5,27, 6,
   6,27,28,   6,28, 7,
   7,28,29,   7,29, 8,
   8,29,30,   8,30, 9,
   9,30,21,   9,21, 0

]);
    var normals = tsuda.indexNormals(vertices,indices);
    var texCoord = new Float32Array(vertices.length * 2 / 3);
    var idx;
    for (idx=0; idx<vertices.length; idx++) {
      tsuda.texCoord(texCoord,vertices,idx, -1.1, -1.1, 1.1, 2, 0, 0, 1, 1);
    }
    var texture = gl.createTexture();

    if (! tsuda.initArrayBuffer('a_Position',vertices,3,gl.FLOAT)) return;
    if (! tsuda.initArrayBuffer('a_Normal',normals,3,gl.FLOAT)) return;
    if (! tsuda.initArrayBuffer('a_TexCoord',texCoord,2,gl.FLOAT)) return;

    if (! tsuda.setElementArrayBuffer(indices)) return;

    var u_MvpMatrix = gl.getUniformLocation(gl.program,'u_MvpMatrix');
    var u_NormalMatrix = gl.getUniformLocation(gl.program,'u_NormalMatrix');
    var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
    var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
    var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
    var u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler');

    if (! u_MvpMatrix || ! u_LightColor || ! u_LightDirection || ! u_AmbientLight
        || ! u_NormalMatrix || ! u_Sampler ) {
        console.log('failed to get location of uniform variable');
        return;
    }

    gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
    var lightDirection = new Vector3([1.0, 0.8, 0.5]); // world coordinates
    lightDirection.normalize();
    gl.uniform3fv(u_LightDirection, lightDirection.elements);
    gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);

    var modelMatrix = new Matrix4();
    var viewMatrix = new Matrix4();
    var projMatrix = new Matrix4();
    var mvpMatrix = new Matrix4();
    var normalMatrix = new Matrix4();

    viewMatrix.setLookAt(-3.0, 5.0, 5.0, 0, 0, 0, 0, 1, 0);
    projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
    //modelMatrix.setTranslate(0, 0, -1);
    //modelMatrix.scale(0.7, 0.3, 0.6);
    //modelMatrix.rotate(45, 0, 0, 1);
    mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix);
    gl.uniformMatrix4fv(u_MvpMatrix,false,mvpMatrix.elements);
    normalMatrix.setInverseOf(modelMatrix);
    normalMatrix.transpose();
    gl.uniformMatrix4fv(u_NormalMatrix,false,normalMatrix.elements);

    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);

    var image = new Image();
    image.onload = function() {
       gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1); // reverse y axis of texture image
       gl.activeTexture(gl.TEXTURE0);
       gl.bindTexture(gl.TEXTURE_2D,texture);
       gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
       gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);
       gl.uniform1i(u_Sampler,0);

       gl.clearColor(0.0, 0.0, 0.0, 1.0); // black
       gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
       gl.drawElements(gl.TRIANGLES, indices.length,gl.UNSIGNED_BYTE,0);

      // added
      tsuda.stepAnim = function() {
        modelMatrix.rotate(1, 0, 1, 0);
        mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix);
        gl.uniformMatrix4fv(u_MvpMatrix,false,mvpMatrix.elements);
        normalMatrix.setInverseOf(modelMatrix);
        normalMatrix.transpose();
        gl.uniformMatrix4fv(u_NormalMatrix,false,normalMatrix.elements);
  
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        gl.drawElements(gl.TRIANGLES, indices.length,gl.UNSIGNED_BYTE,0);
      }
      setInterval("tsuda.stepAnim()",33);
    };
    image.src = "./kadai12texture.png";
}
//]]>
  </script>
</head>
<body onload="main()">
  <canvas id="mycanvas" width="320" height="240">
    Your browser does not support Canvas TAB.
  </canvas>
<p>
このプログラムは難読化されていませんので、ソースを表示して読むことができます。
</p>
</body>
</html>