增加 光噪声场景

This commit is contained in:
hawk86104 2024-10-10 17:57:40 +08:00
parent f29d042cfc
commit 5dc94d23c8
9 changed files with 608 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View File

@ -0,0 +1,96 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-10-10 16:50:34
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-10-10 17:04:01
-->
<template>
<TresLineSegments :material="gm" :geometry="gg" />
</template>
<script setup lang="ts">
import * as THREE from 'three'
import noise from '../../shaders/lightNoise.glsl'
const props = withDefaults(
defineProps<{
globalUniforms: any
}>(),
{},
)
const gPos = []
const gEnds = []
const gCount = 20000
for (let i = 0; i < gCount; i++) {
const x = THREE.MathUtils.randFloatSpread(35)
const y = THREE.MathUtils.randFloat(-5, 10)
const z = THREE.MathUtils.randFloatSpread(35)
const len = THREE.MathUtils.randFloat(0.25, 0.5)
gPos.push(x, y, z, x, y, z)
gEnds.push(0, len, 1, len)
}
const gg = new THREE.BufferGeometry()
gg.setAttribute('position', new THREE.Float32BufferAttribute(gPos, 3))
gg.setAttribute('gEnds', new THREE.Float32BufferAttribute(gEnds, 2))
const gm = new THREE.LineBasicMaterial({
color: 0x884488,
transparent: true,
// @ts-ignore
onBeforeCompile: (shader) => {
shader.uniforms.time = props.globalUniforms.time
shader.uniforms.noiseTex = props.globalUniforms.noise
shader.uniforms.globalBloom = props.globalUniforms.globalBloom
shader.vertexShader = `
uniform float time;
uniform sampler2D noiseTex;
attribute vec2 gEnds;
varying float vGEnds;
varying float vH;
${shader.vertexShader}
`.replace(
`#include <begin_vertex>`,
`#include <begin_vertex>
vec3 pos = position;
vec2 nUv = (vec2(pos.x, -pos.z) - vec2(-25.)) / 50.;
float h = texture2D(noiseTex, nUv).g;
h = (h - 0.5) * 4.;
pos.y = -mod(10. - (pos.y - time * 5.), 15.) + 10.;
h = pos.y - h;
pos.y += gEnds.x * gEnds.y;
transformed = pos;
vGEnds = gEnds.x;
vH = smoothstep(3., 0., h);
`,
)
shader.fragmentShader = `
uniform float time;
uniform float globalBloom;
varying float vGEnds;
varying float vH;
${noise}
${shader.fragmentShader}
`.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
float op = 1. - vGEnds;
op = pow(op, 3.);
float h = (pow(vH, 3.) * 0.5 + 0.5);
vec3 col = diffuse * h; // lighter close to the surface
col *= 1. + smoothstep(0.99, 1., h); // sparkle at the surface
if (globalBloom > 0.5) {
//col *= 0.5;
}
vec4 diffuseColor = vec4( col, op );
`,
)
},
})
</script>

View File

@ -0,0 +1,130 @@
<template>
<lucesPlane :globalUniforms="globalUniforms" />
<portal :globalUniforms="globalUniforms" />
<drops :globalUniforms="globalUniforms" />
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'
import { useRenderLoop, useTresContext } from '@tresjs/core'
import noise from '../../shaders/lightNoise.glsl'
import lucesPlane from './lucesPlane.vue'
import portal from './portal.vue'
import drops from './drops.vue'
import { watch } from 'vue'
const globalUniforms = {
time: { value: 0 },
globalBloom: { value: 0 },
noise: { value: null as any },
}
const renderTarget = new THREE.WebGLRenderTarget(512, 512)
const rtScene = new THREE.Scene()
const rtCamera = new THREE.Camera()
const rtGeo = new THREE.PlaneGeometry(2, 2)
const rtMat = new THREE.MeshBasicMaterial({
// @ts-ignore
onBeforeCompile: (shader) => {
shader.uniforms.time = globalUniforms.time
shader.fragmentShader = `
uniform float time;
${noise}
${shader.fragmentShader}
`.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
vec3 col = vec3(0);
float h = clamp(smoothNoise2(vUv * 50.), 0., 1.);
col = vec3(h);
vec4 diffuseColor = vec4( col, opacity );
`,
)
},
})
rtMat.defines = { USE_UV: '' }
const rtPlane = new THREE.Mesh(rtGeo, rtMat)
rtScene.add(rtPlane)
globalUniforms.noise.value = renderTarget.texture
const { camera, renderer, scene, sizes, controls } = useTresContext()
watch(
() => controls.value,
(v: any) => {
v?.target.set(0, 2, 0)
if (!scene.value.background) {
scene.value.background = new THREE.Color(0x665566)
}
},
)
const bloomComposer = new EffectComposer(renderer.value)
const finalComposer = new EffectComposer(renderer.value)
const renderScene = new RenderPass(scene.value, camera.value)
const bloomPass = new UnrealBloomPass(new THREE.Vector2(sizes.width.value, sizes.height.value), 1.2, 0.5, 0)
bloomComposer.renderToScreen = false
bloomComposer.addPass(renderScene)
bloomComposer.addPass(bloomPass)
const finalPass = new ShaderPass(
new THREE.ShaderMaterial({
uniforms: {
baseTexture: { value: null },
bloomTexture: { value: bloomComposer.renderTarget2.texture },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: `
uniform sampler2D baseTexture;
uniform sampler2D bloomTexture;
varying vec2 vUv;
void main() {
gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
}`,
defines: {},
}),
'baseTexture',
)
finalPass.needsSwap = true
finalComposer.addPass(renderScene)
finalComposer.addPass(finalPass)
scene.value.fog = new THREE.Fog(0x665566, 1, 25)
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
globalUniforms.time.value = elapsed
if (renderer.value) {
renderer.value.setRenderTarget(renderTarget)
renderer.value.render(rtScene, rtCamera)
renderer.value.setRenderTarget(null)
globalUniforms.globalBloom.value = 1.2
scene.value.fog.color.set(0x000000)
scene.value.fog.near = 15
scene.value.background?.set(0x000000)
bloomComposer.render()
globalUniforms.globalBloom.value = 0
scene.value.fog.color.set(0x665566)
scene.value.fog.near = 10
scene.value.background?.set(0x665566)
finalComposer.render()
}
})
</script>

