1. 程式人生 > >HTML5與WebGL程式設計(1):介紹

HTML5與WebGL程式設計(1):介紹

      程式碼https://github.com/tparisi/Programming3DApplications

      HTML5是HTML標準的大規模修訂,包括語法的清理、新的JavaScript語言特性和API、移動端支援以及突破性的多媒體支援。HTML5平臺的核心是一系列先進的圖形技術。

  • WebGL,使得JavaScript支援硬體3D加速渲染。WebGL基於OpenGL,幾乎所有的PC端瀏覽器都支援WebGL,而越來越多的移動端瀏覽器也開始支援WebGL。
  • CSS3 3D變換、平移以及可以支援更高階頁面效果的使用者自定義濾鏡。經過過去幾年的發展,CSS現在已經支援硬體3D加速渲染和動畫。
  • Canvas元素和相應的2D繪圖API。瀏覽器普遍支援這個JavaScript的API,它使得開發者可以在一個DOM元素上繪製任意圖形。儘管Canvas是一個2D繪圖API,但如果使用一些JavaScript庫的話,它也可以用於渲染3D效果---在不支援WebGL和CSS3 3D的平臺上,這通常被作為3D渲染的替代解決方案。

      這些技術各有其優勢和適用場景,它們在構建3D視覺化互動的過程中發揮著各自的作用。至於究竟要選擇哪一種,你需要綜合考慮多方面的因素---你想要構建什麼,需要支援哪些平臺,效能問題,等等。舉例來說,如果你開發一個具有高質量影象的第一人稱射擊遊戲,若不借助WebGL訪問圖形硬體的能力,這將很難實現。又或者你在為某個視訊網站開發一個有趣的調臺器介面,包括當前視訊縮圖、換頻道的旋轉效果,以及視訊剪輯切換間隙的雪花噪點特效。在這個場景下,CSS3會是創造優秀體驗的良好選擇。

      requestAnimationFrame()函式是替代setInterval()和setTimeout()來驅動動畫,使得開發這能夠以和瀏覽器重新整理頁面元素同步的重新整理頻率來更新canvas元素的繪圖內容,這大大地提升了效能,並防止了繪圖殘影的產生。

      HTML5瀏覽器同時也支援多執行緒程式設計(Web Workers)、全雙工TCP/IP通訊(WebSockets)、本地資料儲存等新特性。

      3D座標系

      網格、多邊形和頂點

      材質、紋理與光源

      變換與矩陣

      相機、透視、視口與投影

      著色器

