準(zhǔn)備好了環(huán)境以后(未安裝請(qǐng)移步http://www.reibang.com/p/fdf87797e5ba)蠢涝,新建一個(gè)文件名為01-第一段shaderToy代碼.glsl刃永,并用vscode工具打開(kāi)爆捞,輸入如下代碼
//他是一個(gè)內(nèi)置的函數(shù),函數(shù)名是固定的,不能修改
//iTime是一個(gè)內(nèi)置的全局變量籍铁,表示時(shí)間,是一個(gè)float類型的變量,表示從程序開(kāi)始運(yùn)行到當(dāng)前時(shí)間的秒數(shù)
vec2 ClipCoord(in vec2 fragCoord) {
//偏移歸一化坐標(biāo)
//fragCoord是片元坐標(biāo),iResolution.xy是屏幕分辨率癌幕,
//這里fragCoord / iResolution.xy是將屏幕坐標(biāo)轉(zhuǎn)換為[0,1]的歸一化坐標(biāo)
//然后減去0.5,是將坐標(biāo)系原點(diǎn)從左上角移動(dòng)到中心
//為什么能夠減去0.5呢昧穿?因?yàn)闅w一化坐標(biāo)是[0,1]勺远,所以坐標(biāo)系的中心是0.5
//但是為什么iResolution.xy可以減去0.5,因?yàn)閤y是vec2類型时鸵,是一個(gè)二維向量胶逢,所以可以直接減去0.5
//向量減去一個(gè)數(shù),是將向量的每個(gè)分量都減去這個(gè)數(shù)饰潜,
//最終返回的是一個(gè)以中心為原點(diǎn)的歸一化坐標(biāo)
return 2. * (fragCoord / iResolution.xy - 0.5);
}
// vec2 ClipCoord2(in vec2 fragCoord) {
// //偏移歸一化坐標(biāo)
// return 2. * (fragCoord - 0.5 * iResolution.xy) / iResolution.x;
// }
struct bg_color {
vec3 color;
float time;
};
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
//片元著色器代碼,入?yún)槠鴺?biāo)初坠,出參為片元顏色
//bg_color是一個(gè)結(jié)構(gòu)體,包含了一個(gè)vec3類型的color和一個(gè)float類型的time
//這里bg是一個(gè)bg_color類型的變量彭雾,初始化了一個(gè)vec3類型的顏色和一個(gè)時(shí)間
bg_color bg = bg_color(vec3(1., 1.0, 0.0), iTime);
vec2 uv = ClipCoord(fragCoord);
// vec2 uv = ClipCoord2(fragCoord);
//length函數(shù)是一個(gè)內(nèi)置函數(shù)碟刺,用來(lái)計(jì)算向量的長(zhǎng)度,這里是計(jì)算uv向量的長(zhǎng)度
float coordlen = length(uv);
float iTimeYS = bg.time - floor(bg.time);
//先來(lái)一個(gè)純色背景
fragColor = vec4(bg.color, 1);
// //如何在shader toy中取余數(shù)呢:iTime % 1.0這樣是不對(duì)的冠跷,因?yàn)椴恢С诌@樣的寫法南誊,正確的寫法是iTime - floor(iTime)
// //這里的iTimeYS會(huì)突然變成0,這樣會(huì)導(dǎo)致顏色跳動(dòng)蜜托,所以我們需要他是一個(gè)0-1然后再1-0的過(guò)程
// //這樣的話抄囚,顏色就會(huì)平滑的變化
// //我們可以通過(guò)cos函數(shù)來(lái)實(shí)現(xiàn)這樣的效果,iTimeYS是一個(gè)0-1的過(guò)程橄务,cos(iTimeYS * 3.1415926)是一個(gè)1-0-1的過(guò)程
// fragColor = vec4(cos(bg.time), bg.color.y, 1. - cos(bg.time), 1);
// //如果長(zhǎng)度小于0.5(相當(dāng)于以屏幕中心為原點(diǎn)幔托,半徑在0.5以內(nèi)),那么將顏色設(shè)置為紅色
if(coordlen <= 0.5) {
fragColor = vec4(coordlen * 2., 1, 1, 1);
}
// fragColor = vec4(coordlen, 0, 0, 1);
}
保存代碼蜂挪,右鍵Shader Toy:Show GLSL Preview你將會(huì)看到如下界面:
接下來(lái)重挑,我們將一行行的解釋代碼,以便于新手了解我們的程序如何運(yùn)作:
首先shader toy提供一個(gè)入口函數(shù)mainImage棠涮,和一個(gè)內(nèi)置變量iTime:
mainImage是片元著色器代碼的函數(shù)名(這個(gè)名稱不能改變谬哀,shader toy會(huì)調(diào)用這個(gè)函數(shù),如果你改了就找不到了)严肪,入?yún)槠鴺?biāo)史煎,出參為片元顏色
iTime是浮點(diǎn)數(shù)時(shí)間谦屑,從程序運(yùn)行開(kāi)始計(jì)數(shù),單位為秒
1.我們新建一個(gè)ClipCoord函數(shù)
為何先要新建函數(shù)呢篇梭?因?yàn)檫@里沒(méi)有變量提升的概念氢橙,我們要用之前都需要先新建好。
ClipCoord函數(shù)的意義是偏移并歸一化坐標(biāo)恬偷,它把以左上角為原點(diǎn)的屏幕坐標(biāo)系悍手,轉(zhuǎn)化為以屏幕中心為原點(diǎn)的歸一化坐標(biāo)系,”fragCoord / iResolution.xy“ 是歸一化屏幕坐標(biāo)袍患,歸一化以后再”-0.5“是為了再XY軸上偏移一半的距離坦康,這樣原點(diǎn)就由左上角移動(dòng)到了中心,但是為了不讓單條軸的范圍是(-0.5,0.5),我們給他乘以2(這里可以理解為縮放)协怒,讓它變成(-1,1)這樣方便我們觀察涝焙,也能緩解強(qiáng)迫癥
2.新建一個(gè)構(gòu)造體bg_color
入?yún)関ec3初始背景色,外加一個(gè)時(shí)間參數(shù)(為了后續(xù)做動(dòng)畫使用)孕暇,這個(gè)構(gòu)造體僅僅只是為了把需要用到的參數(shù)集中管理,實(shí)際上不用構(gòu)造體赤兴,僅用普通的變量也可以實(shí)現(xiàn)
3.新建一個(gè)mainImage函數(shù)(該函數(shù)名稱不能修改妖滔,它是shader toy內(nèi)置入口函數(shù))
函數(shù)內(nèi)依次:
創(chuàng)建背景構(gòu)造體,
獲取半徑(后續(xù)用于判斷圖像范圍)
給背景賦值背景色(給整個(gè)畫布繪制顏色)
判斷圓形范圍(處于半徑內(nèi)的任何片元都是圓形區(qū)域)
在圓形區(qū)域內(nèi)用圓的顏色覆蓋背景色(由于之前已經(jīng)繪制過(guò)背景色桶良,此時(shí)的繪制實(shí)際上相當(dāng)于在背景色之上覆蓋圓形的顏色)
大工告成座舍,代碼重還有一些通過(guò)時(shí)間變量來(lái)改變顏色的代碼段,可以讓圖像動(dòng)起來(lái)陨帆,各位可以自行研究
總結(jié):
背景和圓形都是通過(guò)計(jì)算的每一個(gè)片元的顏色來(lái)繪制的曲秉,片元著色器的意義就是根據(jù)你給定的邏輯給屏幕上色,而在編寫邏輯的時(shí)候常常運(yùn)用到一些數(shù)學(xué)知識(shí)比如繪制圓和三角函數(shù)計(jì)算疲牵,不過(guò)不用擔(dān)心只要有高中數(shù)學(xué)水平就能夠?qū)崿F(xiàn)大部分的效果
要點(diǎn):
1.浮點(diǎn)數(shù)必須和浮點(diǎn)數(shù)計(jì)算承二,所以代碼中有“1.”、“.5”這樣的寫法
2.沒(méi)有變量提升纲爸,要使用的變量與函數(shù)都需要提前聲明
3.要認(rèn)識(shí)shader toy的內(nèi)置函數(shù)和內(nèi)置變量
留下兩個(gè)問(wèn)題:
1.為什么繪制的圓有一些拉伸變形亥鸠?
2.為什么下面這個(gè)計(jì)算公式的對(duì)象有xy兩個(gè)值卻能直接減去0.5?fragCoord / iResolution.xy - 0.5