canvas+webgl实现三维机器之心旋转动画效果代码

代码语言:html

所属分类:三维

代码描述:canvas+webgl实现三维机器之心旋转动画效果代码

代码标签: canvas webgl 三维 机器 之心 旋转 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
 
<meta charset="UTF-8">
 
 
 
 
<style>
::-webkit-scrollbar {
       
width: 0.625rem;
       
height: 0.625rem;
}

::-webkit-scrollbar-thumb {
       
background: #111;
       
border-radius: 0.3125rem;
       
box-shadow: inset 0.125rem 0.125rem 0.125rem rgba(255, 255, 255, 0.25),
                inset
-0.125rem -0.125rem 0.125rem rgba(0, 0, 0, 0.25);
       
cursor: default;
}

::-webkit-scrollbar-track {
       
background: #333;
}

::selection {
       
background: #fff;
       
color: #333;
}

html
,
body
{
       
height: 100vh;
       
height: 100dvh;
       
margin: 0;
       
overflow: hidden;
}

body
{
       
display: grid;
       
grid-template-rows: calc(100dvh - 4rem) 4rem;
       
font-family: system-ui, sans-serif;
}

canvas
,
.editor,
#controls {
       
grid-row: 1;
       
grid-column: 1;
}

canvas
{
       
width: 100%;
       
height: auto;
       
object-fit: contain;
       
background: black;
       
touch-action: none;
}

.editor,
.overlay,
#error {
       
background: repeating-linear-gradient(0deg, #000a, #1119, #000a 0.25rem);
       
padding: 1em;
}

.editor {
       
color: #fefefe;
       
tab-size: 2;
       
border: none;
       
resize: none;
}

.editor:focus {
       
outline: none;
}

#error {
       
grid-row: 2;
       
grid-column: 1;
       
margin: 0;
       
padding-block: 0;
       
padding-top: 0.5em;
       
color: firebrick;
       
overflow: auto;
       
text-wrap: pretty;
}

#indicator {
       
visibility: hidden;
       
position: absolute;
       
top: calc(var(--top, 0px) - var(--scroll-top, 0px));
       
width: 0;
       
height: 0;
       
border-top: 10px solid transparent;
       
border-bottom: 10px solid transparent;
       
border-left: 10px solid firebrick;
       
transform: translateY(-25%);
}

.overlay {
       
position: absolute;
       
top: 0;
       
left: 0;
       
right: 0;
       
margin: 0;
}

.editor,
.overlay {
       
font-size: 1rem;
       
line-height: 1.2;
       
white-space: pre;
}

#controls {
       
position: fixed;
       
top: 1em;
       
right: 2em;
}

.controls {
       
position: relative;
       
display: flex;
       
gap: 1.5em;
       
padding: 0.5em 1.25em;
       
background: #1111;
       
border-radius: 4px;
}

.controls::before,
.controls::after {
       
content: "";
       
position: absolute;
       
z-index: -1;
       
inset: 0;
       
transform: scale(0.95);
       
border-radius: inherit;
       
opacity: 0;
}

.controls::before {
       
background: #aef;
       
animation: pulse 2s infinite;
}

.controls::after {
       
background: #fefefe66;
       
transition: transform 200ms ease-in-out;
}

.controls:hover::before,
.controls:hover::after {
       
opacity: 1;
}

.controls:hover::before {
       
transform: scale(0.98);
       
filter: blur(2px);
}

.controls:hover::after {
       
transform: scale(1.025, 1.1);
}

.controls:hover {
       
background: #111f;
}

@keyframes pulse {
       
0% {
               
transform: scale(1);
       
}

       
50% {
               
transform: scale(1.0125);
       
}

       
100% {
               
transform: scale(1);
       
}
}

.hidden {
       
display: none !important;
}

.opaque {
       
opacity: 1 !important;
       
background: #111 !important;
}

input
{
       
all: unset;
       
opacity: 0.2;
       
filter: saturate(0) invert(1);
       
cursor: pointer;
       
transition: opacity 200ms ease-in-out;
       
padding: 0.25em 0.5em;
}

input:hover {
       
opacity: 1;
}

.icon {
       
text-align: center;
       
line-height: 1;
}

#btnToggleView {
       
width: 1.25em;
}

#btnToggleView::after {
       
content: "👁";
}

#btnToggleView:checked::after {
       
content: "✏️";
}

#btnToggleResolution::after {
       
content: "1️⃣";
}

#btnToggleResolution:checked::after {
       
content: "2️⃣";
}

#btnReset::after {
       
content: "⏮️";
}
</style>


 
</head>

<body translate="no">
 
<canvas id="canvas"></canvas>
<textarea id="codeEditor" class="editor" spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" oninput="render()"></textarea>
<pre id="error"></pre>
<div id="indicator"></div>
<div id="controls">
       
<div class="controls">
               
<input id="btnToggleView" class="icon" type="checkbox" name="toggleView" onclick="toggleView()">
               
<input id="btnToggleResolution" class="icon" type="checkbox" name="toggleResolution" onchange="toggleResolution()">
               
<input id="btnReset" class="icon" type="checkbox" name="reset" onclick="reset()">
       
</div>
</div>
<script type="x-shader/x-fragment">#version 300 es
/*********
* made by Matthias Hurrle (@atzedent)
*/

precision highp
float;
out vec4 O
;
uniform
float time;
uniform vec2 resolution
;
uniform vec2 move
;
uniform
int pointerCount;
#define P pointerCount
#define FC gl_FragCoord.xy
#define R resolution
#define T time
#define N normalize
#define S smoothstep
#define rot(a) mat2(cos(a-vec4(0,11,33,0)))

