0


【圣诞节】飘雪圣诞树

一、前言

马上2023年的圣诞节🎄要到了,作为一个程序员,没什么可以送给大家的,就给大家画一个圣诞树🎄,作为礼物来送给大家吧。

二、创意名

明月当空飘雪圣诞树

三、效果展示

在这里插入图片描述

四、实现步骤

主要是利用three.js和shader来动态实现飘雪粒子。

五、编码实现

CSS:

body {
    margin: 0;
}

JavaScript:

var container;var camera, scene, renderer;var uniforms;init();animate();functioninit(){
    container = document.getElementById('container');

    camera =newTHREE.Camera();
    camera.position.z =1;

    scene =newTHREE.Scene();var geometry =newTHREE.PlaneBufferGeometry(2,2);

    uniforms ={u_time:{type:"f",value:1.0},u_resolution:{type:"v2",value:newTHREE.Vector2()},u_mouse:{type:"v2",value:newTHREE.Vector2()}};var material =newTHREE.ShaderMaterial({uniforms: uniforms,vertexShader: document.getElementById('vertexShader').textContent,fragmentShader: document.getElementById('fragmentShader').textContent
    });var mesh =newTHREE.Mesh(geometry, material);
    scene.add(mesh);

    renderer =newTHREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);

    container.appendChild(renderer.domElement);onWindowResize();
    window.addEventListener('resize', onWindowResize,false);

    document.onmousemove=function(e){
        uniforms.u_mouse.value.x = e.pageX
        uniforms.u_mouse.value.y = e.pageY
    }}functiononWindowResize(event){
    renderer.setSize(window.innerWidth, window.innerHeight);
    uniforms.u_resolution.value.x = renderer.domElement.width;
    uniforms.u_resolution.value.y = renderer.domElement.height;}functionanimate(){requestAnimationFrame(animate);render();}functionrender(){
    uniforms.u_time.value +=0.05;
    renderer.render(scene, camera);}

Html:

<divid="container"></div><scriptid="vertexShader"type="x-shader/x-vertex">voidmain(){
    gl_Position =vec4( position,1.0);}</script><scriptid="fragmentShader"type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec3 camUp =vec3(0.0,1.0,0.0);
vec3 camDir=vec3(0.0,0.0,1.0);
vec3 camPos=vec3(0.0,-0.96,-1.76);

vec3 lightPos=vec3(-2.36,5.75,-7.3);

#define TAO6.283const int MAX_ITER=100;
float PI=3.14159265;//--------------------------------------------------
#define time u_time

vec3 getNormal(in vec3 p);//Освещение//-------------------------------------------------Ламберт
vec3 getlightingLambert(in vec3 pos,in vec3 normal,in vec3 lightDir,in vec3 color){//  const vec3 diffColor = vec3 ( 0.5, 0.0, 0.0 );

    vec3 n2   =normalize( normal);
    vec3 l2   =normalize( lightDir-pos );
    vec3 diff = color *max(dot( n2, l2 ),0.0);return diff;}//-------------------------------------------------по Фонгу
vec3 getlightingPhong(in vec3 pos,in vec3 normal,in vec3 lightDir,in vec3 color){
   vec3 specColor =vec3(1.0,0.97,0.94);
   float  specPower =36.0;
       
    vec3   l =normalize(lightDir-pos);   
    vec3   v =normalize(pos-pos);

    vec3   n =normalize(normal);        
    vec3   r =reflect(-l, n ); 
    vec3 diff = color *max(dot( n, l ),0.0);
    vec3 spec = specColor *pow(max(dot( l, r ),0.0), specPower );return diff + spec;}//------------------------------------------
vec2 rot(vec2 p,float r){
  vec2 ret;
  ret.x=p.x*cos(r)-p.y*sin(r);
  ret.y=p.x*sin(r)+p.y*cos(r);return ret;}//------------------------------------------
vec2 rotsim(vec2 p,float s){
  vec2 ret=p;
  ret=rot(p,-PI/(s*2.0));
  ret=rot(p,floor(atan(ret.x,ret.y)/PI*s)*(PI/s));return ret;}//------------------------------------------
vec3 sim(vec3 p,float s){
   vec3 ret=p;
   ret=p+s/2.0;
   ret=fract(ret/s)*s-s/2.0;return ret;}//------------------------------------------------//Примитивы//--------------------------------------------------
float trunkCone(vec3 p, float c){
 float q =length(p.xz);return q + p.y * c;}//----------------------------------------------------
vec3 background(vec3 rd){

   float sky =max(0.0,-dot(rd,vec3(0.0,1.0,0.0)));
   float ground =max(0.0,-dot(rd,vec3(0.0,6.7,2.0)));
   vec3 bFon =pow(ground,0.5)*vec3(0.4,0.3,0.2)+pow(sky,1.)*vec3(0.4,0.3,0.2);return bFon ;}//-------------------------------------------------- 
