顯示GLSL碎片著色器作為網站背景。支持Shadertoy著色器,多通 - 乒乓球式屏幕緩衝區,反饋迴路,浮點紋理。使用WebGL 1或2,將嘗試在技術上盡可能地運行。
網站/演示: ? https://xemantic.github.io/shader-web-background?
❔???要問問題,請訪問Xmantic Discord Server☕???
我設計了此庫,將復雜的片段著色器作為我的網頁設計和開發過程的一部分。這是該工具最終使我可以將Web瀏覽器作為創意編碼環境擁抱。如果您熟悉GLSL,那麼它也可以幫助您在網上發布工作。如果您來自Web開發背景,那麼您可能想先了解更多有關著色器的信息,例如從著色者書中。我希望本文檔中介紹的例子是不言自明的。如果您覺得有用,那就
Github或https://www.buymeacoffee.com/kazik上的讚助商Xemantic
Kazik(Morisil)Pogoda
https://xemantic.com/
目錄
texture功能?tl; dr:
<!DOCTYPE html >
< html lang =" en " >
< head >
< meta charset =" utf-8 " >
< title > Minimal shader </ title >
< meta name =" viewport " content =" width=device-width, initial-scale=1 " >
< meta http-equiv =" X-UA-Compatible " content =" IE=edge " >
< script src =" https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js " > </ script >
< script type =" x-shader/x-fragment " id =" image " >
precision highp float ;
uniform float iTime ;
void main ( ) {
gl_FragColor = vec4 (
mod ( gl_FragCoord . x / 256. , 1. ) ,
mod ( ( gl_FragCoord . x + gl_FragCoord . y - iTime * 40. ) / 256. , 1. ) ,
mod ( gl_FragCoord . y / 256. , 1. ) ,
1.
) ;
}
</ script >
< script >
shaderWebBackground . shade ( {
shaders : {
image : {
uniforms : {
iTime : ( gl , loc ) => gl . uniform1f ( loc , performance . now ( ) / 1000 )
}
}
}
} ) ;
</ script >
< style >
.shader-web-background-fallback {
background: url("https://placekitten.com/666/666");
background-position: center;
background-size: cover;
background-attachment: fixed;
}
</ style >
</ head >
< body >
< h1 > shader-web-background minimal example </ h1 >
</ body >
</ html >如果您希望以身作則學習,以下是帶有其突出顯示的源代碼的演示列表:
https://xemantic.github.io/shader-web-background/#demo
有幾種方法可以根據您的需求調整此庫:
如果您希望著色器在加載任何其他資源之前開始渲染,請使用此方法。只需使用:
https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js
並將其作為<script>在HTML文件的<head>中。
有關參考(實時版本),請參見最小演示。
將此代碼添加到您的html的<head>中:
< script src =" https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js " > </ script > 將來,我會將shader-web-background發佈到NPM。現在,您可以將最新的縮小分發與源地圖和來源一起下載。
您將至少需要這樣定義一個片段著色器:
< script type =" x-shader/x-fragment " id =" image " >
precision highp float ;
void main ( ) {
// ...
}
</ script >將其放在HTML的<head>中。該type應為x-shader/x-fragment ,並且id屬性是任意的。
id 。
< script >
shaderWebBackground.shade( {
shaders : {
image : { }
}
} );
</ script >image應匹配定義為著色器源id屬性的圖像。
此步驟不是必需的,但是補充說,它將改善仍然無法在設備上運行著色器的少數用戶的體驗。
定義後備CSS樣式,例如著色器框架的靜態屏幕截圖:
< style >
.shader-web-background-fallback {
background: url("https://placekitten.com/666/666");
background-position: center;
background-size: cover;
background-attachment: fixed;
}
</ style > shader-web-background-fallback CSS類應用於HTML文檔根和畫布。
shader-web-background-fallback CSS類提供後備帆布背景,但是它可能對某些瀏覽器不起作用。跨兼容性可能需要自定義錯誤處理程序。
有關詳細信息,請參見處理錯誤部分。
查看完整的著色器 - 賓夕法尼亞州API
在上面的示例中傳遞給ShaderWebbackground的配置對象將傳遞給ShaderWebbackground.shade(config)調用,將導致最小的渲染管道,該管道由一個名為image的片段著色器組成。一個新的靜態<canvas id="shader-web-background">覆蓋整個視口的元素將以z-index: -9999添加到頁面上,將顯示在其他頁面元素後面。
注意:僅當整個DOM樹構造時,默認<canvas>元素才會將其附加到文檔<body> 。同樣,即使立即收集著著色器,陰暗器框架的實際渲染也不會發生。
制服為著色器提供了GPU以外的世界的輸入。描述這種機制的內容不超出本文檔的範圍。我決定不在WebGL的這一部分建立抽象,因為它已經很簡潔了。請參閱WebGlrenderingContext.均勻文檔。
假設您想為著色器提供自加載時的時間值以秒為單位。首先定義image著色器中的統一:
uniform float iTime; iTime名稱是任意的,但應與您在配置中指定的內容匹配:
shaderWebBackground . shade ( {
shaders : {
image : {
uniforms : {
iTime : ( gl , loc ) => gl . uniform1f ( loc , performance . now ( ) / 1000 )
}
}
}
} ) ; (gl, loc) => gl.uniform1f(loc, performance.now() / 1000)函數將在渲染每個著色器框架之前調用。如果您不熟悉JavaScript箭頭功能,則相當於:
function ( gl , loc ) {
gl . uniform1f ( loc , performance . now ( ) / 1000 )
}檢查標準JavaScript performance.now()函數的文檔,該功能返回自加載以來的毫秒數。除以1000 ,將導致以秒為單位測量的浮點值。
摘要:您可以使用此機制來調整任何API作為著色器的輸入。檢查項目演示以獲取示例如何集成輸入:
“紋理”統一的聲明使用sampler2D類型:
uniform sampler2D iWebCam;統一名稱是任意的。例如,Shadertoy是名稱iChannel0 , iChannel1等的綁定紋理。這主要是本文檔中使用的約定。
這樣的製服可以設置為:
shaderWebBackground . shade ( {
onInit : ( ctx ) => {
ctx . iWebCam = initializeTexture ( ctx . gl ) ;
} ,
shaders : {
image : {
uniforms : {
iWebCam : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . iWebCam ) ;
}
}
}
} ) ;紋理作為第二個參數傳遞給ctx.Texture可以是WebGlTexture的實例,也可以是對管道中另一個著色器的緩衝區的引用。檢查復雜的配置示例部分和API-上下文:緩衝區。
有關如何從圖像加載紋理的詳細信息,請參見添加紋理部分。
除了管道中的最後一個,所有的著色器都將具有相關的紋理呈現。默認情況下,這些紋理被初始化為帶有線性插值的RGBA HALF_FLOAT (16位)浮點,並將其夾在邊緣。可以自定義紋理初始化。有關詳細信息,請參見API-著色器:紋理文檔。
這是帶有註釋的配置對象的全面示例。它正在使用Shadertoy慣例來命名緩衝區和製服,但請記住,命名是任意的,可以根據您的項目需求進行調整。
// mouse coordinates taken from from the mousemove event expressed in "CSS pixels"
var mouseX ;
var mouseY ;
document . addEventListener ( "mousemove" , ( event ) => {
mouseX = event . clientX ;
mouseY = event . clientY ;
} ) ;
shaderWebBackground . shade ( {
// supplied canvas to use for shading
canvas : document . getElementById ( "my-canvas" ) ,
// called only once before the first run
onInit : ( ctx ) => {
// we can center the mouse even before any "mousemove" event occurs
// note, we are
mouseX = ctx . cssWidth / 2 ;
mouseY = ctx . cssHeight / 2 ;
// for convenience you can store your attributes on context
ctx . iFrame = 0 ;
} ,
onResize : ( width , height , ctx ) => {
ctx . iMinDimension = Math . min ( width , height ) ;
} ,
onBeforeFrame : ( ctx ) => {
ctx . shaderMouseX = ctx . toShaderX ( mouseX ) ;
ctx . shaderMouseY = ctx . toShaderY ( mouseY ) ;
} ,
shaders : {
// the first buffer to be rendered in the pipeline
BufferA : {
// uniform setters, attribute names should match with those defined in the shader
uniforms : {
// uniform value calculated in place
iTime : ( gl , loc ) => gl . uniform1f ( loc , performance . now ( ) / 1000 ) ,
// uniform values taken from context
iFrame : ( gl , loc ) => gl . uniform1i ( loc , ctx . iFrame ) ,
iMinDimension : ( gl , loc , ctx ) => gl . uniform1f ( loc , ctx . iMinDimension ) ,
iResolution : ( gl , loc , ctx ) => gl . uniform2f ( loc , ctx . width , ctx . height ) ,
iMouse : ( gl , loc , ctx ) => gl . uniform2f ( loc , ctx . shaderMouseX , ctx . shaderMouseY ) ,
// inputing the previous output of itself - feedback loop
iChannel0 : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . buffers . BufferA )
// ... more uniforms
}
} ,
// ... more shaders
BufferD : {
// optional custom initializer of buffer's texture
texture : ( gl , ctx ) => {
// initializing floating-point texture in custom way for WebGL 1 and 2
ctx . initHalfFloatRGBATexture ( ctx . width , ctx . height ) ;
// standard WebGL texture parameters
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MIN_FILTER , gl . NEAREST ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MAG_FILTER , gl . NEAREST ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_WRAP_S , gl . REPEAT ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_WRAP_T , gl . REPEAT ) ;
} ,
uniforms : {
iChanel0 : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . buffers . BufferA )
// ... more uniforms
}
} ,
// the last shader will render to screen
Image : {
uniforms : {
iChanel0 : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . buffers . BufferD )
// ... more uniforms
}
}
} ,
onAfterFrame : ( ctx ) => {
ctx . iFrame ++ ;
} ,
// custom error handler
onError : ( error , canvas ) => {
canvas . remove ( ) ;
console . error ( error ) ;
document . documentElement . classList . add ( "my-fallback" ) ;
}
} ) ; API旨在自我解釋。檢查API規範以獲取詳細信息。上面的示例中定義了幾個著色器。它們將在Shadertoy命名法中按順序處理稱為Multipass 。定義的著色器的最後一個將渲染到屏幕上。以前的著色器的輸出,包括同一著色器呈現的先前幀的反饋迴路,可以輕鬆地傳遞給制服。
在提供的配置上正在進行一些驗證,以避免常見問題,否則通常很難調試。 SRC/test/html/errors/文件夾包含所有錯誤測試用例,也可以在錯誤處理的實時演示中檢查。
所有錯誤和警告將在控制台上可見。
看:
// mouse coordinates taken from from the mousemove event
var mouseX ;
var mouseY ;
document . addEventListener ( "mousemove" , ( event ) => {
mouseX = event . clientX ;
mouseY = event . clientY ;
} ) ;
// mouse coordinates relative to the shader, you can also store them on the context
var shaderMouseX ;
var shaderMouseY ;
shaderWebBackground . shade ( {
onInit : ( ctx ) => {
// screen center
mouseX = ctx . cssWidth / 2 ;
mouseY = ctx . cssHeight / 2 ;
} ,
onBeforeFrame : ( ctx ) => {
shaderMouseX = ctx . toShaderX ( mouseX ) ;
shaderMouseY = ctx . toShaderY ( mouseY ) ;
} ,
shaders : {
image : {
uniforms : {
iMouse : ( gl , loc ) => gl . uniform2f ( loc , shaderMouseX , shaderMouseY )
}
}
}
} ) ;注意:初始鼠標坐標是在onInit函數中提供的,因為第一個mousemove事件可以在啟動著色器後很長時間發生。著色器坐標從畫布的底部左下角開始,並與像素的中間對齊 - (0.5, 0.5) 。
API參考:
演示:
python -m http.server 8000如果它不適用於您最新的Ubuntu,那麼首先是運行sudo apt install python-is-python3 。
參見紋理:藍色大理石到平坦的地球映射演示
可以將紋理設置為以相同的方式將緩衝區設置為製服,但首先我們需要加載它們。例如,通過定義可以重複使用的自定義承諾:
const loadImage = ( src ) => new Promise ( ( resolve , reject ) => {
let img = new Image ( ) ;
img . onload = ( ) => resolve ( img ) ;
img . onerror = ( ) => {
reject ( new Error ( "Failed to load image from: " + src ) ) ;
}
img . src = src ;
} ) ; onInit函數是調用loadPicture方便場所:
shaderWebBackground . shade ( {
onInit : ( ctx ) => {
loadImage ( "texture.jpg" )
. then ( image => {
const gl = ctx . gl ;
const texture = gl . createTexture ( ) ;
gl . bindTexture ( gl . TEXTURE_2D , texture ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_WRAP_S , gl . CLAMP_TO_EDGE ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_WRAP_T , gl . CLAMP_TO_EDGE ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MIN_FILTER , gl . LINEAR ) ;
gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
gl . texImage2D ( gl . TEXTURE_2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED_BYTE , image ) ;
gl . bindTexture ( gl . TEXTURE_2D , null ) ;
ctx . iTexture = texture ;
} ) ;
} ,
shaders : {
image : {
uniforms : {
iTexture : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . iTexture )
}
}
}
} ) ; 該庫可以用最少的精力利用Shadertoy代碼 - 簡單的著色器包裝:
< script type =" x-shader/x-fragment " id =" Image " >
precision highp float ;
uniform vec2 iResolution ;
uniform float iTime ;
// ... other needed uniforms
// -- Paste your Shadertoy code here:
// ...
// -- End of Shadertoy code
void main ( ) {
mainImage ( gl_FragColor , gl_FragCoord . xy ) ;
}
</ script > <script>的id屬性設置為反映稱為Image的ShaderToy選項卡。大多數著色器至少會使用這兩種制服,並且在配置中提供其值很容易:
shaderWebBackground . shade ( {
shaders : {
Image : {
uniforms : {
iResolution : ( gl , loc , ctx ) => gl . uniform2f ( loc , ctx . width , ctx . height ) ,
iTime : ( gl , loc ) => gl . uniform1f ( loc , performance . now ( ) / 1000 ) ,
}
}
}
} ) ;Shadertoy演示:
沒有自動解決方案。您將必須將Common部分直接複製到其他Shadertoy代碼上方。
texture功能?在Shadertoy中,在WebGL 1中使用texture功能。它是texture2D 。這是一個簡單的解決方法,要在原始代碼之前添加:
#define texture texture2D在Shadertoy中,每個“通道”綁定紋理可以具有單獨的採樣器參數,例如插值或包裝。此功能不能輕易移植到WebGL 1,但是大多數在這些功能上傳遞的著色器都可以使用基於代碼的解決方法調整。例如,如果應該重複紋理,那麼類似的東西可能是給定著色器中texture函數的功能替換:
vec4 repeatedTexture( in sampler2D channel, in vec2 uv) {
return texture2D (channel, mod (uv, 1 .));
}另請參見API-著色器:紋理。
您可以根據Shadertoy緩衝區名稱命名著著色器:
BufferABufferBBufferCBufferDImage然後將它們連接在一起:
<!DOCTYPE html >
< html lang =" en " >
< head >
< title > Multipass Shadertoy shader </ title >
< script type =" x-shader/x-fragment " id =" BufferA " >
precision highp float ;
uniform sampler2D iChannel0 ;
// ... the code of BufferA tab with the uniforms and wrapping as above
</ script >
< script type =" x-shader/x-fragment " id =" Image " >
precision highp float ;
uniform sampler2D iChannel0 ;
// ... the code of Image tab with the uniforms and wrapping as above
</ script >
< script >
// ... your prefer method of loading shader-web-background as described above
</ script >
< script >
shaderWebBackground . shade ( {
shaders : {
BufferA : {
uniforms : {
iChannel0 : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . buffers . BufferA )
}
} ,
Image : {
uniforms : {
iChannel0 : ( gl , loc , ctx ) => ctx . texture ( loc , ctx . buffers . BufferA )
}
}
}
} ) ;
</ script >
</ head >
< body >
</ body >
</ html > 可以通過在<head> ::
< script type = "x-shader/x-vertex" id = "shaderIdVertex" >
attribute vec2 V;
varying vec2 uv;
void main() {
gl_Position = vec4 ( V , 0 , 1 ) ;
}
</ script >
< script type = "x-shader/x-fragment" id = "shaderId" >
// ...
varying vec2 uv ;
// ...
< / script >注意:腳本type設置為x-shader/x-vertex ,並且id屬性用頂點Vertex進行了啟用。頂點屬性應命名為V 。
注意:可以指定varying vec2 uv在頂點和片段著色器之間共享(默認情況下不添加)。
git clone https://github.com/xemantic/shader-web-background.git
cd shader-web-background
./gradlew compileJs它將觸發Google Cloes Closure編譯器,該編譯器將使用類型信息檢查源並將其轉換為縮小的JavaScript文件:
該項目是使用Intellij Ideas開發的,並啟用了Google-Java-Format插件。該樣式中最明顯的元素是2個空間,而不是4個用於渲染選項卡的空間。
任何一個:
<section id="projects-using-shader-web-background">或給我發送帶有描述的鏈接。