웹 사이트 배경으로 GLSL 조각 셰이더를 표시합니다. Shadertoy Shaders, Multipass-Ping-Pong Offscreen 버퍼, 피드백 루프, 부동 소수점 텍스처를 지원합니다. WebGL 1 또는 2를 사용하면 기술적으로 가능한 곳에서 실행하려고합니다.
웹 사이트/데모 : ? https://xemantic.github.io/shader-web-background?
❔ ??? 질문을하려면 Xemantic Discord Server로 이동하십시오. ???
웹 디자인 및 개발 프로세스의 일부로 복잡한 조각 셰이더를 사용하도록이 라이브러리를 설계했습니다. 이 도구는 마지막으로 웹 브라우저를 창의적인 코딩 환경으로 수용 할 수 있습니다. GLSL에 익숙하다면 웹에 작업을 게시하는 데 도움이 될 수 있습니다. 웹 개발 배경에서 오는 경우 예를 들어 셰이더의 책에서 먼저 셰이더에 대해 조금 더 배우고 싶을 수도 있습니다. 이 문서에 제시된 예가 자명하기를 바랍니다. 그렇다면 유용하다면
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
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에 게시 할 것입니다. 지금은 소스 맵 및 소스와 함께 최신 최신 분포를 다운로드 할 수 있습니다.
다음과 같이 정의 된 하나 이상의 조각 셰이더가 필요합니다.
< 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 라는 하나의 조각 셰이더로 구성된 최소한의 렌더링 파이프 라인을 초래합니다. 새로운 정적 <canvas id="shader-web-background"> 전체 뷰포트를 다루는 요소가 z-index: -9999 사용하여 페이지에 추가되어 다른 페이지 요소 뒤에 표시됩니다.
참고 : 기본 <canvas> 요소는 전체 DOM 트리가 구성된 경우에만 Document <body> 에 첨부됩니다. 또한 셰이더가 즉시 컴파일 되더라도 페이지가 완전히로드 될 때까지 셰이더 프레임의 실제 렌더링은 발생하지 않습니다.
유니폼은 셰이더에게 GPU 외부의 세계의 입력을 제공합니다. 이 메커니즘을 설명하는 것은이 문서의 범위를 벗어나지 않습니다. 나는 이미 간결하기 때문에 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 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 -Shader : Texture Documentation을 참조하십시오.
다음은 주석이있는 구성 객체의 포괄적 인 예입니다. 이름 지정 버퍼 및 유니폼에 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 )
}
}
}
} ) ; 참고 : 초기 마우스 좌표는 셰이더가 시작된 후 오랫동안 첫 번째 mousemove 이벤트가 발생할 수 있기 때문에 onInit 기능에 제공됩니다. 셰이더 좌표는 캔버스의 왼쪽 하단 모서리에서 시작되며 픽셀의 중간 (0.5, 0.5) 과 정렬됩니다.
API 참조 :
시민:
python -m http.server 8000 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 데모 :
이를위한 자동화 된 솔루션이 없습니다. 다른 Shadertoy 코드 바로 위의 Common 부분을 셰이더에 직접 복사해야합니다.
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 버퍼 이름에 따라 셰이더를 지정할 수 있습니다.
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 Vertex와 Fragment Shaders 사이에 공유하도록 지정할 수 있습니다 (기본적으로 추가되지 않음).
git clone https://github.com/xemantic/shader-web-background.git
cd shader-web-background
./gradlew compileJs유형 정보를 사용하여 소스를 확인하고 미니스트 자바 스크립트 파일로 전환하는 Google Closure 컴파일러를 트리거합니다.
이 프로젝트는 Google-Java-Format 플러그인이 활성화 된 Intellij Idea를 사용하여 개발되었습니다. 이 스타일의 가장 눈에 띄는 요소는 렌더링 탭을위한 4 대신 2 개의 공간입니다.
어느 하나:
<section id="projects-using-shader-web-background"> 로 스크롤하십시오또는 설명과 함께 링크를 보내주세요.