vec3 getmaterial(in vec3 p,in float mat){
 
 vec3 pos = p; 
 vec3 color =vec3(1.);
  

 vec3 colorObject =vec3(0.5,0.4,0.3);
 vec3 colorObject1;if(mat ==0.)returnvec3(0.4662,0.4565,0.4488);elseif(mat ==1.)returnvec3(1.0,1.0,1.0);elseif(mat ==2.){

     float r =pow(colorObject.r,cos(u_time *0.5)); 
     float g =pow(colorObject.g,cos(u_time *0.3));
     float b =pow(colorObject.b,cos(u_time *0.7));  
     colorObject1 =vec3(r, g, b);return colorObject1;}elseif(mat ==3.)// стволreturnvec3(0.7218,0.4581,0.0983);elseif(mat ==4.)// иглыreturnvec3(0.5,0.6,0.2);elsereturnvec3(0.3,0.9,0.5);}//------------------------------------------------//Объекты//----------------------------------------------------
vec2 rotate1(vec2 v, float angle){returncos(angle)*v+sin(angle)*vec2(v.y,-v.x);}

vec2 kaleido(vec2 v, float power){returnrotate1(v,floor(.5+atan(v.x,-v.y)*power/TAO)*TAO/power);}

vec2 kaleido6(vec2 v){returnrotate1(v,floor(0.5+atan(v.x,-v.y)*0.95493)*1.0472);}

vec2 kaleido12(vec2 v){returnrotate1(v,floor(0.5+atan(v.x,-v.y)*1.90986)*0.5236);}

mat2 r45=mat2(0.7071,0.7071,-0.7071,0.7071);
mat2 r30=mat2(0.866,0.5,-0.5,0.866);
mat2 rtrn=mat2(0.9689,-0.2474,0.2474,0.9689);//----------------------------------------------------Ветки ёлки
float branch(in vec3 pos, inout float trunk){
 float d =1.0;for(int i=0;i<2;i++){
      vec3 z=pos;

      float c=floor(z.y*4.); 
      z.yz=rotate1(z.yz,-z.z*0.79*(1.0+c*0.1)); 
      float bm =-z.y -2.0;
      z.y=mod(z.y,0.25)-0.05;if(i==1)                    
        z.xz=z.xz*rtrn;
      z.xz=kaleido(z.xz,2.0-c); 
      z.yz=rtrn*z.yz;
      bm=max(bm,-z.z+c*0.086);
      trunk=min(trunk,max(max(abs(z.x),abs(z.y)),bm))-0.001-z.z*0.003;
      float c2=floor(z.z *16.0); 
      z.z=mod(z.z,0.0625)-0.049; 
      z.xy=rotate1(z.xy,c2*0.25);  
      z.xy=kaleido12(z.xy);
      z.yz=z.yz*r30;   
      d=min(d,max(max(max(abs(z.x),abs(z.z)),-z.y-0.05+c*0.005),bm));}return d;}//----------------------------------------------------
vec2 tree(in vec3 pos){
   float d=1.;
   float material =0.;
   float trunk =trunkCone( pos,0.025);// Ствол
   d =branch(pos, trunk );// Веткиif(trunk<d){
      d=trunk;
      material =3.;}else{
      material =4.;}
   float result =max(0.0,max(d,max(pos.y,-pos.y-2.0)));returnvec2(result, material);}//----------------------------------------------------//Star
vec2 star(vec3 p){
  p.y=p.y -0.07;
  p= p *10.0;
  float l=length(p);if(l  <2.0){
  p.xy=rotsim(p.xy,5.0);
  p.y=p.y-2.0; 
  p.z=abs(p.z);
  p.x=abs(p.x);returnvec2(dot(p,normalize(vec3(2.0,1,3.0)))/10.0,2.);}elsereturnvec2((l-1.9)/4.0,2.0);}//----------------------------------------------------//Snow
float makeshowflake(vec3 p){returnlength(p)-0.02;}//----------------------------------------------------
float makeShow(vec3 p,float tx,float ty,float tz){
  p.y=p.y+time*tx;
  p.x=p.x+time*ty;
  p.z=p.z+time*tz;
  p=sim(p,8.0);returnmakeshowflake(p);}//----------------------------------------------------
vec2 show(vec3 p){
  float f=makeShow(p,1.11,1.03,1.38);
  f=min(f,makeShow(p,1.72,0.74,1.06));
  f=min(f,makeShow(p,1.93,0.75,1.35));returnvec2(f,1.0);}//----------------------------------------------------