float smin(float a, float b, float k) {
       
float h = clamp(.5+.5*(b-a)/k,.0,1.);
       
return mix(b,a,h)-k*h*(1.-h);
}

vec3 smthng
(vec3 a, vec3 b, float k) {
        vec3 h
=clamp(.5+.5*(b/a),.0,1.);
       
return mix(b,a,h)-k*h*(1.-h);
}

vec3 kifs
(vec3 p) {
       
for (int i=0; i<2; i++) {
                p
.yz*=rot(T);
                p
.xz*=rot(T);
                p
=smthng(p,-p,-1.);
                p
-=vec3(.26,.02,.1);
       
}
       
return p;
}

float box(vec3 p, vec3 s, float r) {
        p
=abs(p)-(s-r);

       
return length(max(p,.0))+min(.0,max(max(p.x,p.y),p.z))-r;
}

float mspo(vec3 p, vec3 s, float r, float l) {
       
const float k=.25;

       
float
        d
=box(p,s,r),
        res
=d,
        f
=1.,
        i
=.0;

       
for(; i++<l;) {
                vec3
                a
=mod(p*f,2.)-1.,
                r
=abs(1.-3.*abs(a));

                f
*=3.;

               
float
                da
=max(r.x,r.y),
                db
=max(r.y,r.z),
                dc
=max(r.z,r.x),
                c
=(smin(da,smin(db,dc,k),k)-.75)/f;

               
if(c>d) d=c, res = c;
       
}

       
return res;
}

float glow=.0;
float map(vec3 p) {    
        vec3 st
=p;
        st
=kifs(st);
       
float t=T*2., k=.025,
        sp
=length(st-vec3(.5*sin(t), .125*cos(t), -.5*(sin(T)*.125+.8)))-k;
        sp
=min(sp,length(st-vec3(pow(.15*-cos(t*.7),2.), .125*-sin(t), 0))-k);
        sp
=min(sp,length(st-vec3(pow(.125*cos(t*1.1),2.), .125*sin(t), .5*(cos(T)*.125+.8)))-k);
        glow
+=.05/(.05+sp*sp*80.);
       
return min(mspo(p, vec3(1),.005,3.), sp);
}

float calcAO(in vec3 pos, in vec3 nor) {
       
float occ=.0, sca=1.;
       
for(float i=.0; i++<5.;) {
               
float
                h
=.01+.12*float(i)/4.,
                d
=map(pos+h*nor);
                occ
+=(h-d)*sca;
                sca
*=.95;
               
if(occ>.35) break;
       
}
       
return clamp(1.-3.*occ,.0,1.)*(.5+.5*nor.y);
}

vec3 norm
(vec3 p) {
       
float h=1e-3; vec2 k=vec2(-1,1);
       
return N(
                k
.xyy*map(p+k.xyy*h)+
                k
.yxy*map(p+k.yxy*h)+
                k
.yyx*map(p+k.yyx*h)+
                k
.xxx*map(p+k.xxx*h)
       
);
}

void cam(inout vec3 p) {
        p
.yz*=rot(move.y*6.3/min(R.x,R.y)+(P>0?.0:sin(T*.5)*.5+.5));
        p
.xz*=rot(-move.x*6.3/min(R.x,R.y)+(P>0?.0:T*.7));
}

void main() {
        vec2 uv
=(FC-.5*R)/min(R.x,R.y);
        vec3 col
=vec3(0),
        p
=vec3(0,0,-(-S(-1.,-2.,log(2.*pow(sin(T*.2),2.))))-4.),
        ro
=p,
        rd
=N(vec3(uv,1));
        cam
(p); cam(rd);
       
       
float dd=.0;
       
for (float i=.0; i++<400.;) {
               
float d=map(p);
               
if (d<1e-3 || d>12.) break;
                p
+=rd*d;
                dd
+=d;
       
}
       
        vec3 n
=norm(p),
        lp
=vec3(0,1,-3);
        cam
(lp);
        vec3
        l
=N(lp-p);

       
float
        falloff
=.1+10./dot(lp-p,lp-p),
        diffuse
=clamp(dot(l,n),.0,1.),
        occlusion
=calcAO(p,n);
       
        col
+=diffuse*occlusion*falloff;

        vec3 ambient
=vec3(1,.95,.8);
        col
+=.1*ambient;
               
       
if (dd>12.) col=mix(vec3(0),vec3(.35,.5,.65),S(.7,.0,length(uv)));
       
        col
+=vec3(.95,.4,.8)*glow*glow;
       
        O
=vec4(col,1);
}</script>
 
     
<script >
/*********
 * made by Matthias Hurrle (@atzedent)
 */
let editMode = false; // set to false to hide the code editor on load
let resolution = 0.5; // set 1 for full resolution or to .5 to start with half resolution on load
let renderDelay = 1000; // delay in ms before rendering the shader after a change
let dpr = Math.max(1, resolution * window.devicePixelRatio);
let frm, source, editor, store, renderer, pointers;
const shaderId = "It Is All Just a Reflection";
window.onload = init;

function resize() {
        const { innerWidth: width, innerHeight: height } = window;

        canvas.width = width * dpr;
        canvas.height = height * dpr;

        if (renderer) {
                renderer.updateScale(dpr);
        }
}
function toggleView() {
        editor.hidden = btnToggleView.checked;
}
function reset() {
        let shader = sour.........完整代码请登录后点击上方下载按钮下载查看

网友评论0