View File

@ -0,0 +1,171 @@
<template>
<TresMesh :geometry="lGeometry" :material="lMaterial" />
<TresMesh :material="pMaterial">
<TresPlaneGeometry :args="[50, 50, 500, 500]" :rotateX="-Math.PI * 0.5" />
</TresMesh>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { useRenderLoop } from '@tresjs/core'
const props = withDefaults(
defineProps<{
globalUniforms: any
}>(),
{},
)
const luces = [] as any
const lucesInit = [] as any
const instCount = 100
const sphereGeometry = new THREE.SphereGeometry(1, 36, 18) as any
const lGeometry = new THREE.InstancedBufferGeometry().copy(sphereGeometry)
lGeometry.instanceCount = instCount
const instData = []
for (let i = 0; i < instCount; i++) {
let x = THREE.MathUtils.randFloatSpread(49)
let z = THREE.MathUtils.randFloatSpread(49)
let scale = THREE.MathUtils.randFloat(0.0625, 0.125)
let ldist = THREE.MathUtils.randFloat(1, 3)
instData.push(x, z, scale)
lucesInit.push(new THREE.Vector4(x, z, ldist, THREE.MathUtils.randFloat(1, 2)))
luces.push(new THREE.Vector4(x, z, scale, ldist))
}
lGeometry.setAttribute('instData', new THREE.InstancedBufferAttribute(new Float32Array(instData), 3))
const lMaterial = new THREE.MeshBasicMaterial({
color: 0xff2222,
// @ts-ignore
onBeforeCompile: (shader) => {
shader.uniforms.noiseTex = props.globalUniforms.noise
shader.vertexShader = `
uniform sampler2D noiseTex;
attribute vec4 instData;
${shader.vertexShader}
`.replace(`#include <begin_vertex>`,
`#include <begin_vertex>
transformed = position * instData.z;
transformed.x += instData.x;
transformed.z += instData.y;
vec2 nUv = (vec2(instData.x, -instData.y) - vec2(-25.)) / 50.;
float h = texture2D(noiseTex, nUv).g;
h = (h - 0.5) * 4.;
transformed.y += h;
`,)
},
})
const planeUniforms = {
luces: { value: luces },
}
const pMaterial = new THREE.MeshLambertMaterial({
color: 0x241224,
// @ts-ignore
onBeforeCompile: (shader: any) => {
shader.uniforms.luces = planeUniforms.luces
shader.uniforms.globalBloom = props.globalUniforms.globalBloom
shader.uniforms.noiseTex = props.globalUniforms.noise
shader.vertexShader = `
uniform float time;
uniform sampler2D noiseTex;
varying vec3 vPos;
varying float intensity;
//// https://discourse.threejs.org/t/calculating-vertex-normals-after-displacement-in-the-vertex-shader/16989/8 ///
// the function which defines the displacement
float displace(vec2 vUv) {
return (texture2D(noiseTex, vUv).g - 0.5) * 4.;
}
vec3 getNormal(vec2 vUv){
vec3 displacedPosition = position + normal * displace(vUv);
float texelSize = 1.0 / 512.0; // temporarily hardcoding texture resolution
float offset = 0.1;
vec3 neighbour1 = position + vec3(1., 0., 0.) * offset;
vec3 neighbour2 = position + vec3(0., 0., 1.) * offset;
vec2 neighbour1uv = vUv + vec2(-texelSize, 0);
vec2 neighbour2uv = vUv + vec2(0, -texelSize);
vec3 displacedNeighbour1 = neighbour1 + normal * displace(neighbour1uv);
vec3 displacedNeighbour2 = neighbour2 + normal * displace(neighbour2uv);
// https://i.ya-webdesign.com/images/vector-normals-tangent-16.png
vec3 displacedTangent = displacedNeighbour1 - displacedPosition;
vec3 displacedBitangent = displacedNeighbour2 - displacedPosition;
// https://upload.wikimedia.org/wikipedia/commons/d/d2/Right_hand_rule_cross_product.svg
vec3 displacedNormal = normalize(cross(displacedBitangent, displacedTangent));
return displacedNormal;
}
${shader.vertexShader}
`.replace(
`#include <begin_vertex>`,
`#include <begin_vertex>
float h = texture2D(noiseTex, uv).g;
intensity = h;
h = (h - 0.5) * 4.;
transformed.y = h;
vPos = transformed;
transformedNormal = normalMatrix * getNormal(uv);
`,
)
shader.fragmentShader = `
uniform vec4 luces[${instCount}];
uniform sampler2D noiseTex;
uniform float globalBloom;
varying vec3 vPos;
varying float intensity;
${shader.fragmentShader}
`
.replace(
`#include <fog_fragment>`,
`
vec3 col = vec3(1, 0, 0)*0.75;
float intensity = 0.;
for(int i = 0;i < ${instCount}; i++){
vec4 lux = luces[i];
vec2 luxUv = (vec2(lux.x, -lux.y) - vec2(-25.)) / 50.;
float h = texture2D(noiseTex, luxUv).g;
h = (h - 0.5) * 4.;
vec3 lightPos = vec3(lux.x, h, lux.y);
float currIntensity = smoothstep(lux.z + lux.w, lux.z, distance(vPos, lightPos));
intensity += pow(currIntensity, 16.);
}
intensity = clamp(intensity, 0., 1.);
col = mix(col * 0.5, col, intensity);
col = mix(gl_FragColor.rgb, col, intensity);
col += vec3(1) * intensity * 0.01;
gl_FragColor = vec4( col, opacity );
#include <fog_fragment>
`,
)
.replace(
`#include <dithering_fragment>`,
`#include <dithering_fragment>
if (globalBloom > 0.5) {
gl_FragColor = vec4(0);
}
`,
)
},
})
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
for (let i = 0; i < instCount; i++) {
const li = lucesInit[i]
let z = ((li.y + elapsed + 25) % 50) - 25
luces[i].y = z
luces[i].w = (Math.sin(elapsed * li.w * ((i % 3) + 1)) * Math.cos(elapsed * li.w * ((i % 5) + 1)) * 0.25 + 0.25) * li.z + li.z * 0.75
lGeometry.attributes.instData.setY(i, z)
}
lGeometry.attributes.instData.needsUpdate = true
})
</script>

