I have always wanted to create a sun like mesh and this is a small showcase of it.
The design is spheres scaled inside each other.
Avoiding artifacts which doublesided spheres have.
And creating a sun like object in 3D space.
Here is the code:
1import { ImprovedNoise } from 'three/examples/jsm/math/ImprovedNoise';2import React, { useState, useEffect, useMemo } from 'react';3import { Canvas, useFrame } from '@react-three/fiber';4import { OrbitControls } from '@react-three/drei';5import * as THREE from 'three';6import { EffectComposer, Bloom } from '@react-three/postprocessing';7import { KernelSize } from 'postprocessing'89const generate3DNoiseTexture = (width, height, depth) => {10 const size = width * height * depth;11 const data = new Float32Array(size);12 const noise = new ImprovedNoise();13 const scale = 10;1415 for (let z = 0; z < depth; z++) {16 for (let y = 0; y < height; y++) {17 for (let x = 0; x < width; x++) {18 const nx = x / width;19 const ny = y / height;20 const nz = z / depth;21 data[x + width * (y + height * z)] = (noise.noise(nx * scale, ny * scale, nz * scale) + 1) * 0.5;22 }23 }24 }2526 const texture = new THREE.Data3DTexture(data, width, height, depth);27 texture.minFilter = THREE.NearestMipMapLinearFilter;28 texture.magFilter = THREE.NearestMipMapLinearFilter;29 texture.format = THREE.RedFormat;30 texture.type = THREE.FloatType;31 texture.needsUpdate = true;32 texture.wrapR = texture.wrapS = texture.wrapT = THREE.RepeatWrapping;3334 return texture;35};3637const NoiseMaterial = ({ noiseTexture, front, alpha }) => {38 const [time, setTime] = useState(0);39 useFrame(({ clock }) => setTime(clock.getElapsedTime()));4041 const vertexShader = `42 varying vec3 vPosition;43 void main() {44 vPosition = position;45 vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);46 gl_Position = projectionMatrix * mvPosition;47 }48 `;4950 const fragmentShader = `51 varying vec3 vPosition;52 uniform sampler3D noiseTexture;53 uniform float alpha;54 uniform float time;5556 void main() {57 vec3 vPos = vPosition;58 vPos.xyz += time * 0.3;59 vPos.xyz = (vPos.xyz + time * 0.3 + 1.0) * (0.5 + time * 0.8);60 vPos = vec3(vPos);61 vec3 noise = texture(noiseTexture, vPos ).rgb;62 float stepper = step(alpha / 0.3, noise.r);63 gl_FragColor = vec4(0.0, 0.0, mix(stepper * 6.0 * 2.0 - alpha, 0.0, alpha), mix(0.0, stepper, noise.r / 0.7));64 }65 `;6667 return (68 <shaderMaterial69 attach="material"70 transparent={true}71 alphaToCoverage72 sizeAttenuation={false}73 depthTest={true}74 depthWrite={true}75 side={front ? THREE.FrontSide : THREE.BackSide}76 args={[{77 vertexShader,78 fragmentShader,79 uniforms: {80 noiseTexture: { value: noiseTexture },81 alpha: { value: alpha },82 time: { value: time }83 } }]}84 uniforms-noiseTexture-value={noiseTexture}85 uniforms-alpha-value={alpha / 10 - 0.1}86 uniforms-time-value={time * 1.0 / alpha / 50.0}87 />88 );89};9091const LayeredSpheres = ({ radius, noiseTexture, layers }) => {92 const layerOffset = 0.01;9394 return (95 <>96 {[...Array(layers)].map((_, i) => {97 const currentRadius = radius - i / layers * layerOffset;98 if (currentRadius <= 0) return null; // Prevent spheres with non-positive radius99100 return (101 <React.Fragment key={i}>102 <mesh>103 <sphereGeometry args={[currentRadius, 64, 64]} />104 <NoiseMaterial noiseTexture={noiseTexture} front={false} alpha={i} /> {/* Outer Sphere */}105 </mesh>106 <mesh>107 <sphereGeometry args={[currentRadius - layerOffset / 2, 64, 64]} />108 <NoiseMaterial noiseTexture={noiseTexture} front={true} alpha={i} /> {/* Inner Sphere */}109 </mesh>110 </React.Fragment>111 );112 })}113 </>114 );115};116117const LightingAndControls = () => (118 <>119 <ambientLight />120 <pointLight position={[10, 10, 10]} />121 <OrbitControls />122 </>123);124125const BloomEffect = () => (126 <EffectComposer multisampling={8}>127 <Bloom kernelSize={1} luminanceThreshold={0} luminanceSmoothing={0.9} intensity={0.6} />128 <Bloom kernelSize={KernelSize.HUGE} luminanceThreshold={0} luminanceSmoothing={0} intensity={.05} />129 </EffectComposer>130);131132const StarField = ({ count = 5000, radius = 100 }) => {133 const starsGeometry = useMemo(() => {134 const positions = new Float32Array(count * 3);135 for (let i = 0; i < count; i++) {136 const theta = THREE.MathUtils.randFloatSpread(360);137 const phi = THREE.MathUtils.randFloatSpread(360);138139 const distance = THREE.MathUtils.randFloatSpread(radius);140141 const x = distance * Math.cos(theta) * Math.sin(phi);142 const y = distance * Math.sin(theta) * Math.sin(phi);143 const z = distance * Math.cos(phi);144145 positions.set([x, y, z], i * 3);146 }147148 const geometry = new THREE.BufferGeometry();149 geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));150151 return geometry;152 }, [count, radius]);153154 return (155 <points geometry={starsGeometry}>156 <pointsMaterial size={0.001} color="white" />157 </points>158 );159};160161const AppCanvas = ({ children }) => (162 <Canvas style={{ height: '100vh', width: '100vw' }}>163 <color attach="background" args={['black']} />164 {children}165 </Canvas>166);167168const App = () => {169 const [noiseTexture, setNoiseTexture] = useState(null);170171 useEffect(() => {172 setNoiseTexture(generate3DNoiseTexture(256, 256, 256));173 }, []);174175 if (!noiseTexture) return null;176177 return (178 <AppCanvas>179 <LayeredSpheres radius={1} noiseTexture={noiseTexture} layers={60} />180 <LightingAndControls />181 <BloomEffect />182 <StarField />183 <mesh>184 <sphereGeometry args={[0.99, 64, 64]} />185 <meshBasicMaterial color={'#FAF9F6'} emissionIntensity={1.0}/>186 </mesh>187 </AppCanvas>188 );189};190191export default App;