WebGL 1.0

ถ้าพูดถึงเทคโนโลยี 3D ปัจจุบันดูจะเป็นเรื่องที่ไม่ยากและกำลังเป็นที่นิยม รวมถึงกำลังพัฒนาไปอย่างต่อเนื่อง เรื่อยๆทั้งในด้านของ software และ hardware งานด้าน Geoinfomatic ก็ต้องเกี่ยวข้องกับข้อมูล 3D (X,Y,Z) แนวโน้มการวิจัยพัฒนาระบบ Internet GIS ในอนาคตก็มีการนำเอาเรื่อง online 3D GIS มาพูดถึง และนำมาใช้งานกันอยู่บ้าง แต่ยังมีข้อจำกัดอยู่ค่อนข้างมาก ทั้งตัวขนาดข้อมูล และทรัพยากรในการแสดงผลข้อมูลแบบออนไลน์

วันนี้ผมมีเรื่องของ WebGL ที่ออกมาตรฐานรุ่นแรก 1.0 แบบเป็นทางการออกมา โดยเป็นแนวโน้มที่ดีการพัฒนาระบบ 3D แบบ online ข้อดีคือเป็นมาตรฐานที่สามารถทำงานแบบ interoperability บนเว็บบราว์เซอร์ได้ทุกรุ่นที่เข้าร่วม โดยไม่ต้องอาศัย plug-in เสริมเฉพาะ ที่สำคัญทำงานแสดงผล 3 มิติบนเว็บเบราว์เซอร์ผ่านจาวาสคริปต์ ใช้ภาษา javascript ในการควบคุมการแสดงผล โดย WebGL มีรากฐานมาจาก OpenGL ที่โด่งดังนั้นเอง ปัจจุบัน มีเว็บบราว์เซอร์ชั้นนำมากมายที่เข้าร่วม และยอมรับ Firefox, Chrome, Safari และ Opera ขาด IE ผมว่าอนาคต WebGL จะเป็นอีกหนึ่งทางเลือกของการ พัฒนาระบบ Online 3D GIS ลองดูตัวอย่างการทำงานได้ที่

http://www.khronos.org/webgl/wiki/Demo_Repository

ตัวอย่าง code แสดงผลลูกโลกทรงกลม

<html>
  <head>
    <title>Earth and Mars</title>
    <script type="text/javascript" src="../common/webgl-utils.js"></script>
    <script src="resources/J3DI.js"> </script>
    <script src="resources/J3DIMath.js" type="text/javascript"> </script>
    <script id="vshader" type="x-shader/x-vertex">
        uniform mat4 u_modelViewProjMatrix;
        uniform mat4 u_normalMatrix;
        uniform vec3 lightDir;

        attribute vec3 vNormal;
        attribute vec4 vTexCoord;
        attribute vec4 vPosition;

        varying float v_Dot;
        varying vec2 v_texCoord;

        void main()
        {
            gl_Position = u_modelViewProjMatrix * vPosition;
            v_texCoord = vTexCoord.st;
            vec4 transNormal = u_normalMatrix * vec4(vNormal,1);
            v_Dot = max(dot(transNormal.xyz, lightDir), 0.0);
        }
    </script>

    <script id="fshader" type="x-shader/x-fragment">
#ifdef GL_ES
    precision mediump float;