<html>
<head>
<title>Programming 3D Applications in HTML5 and WebGL — Example 2-3</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script src="../libs/jquery-1.9.1/jquery-1.9.1.js"></script>
<script src="../libs/gl-matrix/gl-matrix.js"></script>
<script src="../libs/requestAnimationFrame/RequestAnimationFrame.js"></script>
<script type="text/javascript">
    function initWebGL(canvas) {
	    var gl = null;
	    var msg = "Your browser does not support WebGL, " +
	    	"or it is not enabled by default.";
	    try 
	    {
	        gl = canvas.getContext("experimental-webgl");
	    } 
	    catch (e)
	    {
	        msg = "Error creating WebGL Context!: " + e.toString();
	    }
	
	    if (!gl)
	    {
		    alert(msg);
	    	throw new Error(msg);
	    }
        return gl;        
     }
    function initViewport(gl, canvas)
    {
        gl.viewport(0, 0, canvas.width, canvas.height);
    }
    var projectionMatrix, modelViewMatrix;
    var rotationAxis;
    function initMatrices(canvas)
    {
        // Create a model view matrix with object at 0, 0, -8
        modelViewMatrix = mat4.create();
        mat4.translate(modelViewMatrix, modelViewMatrix, [0, 0, -8]);

        // Create a project matrix with 45 degree field of view
        projectionMatrix = mat4.create();
        mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 1, 10000);

        rotationAxis = vec3.create();
        vec3.normalize(rotationAxis, [1, 1, 1]);
    }
    // Create the vertex, color and index data for a multi-colored cube
    function createCube(gl) {  
        // Vertex Data
        var vertexBuffer;
    	vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        var verts = [
           // Front face
           -1.0, -1.0,  1.0,
            1.0, -1.0,  1.0,
            1.0,  1.0,  1.0,
           -1.0,  1.0,  1.0,

           // Back face
           -1.0, -1.0, -1.0,
           -1.0,  1.0, -1.0,
            1.0,  1.0, -1.0,
            1.0, -1.0, -1.0,

           // Top face
           -1.0,  1.0, -1.0,
           -1.0,  1.0,  1.0,
            1.0,  1.0,  1.0,
            1.0,  1.0, -1.0,

           // Bottom face
           -1.0, -1.0, -1.0,
            1.0, -1.0, -1.0,
            1.0, -1.0,  1.0,
           -1.0, -1.0,  1.0,

           // Right face
            1.0, -1.0, -1.0,
            1.0,  1.0, -1.0,
            1.0,  1.0,  1.0,
            1.0, -1.0,  1.0,

           // Left face
           -1.0, -1.0, -1.0,
           -1.0, -1.0,  1.0,
           -1.0,  1.0,  1.0,
           -1.0,  1.0, -1.0
           ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);

        var texCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
        var textureCoords = [
          // Front face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,

          // Back face
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,

          // Top face
          0.0, 1.0,
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,

          // Bottom face
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,
          1.0, 0.0,

          // Right face
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
          0.0, 0.0,

          // Left face
          0.0, 0.0,
          1.0, 0.0,
          1.0, 1.0,
          0.0, 1.0,
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);

        // Index data (defines the triangles to be drawn)
        var cubeIndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer);
        var cubeIndices = [
            0, 1, 2,      0, 2, 3,    // Front face
            4, 5, 6,      4, 6, 7,    // Back face
            8, 9, 10,     8, 10, 11,  // Top face
            12, 13, 14,   12, 14, 15, // Bottom face
            16, 17, 18,   16, 18, 19, // Right face
            20, 21, 22,   20, 22, 23  // Left face
        ];
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeIndices), gl.STATIC_DRAW);
        
        var cube = {buffer:vertexBuffer, texCoordBuffer:texCoordBuffer, indices:cubeIndexBuffer,
                vertSize:3, nVerts:24, texCoordSize:2, nTexCoords: 24, nIndices:36,
                primtype:gl.TRIANGLES};
        
        return cube;
    }

    function createShader(gl, str, type) {
        var shader;
        if (type == "fragment") {
            shader = gl.createShader(gl.FRAGMENT_SHADER);
        } else if (type == "vertex") {
            shader = gl.createShader(gl.VERTEX_SHADER);
        } else {
            return null;
        }

        gl.shaderSource(shader, str);
        gl.compileShader(shader);

        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert(gl.getShaderInfoLog(shader));
            return null;
        }

        return shader;
    }
    
	var vertexShaderSource =
		
		"    attribute vec3 vertexPos;\n" +
		"    attribute vec2 texCoord;\n" +
		"    uniform mat4 modelViewMatrix;\n" +
		"    uniform mat4 projectionMatrix;\n" +
		"    varying vec2 vTexCoord;\n" +
		"    void main(void) {\n" +
		"		// Return the transformed and projected vertex value\n" +
		"        gl_Position = projectionMatrix * modelViewMatrix * \n" +
		"            vec4(vertexPos, 1.0);\n" +
		"        // Output the texture coordinate in vTexCoord\n" +
		"        vTexCoord = texCoord;\n" +
		"    }\n";

	var fragmentShaderSource = 
		"    precision mediump float;\n" +
		"    varying vec2 vTexCoord;\n" +
		"    uniform sampler2D uSampler;\n" + 
		"    void main(void) {\n" +
		"    // Return the pixel color: always output white\n" +
        "    gl_FragColor = texture2D(uSampler, vec2(vTexCoord.s, vTexCoord.t));\n" +
    	"}\n";


    var shaderProgram, shaderVertexPositionAttribute, shaderVertexColorAttribute, 
    	shaderProjectionMatrixUniform, shaderModelViewMatrixUniform, shaderSamplerUniform;

    function initShader(gl) {

    	// load and compile the fragment and vertex shader
        //var fragmentShader = getShader(gl, "fragmentShader");
        //var vertexShader = getShader(gl, "vertexShader");
        var fragmentShader = createShader(gl, fragmentShaderSource, "fragment");
        var vertexShader = createShader(gl, vertexShaderSource, "vertex");

        // link them together into a new program
        shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);

        // get pointers to the shader params
        shaderVertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPos");
        gl.enableVertexAttribArray(shaderVertexPositionAttribute);

        shaderTexCoordAttribute = gl.getAttribLocation(shaderProgram, "texCoord");
        gl.enableVertexAttribArray(shaderTexCoordAttribute);
        
        shaderProjectionMatrixUniform = gl.getUniformLocation(shaderProgram, "projectionMatrix");
        shaderModelViewMatrixUniform = gl.getUniformLocation(shaderProgram, "modelViewMatrix");
        shaderSamplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
        
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert("Could not initialise shaders");
        }
    }

    var okToRun = false;
    
    function handleTextureLoaded(gl, texture) {
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.bindTexture(gl.TEXTURE_2D, null);
        okToRun = true;
    }
    
    var webGLTexture;

    function initTexture(gl) {
    	webGLTexture = gl.createTexture();
    	webGLTexture.image = new Image();
      
    	webGLTexture.image.onload = function () {
            handleTextureLoaded(gl, webGLTexture)
        }
      webGLTexture.image.crossOrigin = "anonymous"; 
    	webGLTexture.image.src = "../images/webgl-logo-256.jpg";
    }

    
    function draw(gl, obj) {

        // clear the background (with black)
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        gl.clear(gl.COLOR_BUFFER_BIT  | gl.DEPTH_BUFFER_BIT);

        // set the shader to use
        gl.useProgram(shaderProgram);

 		// connect up the shader parameters: vertex position, texture coordinate,
 		// projection/model matrices and texture
   	    // set up the buffers
        gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
        gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, obj.texCoordBuffer);
        gl.vertexAttribPointer(shaderTexCoordAttribute, obj.texCoordSize, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.indices);

        gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix);
        gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix);

        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, webGLTexture);
        gl.uniform1i(shaderSamplerUniform, 0);

        // draw the object
        gl.drawElements(obj.primtype, obj.nIndices, gl.UNSIGNED_SHORT, 0);
    }

    var duration = 5000; // ms
    var currentTime = Date.now();
	function animate() {
        var now = Date.now();
        var deltat = now - currentTime;
        currentTime = now;
        var fract = deltat / duration;
        var angle = Math.PI * 2 * fract;
        mat4.rotate(modelViewMatrix, modelViewMatrix, angle, rotationAxis);
	}
	
    function run(gl, cube) {
        requestAnimationFrame(function() { run(gl, cube); });
        if (okToRun)
        {
	        draw(gl, cube);
	        animate();
        }
    }
          
	$(document).ready(
			function() {
		        var canvas = document.getElementById("webglcanvas");
			    var gl = initWebGL(canvas);
		        initViewport(gl, canvas);
		        initMatrices(canvas);
		        var cube = createCube(gl);
		        initShader(gl);
		        initTexture(gl);
		        run(gl, cube);
			}
	);
