Minecraft GLSL Shader著色器基礎(chǔ)教程#2 核心著色器

回顧
在上節(jié)教程中,我們介紹了后處理著色器中的渲染管線以及著色器程序(json)的格式,有5個(gè)可選的渲染管線,分別在旁觀末影人(invert)、苦力怕(creeper)、蜘蛛(spider),屏幕內(nèi)有發(fā)光實(shí)體(entity_outline),1.16+啟用極佳畫質(zhì)(transparency)時(shí)啟用。后處理著色器對(duì)整個(gè)屏幕生效,所有像素將被同時(shí)讀取。

核心著色器
核心著色器(Core Shader)是Java版1.17加入的全新功能,允許玩家更加全面地更改游戲渲染內(nèi)容。核心著色器負(fù)責(zé)渲染游戲的各個(gè)部分(如方塊、實(shí)體、界面元素等等)。和后處理著色器類似,每個(gè)核心著色器都是由JSON文件定義的單個(gè)渲染程序,其中指定了頂點(diǎn)和片段著色器文件,不同的游戲內(nèi)容使用不同的核心著色器,學(xué)習(xí)核心著色器最大的難點(diǎn)在于如何檢測(cè)特定的游戲內(nèi)容并更改。
下面展示幾個(gè)核心著色器能做到的效果:



原版所有的核心著色器存儲(chǔ)在shaders/core目錄中。
后續(xù)我會(huì)在動(dòng)態(tài)和該專欄評(píng)論區(qū)發(fā)布每個(gè)方塊對(duì)應(yīng)的核心著色器,關(guān)于每個(gè)核心著色器渲染的內(nèi)容可以在Minecraft Fandom?Wiki上查看"著色器"頁面
核心著色器渲染的對(duì)象是游戲內(nèi)容的每個(gè)像素,能夠獲取比后處理著色器更多的信息,如:頂點(diǎn)的位置、顏色信息,紋理采樣器,包括運(yùn)算需要的投影矩陣和旋轉(zhuǎn)矩陣。(后處理著色器只能獲得屏幕上某個(gè)坐標(biāo)的顏色),關(guān)于這些內(nèi)容將在下文的fsh、vsh編寫中介紹。
核心著色器JSON
核心著色器也由一個(gè)著色器程序json調(diào)用vsh和fsh,json格式和后處理一致,但在attributes列表中多了一些列可以使用的屬性UV、UV0、UV1、UV2、Normal、Color等。(其中UV0-2以及Normal作用不明,可能會(huì)在未來的某些時(shí)間更新教程)

