UNPKG

ray-marching

Version:

Embedding ray marching in html files only

21 lines (20 loc) 5.04 kB
var s=class extends HTMLElement{static get observedAttributes(){return["time"]}get time(){let e=this.getAttribute("time");return Number(e)||0}constructor(){super(),this.attachShadow({mode:"open"}),this.isIntersecting=!1,this.shadowRoot&&(this.shadowRoot.innerHTML=this.template());let e=this.shadowRoot?.querySelector("canvas");if(!e)throw new Error("Canvas element not found in shadow root.");this.$canvas=e;let i=this.$canvas.getContext("webgl2")||this.$canvas.getContext("webgl");if(i===null)throw new Error("WebGL not supported.");this.gl=i}attributeChangedCallback(e,i,t){if(e==="time"&&this.isIntersecting){let r=Number(t)||0;this.once(r)}}connectedCallback(){setTimeout(()=>{this.setupShader(),this.resizeObserver=new ResizeObserver(this.handleResize.bind(this)),this.resizeObserver.observe(this),this.intersectionObserver=new IntersectionObserver(this.handleIntersection.bind(this),{root:null}),this.intersectionObserver.observe(this),this.addEventListener("mousemove",this.handleMousemove.bind(this)),this.beginAt=Date.now()},0)}disconnectedCallback(){this.requestID!==void 0&&cancelAnimationFrame(this.requestID),this.resizeObserver&&this.resizeObserver.disconnect(),this.intersectionObserver&&this.intersectionObserver.disconnect(),this.childObserver&&this.childObserver.disconnect()}handleResize(e){let{width:i,height:t}=e[0].contentRect;this.$canvas.width=i/2,this.$canvas.height=t/2,this.gl&&this.uniformLocation&&this.gl.uniform2fv(this.uniformLocation.resolution,[this.$canvas.width,this.$canvas.height])}handleIntersection(e){let i=e[0].isIntersecting;if(this.isIntersecting&&!i&&this.requestID!==void 0&&cancelAnimationFrame(this.requestID),!this.isIntersecting&&i){let t=this.getAttribute("time");t?this.once(Number(t)||0):this.render()}this.isIntersecting=i}handleMousemove(e){!this.gl||!this.uniformLocation||this.gl.uniform2fv(this.uniformLocation.mouse,[Math.max(0,e.offsetX)/this.clientWidth,(this.clientHeight-e.offsetY)/this.clientHeight])}setupShader(){let e=this.querySelector('[type="x-shader/x-fragment"]');if(!e){this.childObserver||(this.childObserver=new MutationObserver(()=>{this.querySelector('[type="x-shader/x-fragment"]')&&(this.childObserver?.disconnect(),this.setupShader())}),this.childObserver.observe(this,{childList:!0}));return}let i=this.createShader(this.gl.VERTEX_SHADER,"attribute vec3 position;void main(){gl_Position=vec4(position,1.);}"),t=this.createShader(this.gl.FRAGMENT_SHADER,e.textContent||"");if(!i||!t)return;let r=this.createProgramObject(i,t);if(r){if(this.program=r,this.gl.useProgram(this.program),this.attribLocation=this.gl.getAttribLocation(this.program,"position"),this.attribLocation===-1){console.error('Attribute "position" not found in shader.');return}this.uniformLocation={resolution:this.gl.getUniformLocation(this.program,"resolution"),mouse:this.gl.getUniformLocation(this.program,"mouse"),time:this.gl.getUniformLocation(this.program,"time")},this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.gl.createBuffer()),this.gl.bufferData(this.gl.ARRAY_BUFFER,new Float32Array([-1,1,0,-1,-1,0,1,1,0,1,-1,0]),this.gl.STATIC_DRAW),this.gl.enableVertexAttribArray(this.attribLocation),this.gl.vertexAttribPointer(this.attribLocation,3,this.gl.FLOAT,!1,0,0)}}template(){return` <style> :host { display: block; width: 100%; height: 100%; } .container { } canvas { width: 100%; height: 100%; } </style> <div class="container"> <slot></slot> <canvas></canvas> </div> `}createShader(e,i){let t=this.gl.createShader(e);return t?(this.gl.shaderSource(t,i),this.gl.compileShader(t),this.gl.getShaderParameter(t,this.gl.COMPILE_STATUS)?t:(console.error("Shader compile error:",this.gl.getShaderInfoLog(t)),this.gl.deleteShader(t),null)):(console.error("Failed to create shader."),null)}createProgramObject(e,i){let t=this.gl.createProgram();return t?(this.gl.attachShader(t,e),this.gl.attachShader(t,i),this.gl.linkProgram(t),this.gl.deleteShader(e),this.gl.deleteShader(i),this.gl.getProgramParameter(t,this.gl.LINK_STATUS)?t:(console.error("Program link error:",this.gl.getProgramInfoLog(t)),this.gl.deleteProgram(t),null)):(console.error("Failed to create program."),null)}once(e){!this.gl||!this.uniformLocation||(this.gl.viewport(0,0,this.$canvas.width,this.$canvas.height),this.gl.clearColor(0,0,0,1),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.uniform1f(this.uniformLocation.time,e),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4))}render(){!this.gl||!this.uniformLocation||this.beginAt===void 0||(this.gl.viewport(0,0,this.$canvas.width,this.$canvas.height),this.gl.clearColor(0,0,0,1),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.uniform1f(this.uniformLocation.time,(Date.now()-this.beginAt)*.001),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4),this.requestID=requestAnimationFrame(this.render.bind(this)))}};window.customElements.define("ray-marching",s);export{s as RayMarching}; //# sourceMappingURL=ray-marching.esm.js.map