View File

@ -0,0 +1,90 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-10-10 16:38:18
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-10-10 17:37:36
-->
<template>
<TresMesh :material="pMaterial" :position="[0, 1.25+2.5, -12]">
<TresPlaneGeometry :args="[5, 5]" />
</TresMesh>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import noise from '../../shaders/lightNoise.glsl'
const props = withDefaults(
defineProps<{
globalUniforms: any
}>(),
{},
)
const pMaterial = new THREE.MeshBasicMaterial({
color: 0xff6633,
transparent: true,
// @ts-ignore
onBeforeCompile: (shader) => {
shader.uniforms.time = props.globalUniforms.time
shader.uniforms.globalBloom = props.globalUniforms.globalBloom
shader.fragmentShader = `
#define S(a, b, t) smoothstep(a, b, t)
uniform float time;
uniform float globalBloom;
${noise}
float getTri(vec2 uv, float shift){
uv = uv * 2.-1.;
float a = atan(uv.x + shift,uv.y) + 3.1415926;
float r = 3.1415926 * 2./3.;
return cos(floor(.5+a/r)*r-a)*length(uv);
}
float doubleTri(vec2 uv, float still, float width){
vec2 baseUv = uv;
vec2 e2 = fwidth(baseUv * 20.);
float e = min(e2.x, e2.y) * width;
float baseTri = getTri(baseUv, cos(baseUv.y * 31. + time) * sin(baseUv.y * 27. + time * 4.) * 0.025 * still);
float td = abs(fract(baseTri * 20.) - 0.5);
float tri = S(e, 0., td) - S(0., e, td);
tri *= step(0.4, baseTri) - step(0.5, baseTri);
return tri;
}
${shader.fragmentShader}
`
.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
float tri = doubleTri(vUv, 0.0, 16.);
float triWave = doubleTri(vUv, 1.0, 8.);
float fullTri = max(tri, triWave);
if (fullTri < 0.5) discard;
vec3 col = mix(diffuse, vec3(0.75), fullTri);
float blinking = smoothNoise(vec2(time, time * 5.));
blinking = blinking * 0.9 + 0.1;
vec4 diffuseColor = vec4(col * blinking, fullTri);
`,
)
.replace(
`#include <dithering_fragment>`,
`#include <dithering_fragment>
if (globalBloom > 0.5) {
gl_FragColor = vec4(gl_FragColor.rgb * 0.375, fullTri);
}
`,
)
},
})
pMaterial.defines = { USE_UV: '' }
// pMaterial.extensions = { derivatives: true }
</script>

