回覆列表
  • 1 # 趣味兒科技

    隨著GPU功能的越來越強大,現在越來越多的應用程式利用CPU+GPU異構的形式,來提高應用程式的計算速度。而OpenGL作為圖形API發揮著重大的作用,OpenGL中CPU傳送資料到GPU的方式一般有以下幾種:

    (1)紋理取樣方式,透過紋理不僅可以將影象資料傳入到GPU中,也可以將一些其他資料透過紋理的形式,傳送到GPU中。例如法線貼圖,就是利用法線以紋理的形式,傳送到GPU的。在工作過程中,也遇到過將類似伽馬矯正資料,透過紋理形式傳送到GPU中,然後來進行處理。

    (2)透過Uniform這種glsl變數的形式。比如透過glUniformMatrix4fv這樣的函式,將一個矩陣或者向量傳輸到GPU中。

    (3)各種buffer方式,緩衝物件是主要的從CPU傳送資料到GPU的方式,在渲染引擎中,頂點屬性引數(頂點座標、法線座標、紋理座標及頂點顏色等)都是透過緩衝物件的形式。

  • 2 # 智慧電子DIY

    WebGL為不同的平臺/硬體提供了統一的封裝,遮蔽了OpenGL ES2.0在各平臺差異。後續我們會繼續談談OpenGL ES2.0在Android/iOS平臺的更多差異。這回我們分析WebKit的原始碼,談談WebGL與Cavans不同,WebGL又多做了哪些呢,效能提升在哪裡呢。

    在H5中渲染機制

    我們可以使用多種方式來繪製圖形【本文以iOS版本的WebKit為例】DOM+CSS:為前端提供了強大圖形渲染技術,門檻低上手快,對硬體要求較高。

    Canvas2D:元素本身並沒有繪製能力,它僅僅是2D圖形的容器,必須使用指令碼來完成實際的繪圖任務。getContext("2d") 方法可返回一個物件CanvasRenderingContext(後續簡稱canvas),該物件提供了用於在畫布上繪圖的方法和屬性,可用於在畫布上繪製圖片、文字、圖形、顏色等,並提供常見的圖形轉換API,進行圖片的縮放、旋轉、畫素再加工能力,最終透過OpenGL渲染到螢幕上。

    Canvas3D:同2D一樣,本身沒有渲染能力,透過getContext("webgl")方法可以返回一個基於OpenGL ES2.0上下文的物件WebGLRenderingContext(後續簡稱webgl),透過webgl可以直接訪問GPU硬體資源,對碼農要求更高,最佳化空間更大。

    2D領域Canvas VS WebGL

    Canvas使用CoreGraphics渲染影象

    WebKit的實現程式碼

    context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

    對應GraphicsContext.cpp中的

    void GraphicsContext::drawNativeImage(imagePtr, imageSize, styleColorSpace, destRect, srcRect, op, blendMode, orientation) { ······ // Flip the coords. CGContextTranslateCTM(context, 0, adjustedDestRect.height()); CGContextScaleCTM(context, 1, -1); // Adjust the color space. image = Image::imageWithColorSpace(image.get(), styleColorSpace); // Draw the image. CGContextDrawImage(context, adjustedDestRect, image.get()); CGContextRestoreGState(context); ······ }

    WebGL直接使用OpenGL ES2.0渲染圖片:

    在《 07. WebApp2.0時代啟程:倒立者贏,從CPU到GPU,一張圖片的旅行 》中,這裡不重新做說明了。

    Canvas與WebGL的對比

    CoreGraphics是執行在CPU上的圖形庫

    它在iOS中已經深入的融合到UIView和UILayer框架中,架構圖如下:

    WebGL只是對OpenGL ES2.0的輕量級封裝

    js程式碼

    gl.bindTexture(gl.TEXTURE_2D, texID);

    在WebKit中對應於C++程式碼:

    void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) { makeContextCurrent(); if (m_state.activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D) m_state.boundTexture0 = texture; ::glBindTexture(target, texture); }

    圖形渲染WebGL完勝Canvas

    CPU在RAM中處理完圖片後,仍需要上傳到GPU中才可以顯示,同時,GPU圖形渲染速度比CPU提升10倍以上。

    Canvas的不可替代和WebGL的優勢

    Canvas提供高階的圖形渲染API

    直接使用DOM物件繪製圖形

    var canvas = document.getElementById("myCanvas"); var cxt=canvas.getContext("2d"); var img = new Image() img.src = "flower.png" cxt.drawImage(img, 0, 0);

    而WebGL需要負責的程式碼實現:

    gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);

    可以渲染文字

    使用 fillText(),在畫布上寫文字 "Hello world!" 和 "w3school.com.cn":

    JS程式碼為:

    var canvas=document.getElementById("myCanvas"); var ctx=canvas.getContext("2d"); ctx.font="20px Georgia"; ctx.fillText("Hello World!",10,50); ctx.font="30px Verdana"; // 建立漸變 var gradient=ctx.createLinearGradient(0,0,c.width,0); gradient.addColorStop("0","magenta"); gradient.addColorStop("0.5","blue"); gradient.addColorStop("1.0","red"); // 用漸變填色 ctx.fillStyle=gradient; ctx.fillText("w3school.com.cn",10,90);

    WebGL無此API,WebKit也是透過FreeType透過CPU來實現文字的載入與渲染。如果需要渲染文字,需要生成一個Canvas物件,在Canvas繪製完成之後,在直接渲染到WebGL空間。

    高效的上下文切換

    多個Canvas例項可以輕鬆切換,因為在CPU中他只是一個靜態的Bitmap。而WebGL上線文最好只有一個,切換上線文需要更改GPU硬體管線的狀態和flushbuffer,頻繁的切換會消耗大量的CPU資源。

    WebGL的優勢

    GPU的framebuffer直接push到Display

    CPU需要將渲染好的記憶體Bitmap上傳給GPU,然後透過display link到螢幕上。WebGL避免了CPU到GPU的大量的資料傳輸,只需要傳送指令給GPU即可。

    支援批次渲染

    支援vertexArray和IndiceArray,多個精靈共享一張文理,只需要將vertext資料緩衝到頂點資料,透過glDrawElements可以一次批次渲染。

    支援非同步操作

    Canvas的API每次都是同步操作,每次渲染必然同步到framebuffer中,不利於效能最佳化。WebGL可以自定義渲染機制和時機

  • 中秋節和大豐收的關聯?
  • 教師節祝福老師的話怎麼寫?