#endif

        uniform sampler2D sampler2d;

        varying float v_Dot;
        varying vec2 v_texCoord;

        void main()
        {
            vec4 color = texture2D(sampler2d,v_texCoord);
            color += vec4(0.1,0.1,0.1,1);
            gl_FragColor = vec4(color.xyz * v_Dot, color.a);
        }
    </script>

    <script>
        function init()
        {
            var gl = initWebGL("example", "vshader", "fshader",
                                [ "vNormal", "vTexCoord", "vPosition"],
                                [ 0, 0, 0, 1 ], 10000);
            if (!gl) {
              return;
            }

            gl.uniform3f(gl.getUniformLocation(gl.program, "lightDir"), 0, 0, 1);
            gl.uniform1i(gl.getUniformLocation(gl.program, "sampler2d"), 0);

            gl.sphere = makeSphere(gl, 1, 30, 30);

            // get the images
            earthTexture = loadImageTexture(gl, "resources/earthmap1k.jpg");
            marsTexture = loadImageTexture(gl, "resources/mars500x250.png");

            return gl;
        }

        var width = -1;
        var height = -1;
        var framerate;

        function reshape(ctx)
        {
            var canvas = document.getElementById('example');
            if (canvas.width == width && canvas.width == height)
                return;

            width = canvas.width;
            height = canvas.height;

            ctx.viewport(0, 0, width, height);

            ctx.perspectiveMatrix = new J3DIMatrix4();
            ctx.perspectiveMatrix.perspective(30, width/height, 1, 10000);
            ctx.perspectiveMatrix.lookat(0,0,6, 0, 0, 0, 0, 1, 0);
        }

        function drawOne(ctx, angle, x, y, z, scale, texture)
        {
            // setup VBOs
            ctx.enableVertexAttribArray(0);
            ctx.enableVertexAttribArray(1);
            ctx.enableVertexAttribArray(2);

            ctx.bindBuffer(ctx.ARRAY_BUFFER, ctx.sphere.vertexObject);
            ctx.vertexAttribPointer(2, 3, ctx.FLOAT, false, 0, 0);

            ctx.bindBuffer(ctx.ARRAY_BUFFER, ctx.sphere.normalObject);
            ctx.vertexAttribPointer(0, 3, ctx.FLOAT, false, 0, 0);

            ctx.bindBuffer(ctx.ARRAY_BUFFER, ctx.sphere.texCoordObject);
            ctx.vertexAttribPointer(1, 2, ctx.FLOAT, false, 0, 0);

            ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, ctx.sphere.indexObject);

            // generate the model-view matrix
            var mvMatrix = new J3DIMatrix4();
            mvMatrix.translate(x,y,z);
            mvMatrix.rotate(30, 1,0,0);
            mvMatrix.rotate(angle, 0,1,0);
            mvMatrix.scale(scale, scale, scale);

            // construct the normal matrix from the model-view matrix
            var normalMatrix = new J3DIMatrix4(mvMatrix);
            normalMatrix.invert();
            normalMatrix.transpose();
            normalMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_normalMatrix"), false);

            // construct the model-view * projection matrix
            var mvpMatrix = new J3DIMatrix4(ctx.perspectiveMatrix);
            mvpMatrix.multiply(mvMatrix);
            mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false);

            ctx.bindTexture(ctx.TEXTURE_2D, texture);
            ctx.drawElements(ctx.TRIANGLES, ctx.sphere.numIndices, ctx.UNSIGNED_SHORT, 0);
        }

        function drawPicture(ctx)
        {
            reshape(ctx);
            ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);

            drawOne(ctx, currentAngle, -1, 0, 0, 1, earthTexture);
            drawOne(ctx, -currentAngle, 1, 0, 0, 0.6, marsTexture);
            ctx.flush();

            framerate.snapshot();

            currentAngle += incAngle;
            if (currentAngle > 360)
                currentAngle -= 360;
        }

        function start()
        {
            var c = document.getElementById("example");
            var w = Math.floor(window.innerWidth * 0.9);
            var h = Math.floor(window.innerHeight * 0.9);

            c.width = w;
            c.height = h;

            var ctx = init();
            if (!ctx) {
              return;
            }
            framerate = new Framerate("framerate");
            currentAngle = 0;
            incAngle = 0.2;
            var f = function() {
              drawPicture(ctx)
              window.requestAnimFrame(f, c);
            };
            f();
        }
    </script>
    <style type="text/css">
        canvas {
            border: 2px solid black;
        }
    </style>
  </head>
  <body onload="start()">
    <canvas id="example">
    There is supposed to be an example drawing here, but it's not important.
    </canvas>
    <div id="framerate"></div>
    <div id="console"></div>
  </body>
</html>
ดูตัวอย่างผลลัพธ์
มีตัวอย่าง code และโปรเจคที่พัฒนาแบบ 3D ที่น่าสนใจอีกมากของ google จาก
http://code.google.com/p/webglsamples/
About these ads

One thought on “WebGL 1.0

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s