火焰Shader

在这里插入图片描述

<template>
  <div class="circle" ref="circle"></div>
</template>

<script setup>
import {onMounted, ref} from "vue";
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import output_fragment from '../shader/output_fragment.glsl.js'
let scene, camera, renderer, controls, circle = ref(null);
let timeValue = {value: 0.0}

function init() {
  let width = circle.value.clientWidth;
  let height = circle.value.clientHeight
  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer({
    antialias: true, //开启锯齿
  });
  renderer.physicallyCorrectLights = true;
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  renderer.toneMappingExposure = 1.0
  renderer.setClearColor(0x001111, 1);
  renderer.setSize(width, height)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  renderer.setClearColor(new THREE.Color('#32373E'), 1);
  camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000)
  camera.position.set(500, 500, 500)
  controls = new OrbitControls(camera, renderer.domElement);
  let light = new THREE.AmbientLight(0xadadad, 0.8); // soft white light
  scene.add(light)
  let light_2 = new THREE.HemisphereLight(0x00AAFF, 0xFFAA00, 0.8)
  scene.add(light_2)
  scene.add(new THREE.AxesHelper(500))
  const geometry = new THREE.PlaneGeometry(500, 500);
  // geometry.translate(250, 250, 0)
  // geometry.rotateX(Math.PI / 2)
  const material = new THREE.MeshBasicMaterial({color: 0xffff00, side: THREE.DoubleSide});

  let vertexShader = `
		varying vec2 vUv;
		void main(){
			vUv = uv;
			gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
		}
	`;
  let fragmentShader = `
    vec2 hash( vec2 p )
  {
    p = vec2( dot(p,vec2(127.1,311.7)),
        dot(p,vec2(269.5,183.3)) );
    return -1.0 + 2.0*fract(sin(p)*43758.5453123);
  }

  float noise( in vec2 p )
  {
    const float K1 = 0.366025404; // (sqrt(3)-1)/2;
    const float K2 = 0.211324865; // (3-sqrt(3))/6;

    vec2 i = floor( p + (p.x+p.y)*K1 );

    vec2 a = p - i + (i.x+i.y)*K2;
    vec2 o = (a.x>a.y) ? vec2(1.0,0.0) : vec2(0.0,1.0);
    vec2 b = a - o + K2;
    vec2 c = a - 1.0 + 2.0*K2;

    vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );

    vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));

    return dot( n, vec3(70.0) );
  }

    float fbm(vec2 uv)
  {
    float f;
    mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
    f  = 0.5000*noise( uv ); uv = m*uv;
    f += 0.2500*noise( uv ); uv = m*uv;
    f += 0.1250*noise( uv ); uv = m*uv;
    f += 0.0625*noise( uv ); uv = m*uv;
    f = 0.5 + 0.5*f;
    return f;
  }

  uniform vec3      iResolution;           // 视口分辨率(像素)
  uniform float     iTime;
  uniform float opacity;
  varying vec2 vUv;
    void main() {
        vec2 uv = vUv.xy / iResolution.xy;
        vec2 q = uv;
        q.x *= 1.;
        q.y *= 1.;
        float strength = floor(q.x+1.);
        float T3 = max(3.,1.25*strength)*iTime;
        q.x = mod(q.x,1.)-0.5;
        q.y -= 0.25;
        float n = fbm(strength*q - vec2(0,T3));
        float c = 1. - 16. * pow( max( 0., length(q*vec2(1.8+q.y*1.5,.75) ) - n * max( 0., q.y+.25 ) ),1.2 );
       float c1 = n * c * (1.5-pow(1.25*uv.y,4.));
        c1=clamp(c1,0.,1.);

        vec3 col = vec3(1.5*c1, 1.5*c1*c1*c1, c1*c1*c1*c1*c1*c1);
        float a = c * (1.-pow(uv.y,3.));
        gl_FragColor = vec4( mix(vec3(0.),col,a),  a);
    }
  `


  let material2 = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader,
    side: THREE.DoubleSide,
    transparent: true,
    uniforms: {
      iTime: timeValue,
      iResolution: { value: new THREE.Vector3( 1,1,1) }
    },
    opacity: {
      value: 0.3
    },
  })

  const plane = new THREE.Mesh(geometry, material2);
  scene.add(plane);
  // plane.rotateX(-Math.PI/2)
}

function animal() {
  renderer.render(scene, camera);
  timeValue.value += 0.01
  requestAnimationFrame(animal)
}

onMounted(() => {
  init();
  circle.value.appendChild(renderer.domElement)
  animal();
})
</script>

<style scoped lang="less">
.circle {
  height: 100%;
}
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity的火焰shader可以通过多种方式实现,下面是其中一种实现方式: 1. 创建一个新的材质,并将其shader设置为“Standard”或“Standard (Specular Setup)”。 2. 在材质的属性面板中添加一个新的纹理,用于表示火焰形状的alpha通道。这个纹理可以是一个黑色背景,中心区域是白色火焰形状的灰度图像。 3. 添加一个新的颜色属性,用于定义火焰的颜色。 4. 在shader中添加以下代码: ``` Shader "Custom/Flame" { Properties { _MainTex ("Flame Texture", 2D) = "white" {} _Color ("Flame Color", Color) = (1,1,1,1) _Speed ("Speed", Range(0, 10)) = 1 _Intensity ("Intensity", Range(0, 5)) = 1 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent"} LOD 200 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; float _Speed; float _Intensity; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } half4 frag (v2f i) : SV_Target { half4 texColor = tex2D(_MainTex, i.uv); float alpha = texColor.a; float t = _Time.y * _Speed; float sinx = sin(i.uv.x * 20 + t); float siny = sin(i.uv.y * 20 + t + 0.5); float noise = sin(sinx + siny) * 0.5 + 0.5; float intensity = pow(noise, _Intensity); return alpha * _Color * intensity; } ENDCG } } FallBack "Diffuse" } ``` 5. 将这个shader拖到材质中,并将火焰纹理拖到“MainTex”属性中。 6. 调整属性面板中的“Color”、“Speed”和“Intensity”属性,直到得到满意的火焰效果。 这个shader使用了alpha通道纹理来定义火焰形状,并且根据时间和噪声函数来产生火焰动态效果。你可以根据自己的需求和创意来调整shader代码和属性面板中的属性,以得到更加逼真和有趣的火焰效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值