</script>
</head>
<body>
    <canvas id="webglcanvas" style="border: none;" width="500" height="500"></canvas>
</body>
</html>

相關推薦

HTML5WebGL程式設計1介紹

      程式碼https://github.com/tparisi/Programming3DApplications       HTML5是HTML標準的大規模修訂,包括語法的清理、新的JavaScript語言特性和API、移動端支援以及突破性的多媒體支援。HTML

Java併發程式設計1可重入內建鎖

每個Java物件都可以用做一個實現同步的鎖,這些鎖被稱為內建鎖或監視器鎖。執行緒在進入同步程式碼塊之前會自動獲取鎖,並且在退出同步程式碼塊時會自動釋放鎖。獲得內建鎖的唯一途徑就是進入由這個鎖保護的同步程式碼塊或方法。 當某個執行緒請求一個由其他執行緒持有的鎖時,發出請求的執行緒就會阻塞。然而,由於內建鎖是可

Java 網路程式設計1使用 NetworkInterface 獲得本機在區域網內的 IP 地址

原文地址:https://segmentfault.com/a/1190000007462741 1、問題提出 在使用 Java 開發網路程式時,有時候我們需要知道本機在區域網中的 IP 地址。很常見的一種做法是呼叫本地命令(比如 Windows 上的 ipconfig 命令和 Li

模板超程式設計1選擇API

C與C++ API的比較    在c語言中,API體現為c函式,如作業系統提供的一系列API,在c++中,API體現為自由函式,這裡的自由函式是指除普通成員函式、靜態成員函式、友元函式外的能在某名稱空間作用域或全域性空間內直接訪問的函式,而這更多地體現為函式模板,如stl提供的一系列演算法swa

F#ASP.NET1基於事件的非同步模式非同步Action

提高ASP.NET應用程式伸縮性的有效手段之一便是使用非同步請求。而在ASP.NET MVC 1中是不能直接支援非同步Action的,因此我們需要使用一些簡單的Hack方式來實現這一點。不過簡單的Hack畢竟無法利用ASP.NET MVC的完整功能,幸好ASP.NET MVC 2已經正式支援ASP.NET中的

Android系統原理原始碼分析1利用Java反射技術阻止通過按鈕關閉對話方塊

本文為原創,如需轉載,請註明作者和出處,謝謝!     眾所周知,AlertDialog類用於顯示對話方塊。關於AlertDialog的基本用法在這裡就不詳細介紹了,網上有很多,讀者可以自己搜尋。那

UNIX環境高階程式設計1UNIX基礎知識1

本系列文章是學習被譽為UNIX程式設計聖經的《UNIX環境高階程式設計》的讀書筆記。《UNIX環境高階程式設計》的英文全稱為《Advanced Programming in the UNIX Envi

