显示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">或给我发送带有描述的链接。