【圣诞节】飘雪圣诞树

news2024/11/21 0:15:20

一、前言

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

二、创意名

明月当空飘雪圣诞树

三、效果展示

在这里插入图片描述

四、实现步骤

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

五、编码实现

CSS:

body {
    margin: 0;
}

JavaScript:

var container;
var camera, scene, renderer;
var uniforms;

init();
animate();

function init() {
    container = document.getElementById('container');

    camera = new THREE.Camera();
    camera.position.z = 1;

    scene = new THREE.Scene();

    var geometry = new THREE.PlaneBufferGeometry(2, 2);

    uniforms = {
        u_time: {
            type: "f",
            value: 1.0
        },
        u_resolution: {
            type: "v2",
            value: new THREE.Vector2()
        },
        u_mouse: {
            type: "v2",
            value: new THREE.Vector2()
        }
    };

    var material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent
    });

    var mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    renderer = new THREE.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
    }
}

function onWindowResize(event) {
    renderer.setSize(window.innerWidth, window.innerHeight);
    uniforms.u_resolution.value.x = renderer.domElement.width;
    uniforms.u_resolution.value.y = renderer.domElement.height;
}

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    uniforms.u_time.value += 0.05;
    renderer.render(scene, camera);
}

Html:

<div id="container"></div>

<script id="vertexShader" type="x-shader/x-vertex">
void main() {
    gl_Position = vec4( position, 1.0 );
}
</script>
<script id="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 TAO 6.283
const 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.)
      return vec3(0.4662, 0.4565, 0.4488);
   else if (mat == 1.)
      return vec3(1.0, 1.0, 1.0);   
   else if (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;         
   }
    else if (mat == 3.) // ствол
      return vec3(0.7218, 0.4581, 0.0983);  
   else if (mat == 4.) // иглы
      return vec3(0.5, 0.6, 0.2);     
   
   else   
      return vec3(0.3, 0.9,0.5);
}

//------------------------------------------------
//Объекты
//----------------------------------------------------
vec2 rotate1(vec2 v, float angle) 
{return cos(angle)*v+sin(angle)*vec2(v.y,-v.x);}

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

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

vec2 kaleido12(vec2 v)
{return rotate1(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)));
   return vec2(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);
  return vec2(dot(p,normalize(vec3(2.0,1,3.0))) / 10.0, 2.);
  } else return vec2((l-1.9)/4.0, 2.0);
}
//----------------------------------------------------
//Snow
float makeshowflake(vec3 p)
{
  return length(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);
  return makeshowflake(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));

  return vec2(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;
  return
    normalize
    (
      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)
{return 0.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));
  return vec4(color.rgb, 1.0);
}
//-------------------------------------------------

