WebGL?繪制與變換使用示例詳解
緩沖區(qū)對象(buffer object)
其中的API
方法的說明官方網(wǎng)址:WebGLRenderingContext
緊接上一篇的問題,其實通過片元著色器可以修改點的顏色,但是會發(fā)現(xiàn)每一次顏色的都是一樣的,兩種方式的區(qū)別就是第一種用到了緩沖區(qū)對象
解釋:buffer object,它可以一次性向著色器中傳入多個頂點數(shù)據(jù),而緩沖區(qū)對象是WebGL中一塊內(nèi)存區(qū)域,我們可以一次性向其中傳入大量的頂點數(shù)據(jù)。
再來看一眼相關(guān)代碼
api說明
createBuffer
: creates and initializes aWebGLBuffer
storing data such as vertices or colors -- 創(chuàng)建和初始化一個可以存儲類似頂點和顏色數(shù)據(jù)的對象bindBuffer
: binds a givenWebGLBuffer
to a target -- 將buffer
對象綁定到目標對象上bufferData
: initializes and creates the buffer object's data store -- 存儲數(shù)據(jù)到創(chuàng)建的buffer
對象中enableVertexAttribArray
: turns on the generic vertex attribute array at the specified index into the list of attribute arrays. -- 傳入的參數(shù)是一個vertex
類型的數(shù)組對象,這個方法可以依次打開這個數(shù)組vertexAttribPointer
: binds the buffer currently bound togl.ARRAY_BUFFER
to a generic vertex attribute of the current vertex buffer object and specifies its layout. -- 將整個數(shù)組中的所有值一次性分配給一個attribute
變量
解析:首先創(chuàng)建多個長度的數(shù)組,用來裝著色器中需要修改的頂點或是顏色信息,之后創(chuàng)建一個buffer
,再將webgl
對象和當前創(chuàng)建的buffer
地址綁定一起,bufferData
方法就是往buffer
地址中傳入數(shù)組數(shù)據(jù)
繪制圖形
上面的例子中都是繪制一個點,只不過這個點的size
可以自定義設(shè)置
webgl.drawArrays(webgl.POINTS, 0, points.length / 4)
其中的drawArrays
中的第一個參數(shù)指的是不同的繪制方式
參數(shù)類型
gl.POINTS
點,繪制在坐標系內(nèi)gl.LINES
線,分別是點1和點2的線,點3和點4的線...gl.LINE_STRIP
線,連接點1-點2-點3...gl.LINE_LOOP
線,連接點1-點2-點3-點1,點的首尾相連gl.TRIANGLES
三角形, 繪制在(點1,點2,點3)...gl.TRIANGLE_STRIP
三角帶,第二個三角形和第一個三角形共享一條邊gl.gl.TRIANGLE_FAN
三角扇
移動、旋轉(zhuǎn)、縮放
const VSHADER_SOURCE = ` attribute vec4 a_Position; uniform vec4 u_Translate; void main() { gl_Position = u_Translate + a_Position; } ` const u_Translate = gl.getUniformLocation(gl.program, 'u_Translate') gl.uniform4f(u_Translate, 0.5, 0.5, 0.0, 0)
創(chuàng)建初始的坐標點
const u_Translate = gl.getUniformLocation(program, 'u_Translate'); // 定義頂點數(shù)據(jù) const positions = [ 0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5, ]; // 將頂點數(shù)據(jù)寫入緩沖區(qū) gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); // 啟用屬性并指定數(shù)據(jù)格式 gl.enableVertexAttribArray(aPosition); gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0); // 設(shè)置平移向量 const translation = [0.5, 0.5]; // 將平移向量傳遞給uniform變量 gl.uniform2fv(translationUniformLocation, translation); // 繪制圖形 gl.drawArrays(gl.TRIANGLE_FAN, 0, positions.length / 2);
u_Translate + a_Position為每一個分量相加得到一個新的vec4值。
自動旋轉(zhuǎn)
定義頂點著色器:一個頂點的信息,然后可以設(shè)置旋轉(zhuǎn)中心點的錨點,旋轉(zhuǎn)的角度,和一個需要改變的顏色
const vertexShaderSource = ` attribute vec2 a_position; uniform vec2 u_rotationCenter; uniform float u_angle; varying vec3 v_color; void main() { vec2 rotatedPosition = vec2( cos(u_angle) * (a_position.x - u_rotationCenter.x) - sin(u_angle) * (a_position.y - u_rotationCenter.y) + u_rotationCenter.x, sin(u_angle) * (a_position.x - u_rotationCenter.x) + cos(u_angle) * (a_position.y - u_rotationCenter.y) + u_rotationCenter.y ); gl_Position = vec4(rotatedPosition, 0, 1); v_color = vec3(cos(u_angle), 3.14 - cos(u_angle), cos(u_angle)); } `
這樣在片元著色器中就需要
const fragmentShaderSource = ` precision mediump float; varying vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1); } `
v_color
屬性是從頂點著色器中綁定而來的
// 設(shè)置旋轉(zhuǎn)中心和旋轉(zhuǎn)角度 const rotationCenter = [0.25, 0.25]; let angle = 0 function render() { // 更新旋轉(zhuǎn)角度 angle += 0.01 if (angle === 3.1415926) { angle = 0 } // 將旋轉(zhuǎn)中心和旋轉(zhuǎn)角度傳遞給uniform變量 webgl.uniform2fv(rotationCenterUniformLocation, rotationCenter) webgl.uniform1f(angleUniformLocation, angle) draw() // 繪制圖形 webgl.drawArrays(webgl.TRIANGLE_FAN, 0, 4); // 請求瀏覽器調(diào)用下一幀動畫 requestAnimationFrame(render) } // 開始動畫 render()
縮放
demo
實現(xiàn):根據(jù)滑動鼠標控制三角形中的縮放大小
代碼實現(xiàn)
var vertexShaderSource = ` attribute vec3 aVertexPosition; uniform float uScale; void main() { gl_Position = vec4(aVertexPosition * uScale, 1.0); } `
頂點著色器中定義了uniform
的變量uScale
,比例因子,通過之后的代碼中
const scaleUniformLocation = webgl.getUniformLocation(webgl.program, "uScale") webgl.uniform1f(scaleUniformLocation, scale)
重新設(shè)置該變量的值 監(jiān)聽鼠標滑動事件
canvas.addEventListener("wheel", function (event: any) { scale += event.deltaY / 1000 })
補充說明
變換中主要用到是矩陣的知識,矩陣按儲存方式分為按行矩陣和按列矩陣,而WebGL
中主要是按列矩陣
那么使用矩陣可以 <新坐標> = <變換矩陣> * <舊坐標>
以上就是WebGL 繪制與變換使用示例詳解的詳細內(nèi)容,更多關(guān)于WebGL繪制變換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript實現(xiàn)導(dǎo)入導(dǎo)出excel的示例代碼
這篇文章主要為大家詳細介紹了如何利用JavaScript語言實現(xiàn)導(dǎo)入導(dǎo)出excel文件的功能,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-07-07Three.js利用orbit controls插件(軌道控制)控制模型交互動作詳解
這篇文章主要給大家介紹了關(guān)于Three.js利用orbit controls插件,也就是軌道控制來控制模型交互動作的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09JavaScript實現(xiàn)仿新浪微博大廳和騰訊微博首頁滾動特效源碼
最近看到朋友用JavaScript實現(xiàn)仿新浪微博大廳和未登錄騰訊微博首頁滾動效果,朋友使用jquery實現(xiàn)的,在網(wǎng)上看到有用js制作的也比較好,于是把我的內(nèi)容整理分享給大家,具體詳解請看本文2015-09-09