يعرض تظليل شظايا GLSL كخلفية موقع على شبكة الإنترنت. يدعم Shadertoy Tames ، Multipass-Ping-Pong خارج الشاشة ، وحلقات التغذية المرتدة ، والقوام الفاصلة. إما مع WebGL 1 أو 2 ، سيحاول الركض أينما كان ذلك ممكنًا تقنيًا.
موقع/تجريبي : ؟ https://xemantic.github.io/shader-web-background؟
❔ ؟؟؟ لطرح الأسئلة ، انتقل إلى خادم Discord Xemantic ☕ ؟؟؟
لقد صممت هذه المكتبة لاستخدام تظليل الأجزاء المعقدة كجزء من عملية تصميم الويب الخاصة بي وتطويرها. هذه هي الأداة التي تتيح لي أخيرًا تبني متصفح الويب كبيئة ترميز إبداعية. إذا كنت على دراية بـ GLSL ، فقد يساعدك ذلك في نشر عملك على الويب أيضًا. إذا كنت تأتي من خلفية تطوير الويب ، فقد ترغب في تعلم المزيد عن التظليل أولاً ، على سبيل المثال من كتاب التظليل. آمل أن تكون الأمثلة المقدمة في هذه الوثائق محسوسة ذاتية. إذا وجدت أنها مفيدة ، إذن
❤ راعي Xemantic على github أو https://www.buymeacoffee.com/kazik
كازيك (موريسيل) بوغودا
https://xemants.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> في <head> من ملف HTML الخاص بك.
انظر الحد الأدنى من العرض التجريبي للرجوع إليه (الإصدار المباشر).
أضف هذا الرمز إلى <head> من HTML الخاص بك:
< 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 > ضعه في <head> من HTML الخاص بك. يجب أن يكون 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 > يتم تطبيق فئة CSS shader-web-background-fallback على جذر مستند HTML و Canvas.
shader-web-background-fallback ، ومع ذلك ، فقد لا تعمل على بعض المتصفحات. قد تكون هناك حاجة إلى معالج الخطأ المخصص للتوافق المتبادل.
انظر قسم أخطاء التعامل للحصول على التفاصيل.
شاهد واجهة برمجة تطبيقات التظليل الكامل
سيؤدي كائن التكوين الذي تم تمريره إلى استدعاء ShaderWebBackground.shade (التكوين) في المثال أعلاه إلى الحد الأدنى من خط أنابيب التقديم الذي يتكون من ظلال شظية واحدة مسماة image . سيتم إضافة عنصر جديد <canvas id="shader-web-background"> الذي يغطي منفذ العرض بأكمله إلى الصفحة مع z-index: -9999 ، ليتم عرضه خلف عناصر الصفحات الأخرى.
ملاحظة: سيتم إرفاق العنصر الافتراضي <canvas> بمستند <body> فقط عند إنشاء شجرة DOM بأكملها. كما أن العرض الفعلي لإطارات التظليل لن يحدث حتى يتم تحميل الصفحة بالكامل ، على الرغم من تجميع التظليل على الفور.
يوفر الزي الرسمي تظليلات مدخلات من العالم خارج وحدة معالجة الرسومات. وصف هذه الآلية خارج نطاق هذه الوثائق. قررت عدم بناء التجريد على هذا الجزء من WebGL ، لأنه موجز بالفعل. انظر WebGlrenderingContext.uniform Documentation.
دعنا نفترض أنك تريد تزويد التظليل بقيمة زمنية تقاس في ثوانٍ منذ اللحظة التي تم فيها تحميل الصفحة. أولاً ، حدد الزي الموحد في تظليل 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 القياسية سيؤدي تقسيمه على 1000 إلى قياس قيمة الفاصلة العائمة في ثوان.
ملخص: يمكنك استخدام هذه الآلية لتكييف أي واجهة برمجة تطبيقات كمدخل لتظليلاتك. تحقق من عروض المشروع لأمثلة كيفية دمج الإدخال مثل:
يستخدم إعلان "الملمس" الموحد نوع 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 (16bit) نقطة عائمة مع الاستيفاء الخطي ويتم تثبيتها على الحافة. يمكن تخصيص تهيئة الملمس. انظر API - Shader: وثائق الملمس للحصول على التفاصيل.
فيما يلي مثال شامل لكائن التكوين مع التعليقات. إنه يستخدم اتفاقيات 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 للحصول على التفاصيل. هناك العديد من التظليلات المحددة في المثال أعلاه. ستتم معالجتها بتسلسل يسمى Multipass في Shadertoy Nomenclature. سيتم عرض آخر التظليلات المحددة على الشاشة. يمكن تمرير إخراج التظليلات السابقة ، بما في ذلك حلقة التغذية المرتدة للإطار السابق المقدم من نفس التظليل ، إلى الزي الرسمي.
يتم تنفيذ العديد من عمليات التحقق من التكوين الموردين لتجنب المشكلات الشائعة التي يصعب تصحيحها عادة على خلاف ذلك. يحتوي SRC/Test/HTML/Orrors/Folder على جميع حالات اختبار الخطأ التي يمكن فحصها أيضًا في العرض التجريبي المباشر لمعالجة الأخطاء.
جميع الأخطاء والتحذيرات ستكون مرئية على وحدة التحكم.
يرى:
// 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 من Run 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 > تم تعيين سمة id لـ <script> لتعكس علامة التبويب Shadertoy تسمى Image . ستستخدم معظم التظليلات على الأقل هذين الزي الموحدين ، ومن السهل توفير قيمها في التكوين:
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 ) ,
}
}
}
} ) ;Demos Shadertoy:
لا يوجد حل آلي لذلك. سيتعين عليك نسخ الجزء Common مباشرة إلى تظليلاتك ، فوق رمز Shadertoy الآخر.
texture ؟ في Shadertoy يتم الوصول إلى قوام من خلال وظيفة texture بينما في WebGL 1 هو texture2D . فيما يلي حل بسيط لإضافته قبل الكود الأصلي:
#define texture texture2D في Shadertoy ، يمكن أن يكون لكل "قناة" ربط الملمس معلمات عينات منفصلة مثل الاستيفاء أو التفاف. لا يمكن نقل هذه الوظيفة بسهولة إلى WebGL 1 ، ولكن يمكن تعديل معظم التظليلات التي تنقل هذه الميزات باستخدام حلول تعتمد على الكود. على سبيل المثال ، إذا كان من المفترض تكرار النسيج ، فقد يكون هناك شيء من هذا القبيل بديلاً وظيفيًا لوظيفة texture في تظليل معين:
vec4 repeatedTexture( in sampler2D channel, in vec2 uv) {
return texture2D (channel, mod (uv, 1 .));
}انظر أيضا API - تظليل: الملمس.
يمكنك تسمية تظليلاتك وفقًا لأسماء Shadertoy Buffer:
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 > من الممكن تغيير تظليل Vertex الافتراضي لكل ظلال شظية من خلال توفير البرنامج النصي التالي في <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 . يجب تسمية سمة Vertex V .
ملاحظة: يمكن تحديد varying vec2 uv لتشاركه بين قمة الرأس وتظليل الأجزاء (لم يتم إضافته بشكل افتراضي).
git clone https://github.com/xemantic/shader-web-background.git
cd shader-web-background
./gradlew compileJsسيؤدي إلى قيام برنامج التحويل البرمجي بإغلاق Google والذي سيتحقق من المصادر باستخدام معلومات النوع ونقلها إلى ملفات JavaScript المصغرة:
تم تطوير هذا المشروع باستخدام Intellij Idea مع تمكين Google-Java-Format Plugin. العنصر الأكثر وضوحا في هذا النمط هو مساحتين بدلاً من 4 لتقديم علامات تبويب.
أيضاً:
<section id="projects-using-shader-web-background">أو أرسل لي رابطًا مع الوصف.