void main()
{
  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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详细设计说明书(GB8567——88)基于协同的在线表格forture-sheet

详细设计说明书 1引言 1.1编写目的 该文档在概要设计的基础上&#xff0c;进一步的细化系统结构&#xff0c;展示了软件结构的图标&#xff0c;物理设计、数据结构设计、及算法设计、详细的介绍了系统各个模块是如何实现的&#xff0c;包括涉及到的算法&#xff0c;逻辑流程…

【LeetCode每日一题:1754. 构造字典序最大的合并字符串~~~双指针+贪心算法】

题目描述 给你两个字符串 word1 和 word2 。你需要按下述方式构造一个新字符串 merge &#xff1a;如果 word1 或 word2 非空&#xff0c;选择 下面选项之一 继续操作&#xff1a; 如果 word1 非空&#xff0c;将 word1 中的第一个字符附加到 merge 的末尾&#xff0c;并将其…

《Unified Structure Generation for Universal Information Extraction》论文阅读

文章目录文章介绍文章方案用于统一结构编码的结构化抽取语言&#xff08;SEL&#xff09;用于可控IE结构生成的结构模式指导使用UIE生成预训练任务微调任务总结参考文章地址&#xff1a; https://arxiv.org/abs/2203.12277文章介绍 目前对于自然语言处理中的信息抽取任务如关系…

业聚医疗港交所上市:市值76亿港元 为钱永勋家族企业

雷递网 雷建平 12月23日血管介入器械公司――业聚医疗集团有限公司&#xff08;OrbusNeich Medical Group Limited&#xff09;&#xff08;简称“业聚医疗”&#xff0c;股票代码为&#xff1a;6929 &#xff09;今日在港交所上市。业聚医疗发行价为8.8港元&#xff0c;募资净…

SpringCloudGateway源码(四)限流组件

前言 如果不使用Alibaba Sentinel的网关流控规则&#xff0c; 是否可以选择使用SpringCloudGateway基于Redis的限流组件&#xff1f; 基于这个问题&#xff0c;笔者想了解一下scg自带限流组件的实现原理。 一、使用案例 1、pom 注意要加入redis-reactive依赖。 <depe…

OA系统遇到的问题

目录 一、开始时间与结束时间之差 二、弹出层的大小以及位置设置 2.1、高度设置body-style 2.2、位置设置dialogStyle 三、vue2安装引入Ant Design Vue 四、按钮控制盒子的显示与隐藏 五、表单生成器思想 5.1、点击左侧控件库生成中间的控件元素 5.2、点击中间的控件&…

Flink-状态编程的基本概念

文章目录Flink 中的状态1.1 有状态算子1.2 状态的管理1.3 状态的分类&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e; 更多资源链接&#xff0c;欢迎访问作者gitee仓库&#xff1a;https://gitee.com/fanggaolei/learning-notes-warehouse/tree/master Fli…

springcloud-gateway简介

目录 1. gateway简介 1.1 是什么 1.2 作用 1.3 主要特征 1.4 与zuul的主要区别 1.5 主要组件 1.6 架构图 2. 开发示例 2.1 创建一个gateway模块 2.2 与nacos结合使用 2.2.1 默认规则 2.2.2 通过配置文件配置路由 2.2.3 动态路由 1. gateway简介 1.1 是什么 SpringC…

一文带你深入理解【Java基础】· 网络编程(上)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

Kali Linux中安装IDLE的方法

1 IDLE简介 IDLE是Integrated Development and Learning Enviroment即集成开发和学习环境的简称&#xff0c;是Python的集成开发环境。在Kali Linux中&#xff0c;可以通过IDLE进行Python编程。 2 Kali Linux中安装IDLE 2.1 查看Kali Linux中是否安装IDLE 在Kali Linux终端…

WEB1.0起源:全球首个网站info.cern.ch

伯纳斯李&#xff08;图&#xff09;1990年创立第一个网站。 info.cern.ch是世上第一个网站&#xff0c;提供有关万维网的资料。 info.cern.ch这个网站依然运作如常。 英国科学家蒂姆伯纳斯-李 (Tim Berners-Lee) 于 1989 年在 CERN 工作期间发明了万维网 (WWW)。Web 最初的构思…

基于Vue+SpringBoot智慧校园疫情防控系统(PC端、手机端)--附源码

介绍 智慧校园疫情防控系统——PC 手机端 多端并行 项目源码下载&#xff1a;https://download.csdn.net/download/DeepLearning_/87340321 软件架构 手机端信息系统——日常健康信息填报系统&#xff08;前端手机端 文件夹&#xff09;电脑端智疫图 —— 数据可视化界面 &…

一种新的语义分割思路

这两天看到一篇挺有意思的论文&#xff0c;虽然不是语义分割方面的但是挺有意思的&#xff0c;因此在这里跟大家分享一下&#xff0c;这个也是一种语义分割的思路和方法。 Paper&#xff1a;Fully-Convolutional Siamese Networks for Object Tracking. SiamFC是深度学习目标…

【深入浅出 Yarn 架构与实现】4-2 RM 管理 Application Master

上一篇文章对 ResourceManager 整体架构和功能进行了讲述。本篇将对 RM 中管理 Application Master 的部分进行深入的讲解。 下面将会介绍 RM 与 AM 整体通信执行流程&#xff0c;并对 RM 中涉及的对应服务进行具体讲解。 为了更好的学习本篇知识&#xff0c;建议先熟悉以下知识…

股票量化分析工具QTYX使用攻略——实盘交易信号监控(更新2.5.7)

搭建自己的量化系统如果要长期在市场中立于不败之地&#xff01;必须要形成一套自己的交易系统。如何学会搭建自己的量化交易系统&#xff1f;边学习边实战&#xff0c;在实战中学习才是最有效地方式。于是我们分享一个即可以用于学习&#xff0c;也可以用于实战炒股分析的量化…

3天学会撰写软件发明专利——5.专利法律常识

“无意中发现了一个巨牛的人工智能教程&#xff0c;忍不住分享一下给大家。教程不仅是零基础&#xff0c;通俗易懂&#xff0c;而且非常风趣幽默&#xff0c;像看小说一样&#xff01;觉得太牛了&#xff0c;所以分享给大家。点这里可以跳转到教程。”。 1)假冒专利行为及其法…

Activemq的Broker

目录 一、broker是什么 二、启动broker时指定配置文件 三、嵌入式Broker &#xff08;一&#xff09;Pom.xml &#xff08;二&#xff09;Broker实例 &#xff08;三&#xff09;验证 一、broker是什么 相当于一个ActiveMQ服务器实例。说白了&#xff0c;Broker其实就是…

YK-L1刷机

文章目录1.测试是否能够连接到路由器2.刷breed3.Padavan firmware编译4.烧板5.验证杂文1.1内核模块编写&#xff08;使用insmod方式&#xff09;1.2内核模块编写&#xff08;跟随内核一起编译&#xff09;参考资料1.测试是否能够连接到路由器 插上网线和电脑相连&#xff0c;网…

计算机网络基础——一文详解IPv4与子网划分

IPv4地址概述 在因特网中&#xff0c;为了实现计算机之间的相互通信&#xff0c;通常需要为每台计算机分配一个IP地址。在互联网的发展过程中主要有两个版本的互联网协议&#xff0c;分别是IPv4(Internet Protocol version4)和IPv6 (Internet Protocol version 6) IPv4的IP地址…

SpringBoot:模块探究之spring-boot-starters

Spring Boot Starters 是一组方便的依赖描述符&#xff0c;您可以将它们包含在您的应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式服务&#xff0c;而无需搜索示例代码和复制粘贴大量依赖项描述符。 例如&#xff0c;如果想使用 Spring 和 JPA 进行数据库访问&am…