GLSL語言
片段著色器(fsh)、和頂點(diǎn)著色器(vsh)的內(nèi)容都采用GLSL編寫,支持變量、函數(shù)、循環(huán)等基本的編程要素,但由于無法自由訪問內(nèi)存,GLSL并不支持遞歸操作。
有關(guān)核心語言的更多信息:khronos.org/opengl/wiki/Core_Language_(GLSL)
有關(guān)所有可用函數(shù)的詳細(xì)文檔:docs.gl/sl4/all
GLSL的語法類似于C語言,有編程基礎(chǔ)的讀者可以選擇性閱讀本段內(nèi)容
工作流程
vsh和fsh中都應(yīng)有且只有一個(gè)main函數(shù),沒有參數(shù)和返回值(void),主函數(shù)在vsh和fsh中的任務(wù)分別是更新gl_Position或gl_FragColor這兩個(gè)變量,這兩個(gè)變量是GLSL中特殊的變量,使用時(shí)不需要聲明,且值的類型都為vec4。gl_FragColor也可以被一個(gè)聲明為out vec4 fragColor的變量代替(原版所有的fsh都使用了后面一種寫法,但仍然可以使用gl_FragColor的寫法,而不會(huì)出現(xiàn)錯(cuò)誤)
數(shù)據(jù)類型
GLSL有三種數(shù)據(jù)類型、分別是標(biāo)量、向量、矩陣,用于一系列計(jì)算
GLSL允許在構(gòu)造矩陣或向量時(shí)隨意組合其他其他的標(biāo)量/向量,但要注意數(shù)據(jù)的個(gè)數(shù)以及類型,如:
除了[索引]外GLSL允許使用rgba或xyzw來訪問向量的(0-3號(hào))成員,這些字符也可以隨意組合
注意:形如rgba的數(shù)據(jù)是一個(gè)vec4,類似foo.rgba?= 1.0的代碼是錯(cuò)誤的,應(yīng)該使用vec4(1.0)或vec4(1.0, 1.0, 1.0, 1.0)進(jìn)行賦值。盡管rgba和xyzw之間可以混用,但一般還是用rgba表示顏色,xyzw表示位置,防止混淆
變量修飾符
GLSL中可以將變量以uniform(全局量)、in(傳入變量)、out(傳出變量)
PS:在21w10a(1.17)后,原版著色器的GLSL版本由120升級(jí)到了150,原本varying(傳遞量)和attribute(屬性)現(xiàn)在變?yōu)榱薸n和out,具體可在原版.jar文件中查看示例,這里采用新版本的寫法和譯法
uniform全局量和后處理一樣,可以通過著色器程序?qū)?yīng)的json來聲明,同樣,在專欄末尾再次給出特殊作用的全局量列表
in傳入變量和out傳出變量配合使用,可以將變量在不同著色器流程中傳遞,vsh中使用in傳入的變量似乎是寫死的,但對(duì)于fsh則可以將變量聲明為in來表示vsh中聲明為out的變量,下面是原版核心著色器中的代碼
Position、UV、Color為傳入變量,對(duì)于核心著色器來說、Position是頂點(diǎn)的初始位置(值是該頂點(diǎn)相對(duì)于區(qū)塊原點(diǎn)的三維坐標(biāo),在0.0和16.0之間);UV是一個(gè)二維坐標(biāo),每項(xiàng)的值在0.0和1.0之間、用于在一張名為atlas的紋理合集上獲取需要的紋理,可以通過UV檢查著色器正在渲染的方塊,但atlas會(huì)隨著資源包中紋理數(shù)量的改變而改變,這種方法可能會(huì)因?yàn)榧y理數(shù)量的改變而受影響;Color則是該頂點(diǎn)的紋理顏色
后處理著色器似乎只有Position這個(gè)傳入變量,表示頂點(diǎn)在屏幕上的二維坐標(biāo)。
因?yàn)楹筇幚碇鞯膶?duì)象是一個(gè)平面,vsh和fsh的坐標(biāo)值都相同且都為vec2類型的屏幕坐標(biāo),整個(gè)屏幕左下角的坐標(biāo)是(0.0, 0.0),右上角為(1.0, 1.0)坐標(biāo)的值為負(fù)或大于1.0時(shí)并不會(huì)報(bào)錯(cuò),但并沒有實(shí)際意義。此外,我們還可以通過全局量InSize或OutSize兩個(gè)全局量來檢測(cè)玩家窗口的大小以及點(diǎn)的實(shí)際像素坐標(biāo)。
核心著色器則有兩個(gè)不同的坐標(biāo),在vsh中則有頂點(diǎn)的空間坐標(biāo),fsh中則有該點(diǎn)的紋理坐標(biāo),同樣紋理左下角為(0.0, 0.0),右上角為(1.0, 1.0),坐標(biāo)并不以紋理中的像素為單位。
texCoord、vertexColor是由vsh中同名變量傳遞而來,在vsh聲明為out,在fsh聲明為in,這樣就可以將變量在不同著色器流程中傳遞。這兩個(gè)變量的計(jì)算過程在vsh中,前者在核心著色器中被賦值為變量UV,即atlas紋理集中的UV坐標(biāo)(同樣名稱的變量在后處理著色器中則為被采樣點(diǎn)的屏幕坐標(biāo))后者只在核心著色器中使用,被賦值為Color,即該點(diǎn)的紋理顏色,讀者可以自己在原版文件中閱讀計(jì)算過程。
采樣器
GLSL中還有一種特殊的變量,稱為采樣器Sampler,原版中只使用了平面采樣器(sampler2D),這里就不再說明其他的采樣器,感興趣的讀者可以在glsl的官方文檔上學(xué)習(xí)。
sampler2D類型的變量可以通過一些列以textrue開頭的函數(shù)獲取數(shù)據(jù),在原版中則是使用了texture()和texture2D()來獲取紋理顏色。以texture2D為例,其語法為:
(vec4) texture2D(sampler2D sampler, vec2 texCoord);
一些特殊的著色器可能需要不止一張紋理數(shù)據(jù),所以會(huì)出現(xiàn)多個(gè)采樣器,可以通過原版的代碼來分辨采樣器的作用。原版一般將以DiffuseSampler、Sampler0為變量名的sampler2D作為紋理的采樣器,以DepthSampler為變量名作為深度采樣器
著色器中,和顏色相關(guān)的變量一般是vec4類型,分別對(duì)應(yīng)Red(紅色)、Green(綠色)、Blue(藍(lán)色)、Alpha(不透明度)四個(gè)通道(有些可能為vec3,則對(duì)應(yīng)RGB三個(gè)通道)。和紋理坐標(biāo)一樣,每個(gè)顏色通道的值一般也都在0.0到1.0之間,和常用的0-255不同,檢測(cè)顏色時(shí)需要注意這一點(diǎn)。
原版著色器還有一種深度信息,在之后正式制作著色器的教程中會(huì)介紹。
全局量列表
下節(jié)預(yù)告:后處理著色器應(yīng)用篇

本篇教程描述比較簡(jiǎn)短,但內(nèi)容非常重要,編寫著色器時(shí)可能會(huì)因?yàn)橐恍┘?xì)節(jié)問題導(dǎo)致錯(cuò)誤,所以建議多次消化本篇教程。
下面是一個(gè)簡(jiǎn)單的核心著色器,讀者可以通過拆包了解

下載地址:https://github.com/ShockMicro/CorePerspectiveModels
添加了一種在玩家手上和物品欄里顯示不同模型的方法。注意要把物品欄模型的紋理alpha通道設(shè)置為253,把手上物品模型的紋理alpha通道設(shè)置為254,將手上和物品欄中的模型放在一個(gè)模型文件中,并加上正確的紋理,把文件都放在正確的位置,即可使用