vec4 swag(vec2 pos){
 
  vec3 camSide =cross(camDir, camUp);
  mat4 cm=mat4(
    camUp.x,   camUp.y,   camUp.z,-dot(camUp,camPos),
    camSide.x,   camSide.y,   camSide.z,-dot(camSide,camPos),
    camDir.x, camDir.y, camDir.z,-dot(camDir,camPos),0.0,0.0,0.0,1.0);

  vec4 pc=vec4(0,0,0,0);const float maxl=64.0;for(float i=0.0;i<maxl;i++){

   vec4 pt=vec4(sin(i*PI*2.0*7.0/maxl)*0.75*(1.0-i/maxl),/* Ширина основания по X  */
    i/maxl *2.1,/*Высота конуса */cos(i*PI*2.0*7.0/maxl)*0.75*(1.0-i/maxl),/* Ширина основания по Z */1.0);
    
  pt=pt*cm;
  vec2 vPos = pos;
 vPos.y +=1.28;

  vec2 xy=(pt/(-pt.z )).yx + vPos;

  float c;
  c=0.2/length(xy); 

 pc+=vec4((sin(i*5.0+time*10.0)*0.5+0.5)* c,(cos(i*3.0+time*8.0)*0.5+0.5)* c,(sin(i*6.0+time*9.0)*0.5+0.5)* c ,0.0);}
  pc=pc/maxl; 

  pc=smoothstep(0.0,1.0,pc);return pc;}//----------------------------------------------------// вывод объекта
vec2 renderFunction(in vec3 pos){
  vec2 result;
  vec3 pos1 = pos;//   pos1 = rotationCoord(pos, 3.);
  vec2 treeMy =tree(pos1);
  vec2 starMy =star(pos1);
  vec2 showMy =show(pos1);if(treeMy.x < starMy.x)
      result = treeMy;else
      result = starMy;if(result.x > showMy.x)
      result = showMy;return result;}//-------------------------------------------------
vec3 getNormal(in vec3 p){const float e =0.0001;returnnormalize(vec3(renderFunction(p+vec3(e,0.0,0.0)).x -renderFunction(p+vec3(-e,0.0,0.0)).x,renderFunction(p+vec3(0.0,e,0.0)).x -renderFunction(p+vec3(0.0,-e,0.0)).x,renderFunction(p+vec3(0.0,0.0,e)).x -renderFunction(p+vec3(0.0,0.0,-e)).x
      ));}//-------------------------------------------------
float rndStart(vec2 co){return0.1+0.9*fract(sin(dot(co,vec2(123.42,117.853)))*412.453);}//-------------------------------------------------
vec4 render(in vec3 posOnRay,in vec3 camPos,in vec3 rayDir, out vec2 object){ 
  vec4 color =vec4(0.0);
  float t =0.0;
  vec3 normal;
  vec3 lightDir = lightPos;
  vec4 colorMirror =vec4(0.);//--------------Цвет фона
  vec3 bcol =background(rayDir);for(int i=0; i<MAX_ITER;++i){

    object =renderFunction(posOnRay);// Объект и его цвет//------------------    if(abs(object.x)<0.004){
    normal =normalize(getNormal(posOnRay));//----------------- 
    vec3 materialColor =getmaterial(posOnRay.xyz, object.y);if(object.y ==2.0)
       color.rgb =getlightingPhong(posOnRay, normal, lightDir, materialColor);// По Фонгуelse 
       color.rgb =getlightingLambert(posOnRay, normal, lightDir, materialColor);return color;}//------------------
    t = object.x;
   posOnRay = posOnRay + t*rayDir;}

  
  color.rgb+=bcol*(1.0-clamp(color.w,0.0,1.0));returnvec4(color.rgb,1.0);}//-------------------------------------------------voidmain(){
  vec2 pos =(2.0* gl_FragCoord.xy - u_resolution.xy )/ u_resolution.y;

  vec3 camSide =cross(camDir, camUp);
  vec3 rayDir =normalize(camSide*pos.x + camUp*pos.y + camDir);

  float t =0.0, s =0.1;
  vec2 object =vec2(1.,1.);//------------------------------
  vec3 posOnRay = camPos;//------------------------------ 
  vec4 color =vec4(0.);

  color=render(posOnRay, camPos, rayDir, object);//------------------------------
   vec3 light_color =vec3(0.9,0.5,0.1);
   float c =0.075/(length(pos -vec2(0.48,0.66)));//луна
   vec4 moon =smoothstep(0.95,1.05,c)*vec4(1.0)+vec4(vec3(c)* light_color,1.0);//-----------------------------
vec4 swagMy =swag(pos);// гирлянда//-----------------------------

     gl_FragColor =color + moon + swagMy;}</script>
标签: javascript 前端 html

本文转载自: https://blog.csdn.net/weixin_44427181/article/details/128407336
版权归原作者 编程初体验 所有, 如有侵权,请联系我们删除。

“【圣诞节】飘雪圣诞树”的评论:

还没有评论