OpenGL
- 開(kāi)放圖形庫(kù)或者“開(kāi)放式圖形庫(kù)” 是用于渲染2D、3D矢量圖形的跨語(yǔ)言邻辉、跨平臺(tái)的應(yīng)用程序編程接口規(guī)范(API規(guī)范).
- 是Khronos Group開(kāi)發(fā)維護(hù)的一個(gè)規(guī)范尚洽,它主要為我們定義了用來(lái)操作圖形和圖片的一系列函數(shù)的API刨沦,需要注意的是OpenGL本身并非API记盒。
- GPU的硬件開(kāi)發(fā)商則需要提供滿足OpenGL規(guī)范的實(shí)現(xiàn)体啰,這些實(shí)現(xiàn)通常被稱為“驅(qū)動(dòng)”稻扬,它們負(fù)責(zé)將OpenGL定義的API命令翻譯為GPU指令卦方。顯卡驅(qū)動(dòng)中包括了對(duì)OpenGL規(guī)范的實(shí)現(xiàn)。
競(jìng)品:
metal 蘋(píng)果的
vulkan
directX/direct3D 微軟的(對(duì)應(yīng)編程語(yǔ)言HLSL)
shader
https://learnopengl-cn.github.io/01%20Getting%20started/05%20Shaders/
著色器(Shader)是運(yùn)行在GPU上的小程序泰佳。這些小程序?yàn)閳D形渲染管線的某個(gè)特定部分而運(yùn)行盼砍。從基本意義上來(lái)說(shuō),著色器只是一種把輸入轉(zhuǎn)化為輸出的程序逝她。著色器也是一種非常獨(dú)立的程序浇坐,因?yàn)樗鼈冎g不能相互通信;它們之間唯一的溝通只有通過(guò)輸入和輸出黔宛。
https://blog.csdn.net/onafioo/article/details/38983197
著色程序分為兩類:vertex shader program(頂點(diǎn)著色程序)和fragment shader program(片斷著色程序)吗跋。對(duì)應(yīng)GPU上的兩個(gè)組件:Programmable Vertex Processor(可編程頂點(diǎn)處理器,又稱為頂點(diǎn)著色器)和 Programmable Fragment Processor(可編程片斷處理器宁昭,又稱為片斷著色器)跌宛。頂點(diǎn)和片段處理器被分離成可編程單元,可編程頂點(diǎn)處理器是一個(gè)硬件單元积仗,可以運(yùn)行頂點(diǎn)程序疆拘,而可編程片段處理器則是一個(gè)可以運(yùn)行片段程序的單元。
頂點(diǎn)和片段處理器都擁有非常強(qiáng)大的并行計(jì)算能力
什么是片斷寂曹?片斷和像素有什么不一樣哎迄?所謂片斷就是所有的三維頂點(diǎn)在光柵化(矢量圖轉(zhuǎn)成位圖)之后的數(shù)據(jù)集合,這些數(shù)據(jù)還沒(méi)有經(jīng)過(guò)深度值比較隆圆,而屏幕顯示的像素都是經(jīng)過(guò)深度比較的漱挚。
頂點(diǎn)著色器控制頂點(diǎn)坐標(biāo)轉(zhuǎn)換過(guò)程;片段著色器控制像素顏色計(jì)算過(guò)程渺氧。這樣就區(qū)分出頂點(diǎn)著色程序和片段著色程序的各自分工:Vertex program負(fù)責(zé)頂點(diǎn)坐標(biāo)變換和幾何計(jì)算旨涝;Fragment program負(fù)責(zé)像素顏色計(jì)算;前者的輸出是后者的輸入侣背。
GLSL
聲明
著色器是使用一種叫GLSL的類C語(yǔ)言寫(xiě)成的白华, GPU變成語(yǔ)言
著色器的開(kāi)頭總是要聲明版本慨默,接著是輸入和輸出變量、uniform和函數(shù)弧腥。每個(gè)著色器的入口點(diǎn)都是函數(shù)厦取,在這個(gè)main函數(shù)中我們處理所有的輸入變量,并將結(jié)果輸出到輸出變量中管搪。
#version version_number
in type in_variable_name;
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
int main()
{
// 處理輸入并進(jìn)行一些圖形操作
...
// 輸出處理過(guò)的結(jié)果到輸出變量
out_variable_name = weird_stuff_we_processed;
}
分類:
-
vertexShader: 數(shù)量有限 跟硬件有關(guān)虾攻,一般不少于16個(gè)
fragmentShader
著色器是各自獨(dú)立的小程序,每個(gè)著色器都有輸入和輸出更鲁,并進(jìn)行數(shù)據(jù)交流和傳遞台谢。一個(gè)輸出變量與下一個(gè)著色器階段的輸入匹配(名字相同),它就會(huì)傳遞下去岁经。
vertexShader從頂點(diǎn)數(shù)據(jù)中直接接收輸入,使用?location?這一元數(shù)據(jù)指定輸入變量朋沮。頂點(diǎn)著色器需要為它的輸入提供一個(gè)額外的?layout?標(biāo)識(shí),這樣我們才能把它鏈接到頂點(diǎn)數(shù)據(jù)?layout (location = 0)?缀壤。在OpenGL代碼中使用查詢屬性位置值(Location)
fragment樊拓,它需要一個(gè)?vec4?顏色輸出變量,因?yàn)槠沃餍枰梢粋€(gè)最終輸出的顏色塘慕。如果你在片段著色器沒(méi)有定義輸出顏色筋夏,OpenGL會(huì)把你的物體渲染為黑色(或白色)。
數(shù)據(jù)類型:
基礎(chǔ)類型 ?int?图呢、?float?条篷、?double?、?uint蛤织、bool?
容器類型:Vector赴叹、Matrix
Vector類型:
- 可以包含1-4個(gè)基礎(chǔ)類型的分量
<colgroup><col width="395"><col width="395"></colgroup>
| 類型 | 含義 |
| vecn | 包含n個(gè)float分量的默認(rèn)向量 |
| bvecn | 包含n個(gè)bool分量的向量 |
| ivecn | 包含n個(gè)int分量的向量 |
| uvecn | 包含n個(gè)unsigned int分量的向量 |
| dvecn | 包含n個(gè)double分量的向量 |
重組swizzling
一個(gè)向量的分量可以通過(guò)?vec.x?這種方式獲取,這里?x?是指這個(gè)向量的第一個(gè)分量指蚜。你可以分別使用?.x?乞巧、?.y?、?.z?和?.w?來(lái)獲取它們的第1摊鸡、2绽媒、3、4個(gè)分量免猾。GLSL也允許你對(duì)顏色使用?rgba?是辕,或是對(duì)紋理坐標(biāo)使用?stpq?訪問(wèn)相同的分量。
向量這一數(shù)據(jù)類型也允許一些有趣而靈活的分量選擇方式猎提,叫做(Swizzling)获三。重組允許這樣的語(yǔ)法:
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;
你可以使用上面4個(gè)字母任意組合來(lái)創(chuàng)建一個(gè)和原來(lái)向量一樣長(zhǎng)的(同類型)新向量,只要原來(lái)向量有那些分量即可;然而石窑,你不允許在一個(gè)vec2向量中去獲取.z元素。我們也可以把一個(gè)向量作為一個(gè)參數(shù)傳給不同的向量構(gòu)造函數(shù)蚓炬,以減少需求參數(shù)的數(shù)量:
vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0);
uniform
是一種從CPU中的應(yīng)用向GPU中的著色器發(fā)送數(shù)據(jù)的方式松逊,但uniform和頂點(diǎn)屬性有些不同。首先肯夏,uniform是(Global)经宏。全局意味著uniform變量必須在每個(gè)著色器程序?qū)ο笾卸际仟?dú)一無(wú)二的,而且它可以被著色器程序的任意著色器在任意階段訪問(wèn)驯击。第二烁兰,無(wú)論你把uniform值設(shè)置成什么,uniform會(huì)一直保存它們的數(shù)據(jù)徊都,直到它們被重置或更新沪斟。
輸入輸出
vertexShader與fragShader鏈接
**頂點(diǎn)著色器**
#version 330 core
layout (location = 0) in vec3 aPos; // 位置變量的屬性位置值為0
out vec4 vertexColor; // 為片段著色器指定一個(gè)顏色輸出
void main()
{
gl_Position = vec4(aPos, 1.0); // 注意我們?nèi)绾伟岩粋€(gè)vec3作為vec4的構(gòu)造器的參數(shù)
vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把輸出變量設(shè)置為暗紅色
}
**片段著色器**
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // 從頂點(diǎn)著色器傳來(lái)的輸入變量(名稱相同、類型相同)
void main()
{
FragColor = vertexColor;
}
如何使用GLSL
使用canvas.getContext('webgl'), 就可以使用gl實(shí)例的語(yǔ)法了 eg
.createShader(shaderType)
.shaderSource(shaderInstance, option)
.compileShader(shaderInstance)
.createProgram()
.attachShader(programInstance, shaderInstance)
.linkProgram(programInstance)
.useProgram(programInstance)
.createBuffer()
.bindBuffer(bufferType, bufferInstance)
.bufferData(bufferType, data)
.vertexAttribArrary()
.enableVertexAttribArray(position)
.drawArrays()
可以解決前端的什么問(wèn)題呢暇矫?
生成圖片主之、修改圖片
減少引入切圖
結(jié)論
但是使用OpenGL繪制圖形還是很難的(很多時(shí)候是一個(gè)數(shù)學(xué)問(wèn)題)吧 所以權(quán)衡一下把