【python】Python + C/C++ 嵌入式程式設計1多維陣列Numpy.Array()在Python和C/C++檔案間的傳遞問題

Python 提供了豐富的 C API 函式,我們使用這些 C API 函式可以實現將 Python 檔案中的函式、類等在 C/C++ 檔案中進行呼叫,從而使得我們可以方便地使用 Python 程式碼來幫助我們實現一些額外的需求(如:嵌入神經網路模型)。 網上已經有很多

Linux網路程式設計1如何使用"unp.h"

俗話說萬事開頭難,學習新知識也是如此,當我們下定決心要實現UNP中的例子時,發現卻無法將程式部署上去,這種感覺是不是很令人沮喪?本文就是用來給我自己這種linux菜鳥掃盲用的。 首先,UNP的原始碼連結為 點選開啟連結,下載完成後使用tar -zxvf命令進行解壓。 $

Python影象處理1繪製圖像,點和線,影象輪廓,直方圖

說明:此實驗主要是在Python中實現:繪製圖像,點和線,影象輪廓,直方圖 import tkFileDialog from PIL import Image from pylab import * #開啟一個對話方塊用來選擇一個檔案 filename = t

演算法分析設計課程1Add Two Numbers

Description: You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and

十四、卷積神經網路1介紹卷積神經網路

本篇部落格主要內容參考圖書《神經網路與深度學習》,李航博士的《統計學習方法》National Taiwan University (NTU)李巨集毅老師的《Machine Learning》的課程,在下文中如果不正確的地方請積極指出。 如果喜歡請點贊

QtFFmpeg聯合開發指南——編碼1代碼流程演示

開啟 fault 原因 上下 sizeof ffmpeg 不同步 目前 直接 前兩講演示了基本的解碼流程和簡單功能封裝,今天我們開始學習編碼。編碼就是封裝音視頻流的過程,在整個編碼教程中,我會首先在一個函數中演示完成的編碼流程,再解釋其中存在的問題。下一講我們會將編碼功能進

Redis學習筆記1Redis的說明安裝

sets cti ansi c sde pos AR bsd 學習 ash Redis學習筆記(1):Redis說明的安裝 說明 什麽是Redis REmote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo寫的key-v

提高篇1RMQ問題ST表

style 總結 線段 區間 選擇 線段樹 支持 ins 例題 RMQ是英文Range Minimum/Maximum Query的縮寫,是詢問某個區間內的最值,這裏講一種解法:ST算法 ST算法通常用在要多次(10^6級別)詢問區間最值的問題中,相比於線段樹,它實現更簡

Java併發程式設計3執行緒掛起、恢復終止的正確方法含程式碼

JAVA大資料中高階架構 2018-11-06 14:24:56掛起和恢復執行緒Thread 的API中包含兩個被淘汰的方法,它們用於臨時掛起和重啟某個執行緒,這些方法已經被淘汰,因為它們是不安全的,不穩定的。如果在不合適的時候掛起執行緒(比如,鎖定共享資源時),此時便可能會發生死鎖條件——其他執行緒在等待該

Java併發程式設計4守護執行緒執行緒阻塞的四種情況

守護執行緒Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 使用者執行緒即執行在前臺的執行緒,而守護執行緒是執行在後臺的執行緒。 守護執行緒作用是為其他前臺執行緒的執行提供便利服務,而且僅在普通、非守護執行緒仍然執行時才需要,比如垃圾回收執行緒就是一個

3D引擎資料結構glTF1簡介

不是有句老話講“程式 = 演算法 + 資料結構”嘛,對於3D引擎來說也是這樣。學習和掌握3D引擎中的核心資料有哪些,它們直接的關係是怎樣等等問題,對於理解3D引擎的架構和圖形渲染關係都有著非常大的幫助。然而,現在的商業3D引擎非常複雜,想要通過學習其原始碼嘛非常困難,那麼你就這樣放棄了嗎

iOS開發簡記1指定APP的圖標啟動圖

appstore 技術分享 tps http data 對象 暫時 -c 系統 各位兄弟姐妹們,早上好,本人花了將近一個月的時間打造了一個完整的IOS版的App, 期間包括開發,測試,上線審核,現在花點時間把實現的過程分享給大家,“知音”app功能簡單,適合對象為初學者,後

Spring Boot Actuator詳解深入應用Actuator 1.x

《Spring Boot Actuator詳解與深入應用》預計包括三篇,第一篇重點講Spring Boot Actuator 1.x的應用與定製端點;第二篇將會對比Spring Boot Actuator 2.x 與1.x的區別,以及應用和定製2.x的端點;第三篇將會介紹Actuator metric指