View File

@ -0,0 +1,43 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-10-10 17:52:35
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-10-10 17:54:56
-->
<template>
<div class="text">
<span class="retro noselect"><span style="color: #eae"></span>噪声</span>
</div>
</template>
<style lang="less" scoped>
.text {
position: absolute;
bottom: 6vh;
width: 100%;
text-align: center;
z-index: 9999;
}
.retro {
font-size: 18vh;
display: block;
color: #000;
text-shadow: 0 0 0.125vh #f4a, 0 0 0.125vh #f4a, 0 0 0.25vh #f4a, 0 0 0.5vh #f4a, 0 0 0.75vh #f4a;
}
.noselect {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently
supported by Chrome and Opera */
}
</style>

View File

@ -63,6 +63,12 @@ export default {
name: 'repulsionEffect',
title: '排斥效果',
referenceSource: { title: 'alvarosabu', url: 'https://lab.tresjs.org/experiments/repulsion-effect' },
}
},
{
src: 'plugins/visualArts/preview/lightNoise.png',
type: 'img',
name: 'lightNoise',
title: '光噪声',
},
],
}

View File

@ -0,0 +1,41 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-10-10 16:08:41
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-10-10 17:44:14
-->
<template>
<textC />
<TresCanvas v-bind="tcConfig">
<TresPerspectiveCamera :position="[0, 3, 5]" :fov="45" :near="0.1" :far="1000" />
<OrbitControls v-bind="oc" />
<TresAmbientLight :intensity="0.5" />
<TresDirectionalLight :position="[0, 3, -12]" :intensity="1" />
<fboRender />
</TresCanvas>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from '@tresjs/cientos'
import fboRender from '../components/lightNoise/fboRender.vue'
import textC from '../components/lightNoise/text.vue'
const tcConfig = {
windowSize: true,
antialias: true,
renderMode: 'manual',
}
const oc = {
enableDamping: true,
minDistance: 5,
maxDistance: 10,
minPolarAngle: THREE.MathUtils.DEG2RAD * 60,
maxPolarAngle: THREE.MathUtils.DEG2RAD * 90,
makeDefault: true,
}
</script>

View File

@ -0,0 +1,30 @@
float N21(vec2 st){// https://thebookofshaders.com/10/
return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}
float smoothNoise(vec2 ip){// https://www.youtube.com/watch?v=zXsWftRdsvU
vec2 lv=fract(ip);
vec2 id=floor(ip);
lv=lv*lv*(3.-2.*lv);
float bl=N21(id);
float br=N21(id+vec2(1,0));
float b=mix(bl,br,lv.x);
float tl=N21(id+vec2(0,1));
float tr=N21(id+vec2(1,1));
float t=mix(tl,tr,lv.x);
return clamp(mix(b,t,lv.y)*.5+.5,0.,1.);
}
float smoothNoise2(vec2 p){
p.y+=time;
p/=4.;
float n=smoothNoise(p)*1.5;
n+=smoothNoise(p*2.01)*.25;
n+=smoothNoise(p*4.02)*.125;
n+=smoothNoise(p*8.03)*.0625;
n/=(1.5+.25+.125+.0625);
return clamp(n,0.,1.);
}