GLSLフラグメントシェーダーをWebサイトの背景として表示します。 Shadertoy Shaders、Multipass-Ping-Pong Offscreenバッファー、フィードバックループ、フローティングポイントテクスチャをサポートします。 WebGL 1または2のいずれかで、技術的にどこでも実行しようとします。
ウェブサイト/デモ: ? https://xemantic.github.io/shader-web-background?
❔???質問するには、Xemantic Discord Server☕にアクセスしてください???
このライブラリを設計して、Webデザインと開発プロセスの一部として複雑なフラグメントシェーダーを使用しました。これは、最終的に創造的なコーディング環境としてWebブラウザを受け入れることができるツールです。 GLSLに精通している場合は、Webで作業を公開するのに役立つ可能性があります。 Web開発のバックグラウンドから来ている場合は、シェーダーの本など、最初にシェーダーについてもう少し学びたいと思うかもしれません。このドキュメントで提示された例が自明であることを願っています。便利だと思う場合は、
Githubまたはhttps://www.buymeacoffee.com/kazikでXemanticのスポンサー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
そして、htmlファイルの<head>に<script>に配置します。
参照の最小デモ(ライブバージョン)を参照してください。
このコードをHTMLの<head>に追加します。
< script src =" https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js " > </ script > 将来的にはshader-web-background NPMに公開します。今のところ、ソースマップとソースと一緒に最新の削除分布をダウンロードすることができます。
このように定義される少なくとも1つのフラグメントシェーダーが必要です。
< 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.shade(config)呼び出しに渡された構成オブジェクトは、 imageという名前の1つのフラグメントシェーダーで構成される最小限のレンダリングパイプラインになります。新しいstatic <canvas id="shader-web-background">ビューポート全体をカバーする要素は、他のページ要素の背後に表示されるz-index: -9999のページに追加されます。
注:デフォルトの<canvas>要素は、DOMツリー全体が構築されている場合にのみ、 <body>に添付されます。また、シェーダーがすぐにコンパイルされていても、ページが完全にロードされるまで、シェーダーフレームの実際のレンダリングは発生しません。
ユニフォームは、GPU以外の世界からの入力をシェーダーに提供します。このメカニズムの説明は、このドキュメントの範囲外です。 WebGLのこの部分で抽象化を構築しないことにしました。なぜなら、それはすでに非常に簡潔であるからです。 webglrenderingContext.Uniformドキュメントを参照してください。
ページが読み込まれてから数秒で測定された時間値をシェーダーに提供したいと仮定します。最初に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 Arrow関数に精通していない場合、それは次のものです。
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の2番目の引数として渡されたテクスチャは、WebGltextureのインスタンスまたはパイプライン内の別のシェーダーのバッファーへの参照のいずれかです。複雑な構成の例セクションとAPI-コンテキスト:バッファを確認します。
画像からテクスチャをロードする方法の詳細については、テクスチャの追加セクションを参照してください。
パイプラインの最後のものを除くすべてのシェーダーには、関連するテクスチャがレンダリングされます。デフォルトでは、これらのテクスチャは、線形補間を備えたRGBA HALF_FLOAT (16bit)フローティングポイントとして初期化され、エッジに固定されています。テクスチャの初期化をカスタマイズできます。詳細については、API -Shader:Texture Documentationを参照してください。
コメント付きの構成オブジェクトの包括的な例を次に示します。バッファーやユニフォームを命名するためにShadertoyコンベンションを使用していますが、命名はarbitrary意的であり、プロジェクトのニーズに合わせて調整される可能性があることに留意してください。
// 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 )
}
}
}
} ) ;注:最初のmousemoveイベントは、シェーダーが開始されてからずっと発生する可能性があるため、最初のマウス座標はonInit関数で提供されます。シェーダー座標は、キャンバスの左下の角から始まり、ピクセルの中央 - (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タブを反映するように設定されています。ほとんどのシェーダーは、少なくともこれら2つのユニフォームを使用します。構成に値を簡単に提供できます。
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 Demos:
そのための自動化されたソリューションはありません。他のShadertoyコードのすぐ上のシェーダーにCommon部分を直接コピーする必要があります。
texture関数をどうするか? Shadertoyでは、テクスチャ関数でtextureアクセスされますが、Webgl 1ではtexture2Dです。以下は、元のコードの前に追加される簡単な回避策です。
#define texture texture2DShadertoyでは、各「チャンネル」バインドテクスチャには、補間やラッピングなどの個別のサンプラーパラメーターがあります。この機能はWebGL 1に簡単に移植することはできませんが、これらの機能を中継するほとんどのシェーダーは、コードベースの回避策で調整できます。たとえば、テクスチャが繰り返されることになっている場合、このようなものは、特定のシェーダーのtexture関数の機能的な置換である可能性があります。
vec4 repeatedTexture( in sampler2D channel, in vec2 uv) {
return texture2D (channel, mod (uv, 1 .));
}API -Shader:Textureも参照してください。
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タイプ情報を使用してソースをチェックし、それらを模倣されたJavaScriptファイルに透過させるGoogle Closureコンパイラをトリガーします。
このプロジェクトは、Google-Java-Formatプラグインを有効にしてIntellij Ideaを使用して開発されました。このスタイルの最も顕著な要素は、レンダリングタブ用の4つではなく2つのスペースです。
どちらか:
<section id="projects-using-shader-web-background">にスクロールしますまたは、説明でリンクを送ってください。