-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from SmartCompiler/feature/3d-sphere
Add 3d sphere three js to the project
- Loading branch information
Showing
17 changed files
with
4,341 additions
and
2,177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { | ||
DirectionalLight, | ||
AmbientLight, | ||
IcosahedronGeometry, | ||
MeshStandardMaterial, | ||
Mesh, | ||
LinearFilter, | ||
WebGLRenderTarget | ||
} from 'three' | ||
import { getCamera, getRenderSize, getScene, getTick } from './render/init.js' | ||
// import postprocessing passes | ||
import { SavePass } from 'three/examples/jsm/postprocessing/SavePass.js' | ||
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js' | ||
import { BlendShader } from 'three/examples/jsm/shaders/BlendShader.js' | ||
import { CopyShader } from 'three/examples/jsm/shaders/CopyShader.js' | ||
|
||
import vertexParse from './shaders/vertex-pars.glsl' | ||
import vertexMain from './shaders/vertex-main.glsl' | ||
import fragmentPars from './shaders/fragment_pars.glsl' | ||
import fragmentMain from './shaders/fragment_main.glsl' | ||
|
||
const startApp = () => { | ||
const scene = getScene() | ||
const { width, height } = getRenderSize() | ||
|
||
// settings | ||
const MOTION_BLUR_AMOUNT = 0.725 | ||
|
||
// lighting | ||
const dirLight = new DirectionalLight('#36938a', 1.5) | ||
dirLight.position.set(10, 10, 2) | ||
|
||
const ambientLight = new AmbientLight('#3aa294', 0.9) | ||
scene.add(dirLight, ambientLight) | ||
|
||
// meshes | ||
const geometry = new IcosahedronGeometry(1, 300) | ||
const material = new MeshStandardMaterial({ | ||
onBeforeCompile(shader) { | ||
// Storing a reference to the shader object | ||
material.userData.shader = shader | ||
|
||
// uniforms | ||
shader.uniforms.uTime = { value: 0 } | ||
|
||
const parsVertextString = /* glsl*/ `#include <displacementmap_pars_vertex>` | ||
shader.vertexShader = shader.vertexShader.replace( | ||
parsVertextString, | ||
parsVertextString + vertexParse | ||
) | ||
|
||
const mainVertexString = /* glsl */ `#include <displacementmap_vertex>` | ||
shader.vertexShader = shader.vertexShader.replace( | ||
mainVertexString, | ||
mainVertexString + vertexMain | ||
) | ||
|
||
const mainFragmentString = /* glsl */ `#include <normal_fragment_maps>` | ||
const parsFragmentString = /* glsl */ `#include <bumpmap_pars_fragment>` | ||
shader.fragmentShader = shader.fragmentShader.replace( | ||
parsFragmentString, | ||
parsFragmentString + fragmentPars | ||
) | ||
shader.fragmentShader = shader.fragmentShader.replace( | ||
mainFragmentString, | ||
mainFragmentString + fragmentMain | ||
) | ||
} | ||
}) | ||
|
||
const ico = new Mesh(geometry, material) | ||
scene.add(ico) | ||
|
||
// postprocessing | ||
const renderTargetParameters = { | ||
minFilter: LinearFilter, | ||
magFilter: LinearFilter, | ||
stencilBuffer: false, | ||
} | ||
|
||
// save pass | ||
const savePass = new SavePass(new WebGLRenderTarget(width, height, renderTargetParameters)) | ||
|
||
// blend pass | ||
const blendPass = new ShaderPass(BlendShader, 'tDiffuse1') | ||
blendPass.uniforms['tDiffuse2'].value = savePass.renderTarget.texture | ||
blendPass.uniforms['mixRatio'].value = MOTION_BLUR_AMOUNT | ||
|
||
// output pass | ||
const outputPass = new ShaderPass(CopyShader) | ||
outputPass.renderToScreen = true | ||
|
||
getTick(({ timestamp, timeDiff }) => { | ||
const time = timestamp / 10000; | ||
if (material?.userData?.shader?.uniforms?.uTime) | ||
material.userData.shader.uniforms.uTime.value = time | ||
}) | ||
} | ||
|
||
export default startApp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import startApp from './app'; | ||
import { initEngine } from './render/init'; | ||
|
||
export const initSphere = async (sphereRef) => { | ||
await initEngine(sphereRef) | ||
startApp() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { | ||
Scene, | ||
PerspectiveCamera, | ||
WebGLRenderer, | ||
PCFSoftShadowMap, | ||
WebGLRenderTarget | ||
} from 'three' | ||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' | ||
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js' | ||
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js' | ||
import TickManager from './tick-manager.js' | ||
|
||
let scene, | ||
camera, | ||
renderer, | ||
composer, | ||
controls, | ||
renderWidth, | ||
renderHeight, | ||
renderAspectRatio | ||
const renderTickManager = new TickManager() | ||
|
||
export const initEngine = async (sphereRef) => { | ||
scene = new Scene() | ||
|
||
renderWidth = 370 | ||
renderHeight = 370 | ||
|
||
renderAspectRatio = renderWidth / renderHeight | ||
|
||
camera = new PerspectiveCamera(75, renderAspectRatio, 0.1, 100) | ||
camera.position.z = 2.2 | ||
|
||
renderer = new WebGLRenderer({ antialias: true, alpha: true}) | ||
renderer.setSize(renderWidth, renderHeight) | ||
|
||
// shadow | ||
renderer.shadowMap.enabled = true | ||
renderer.shadowMap.type = PCFSoftShadowMap | ||
console.log(renderer.domElement) | ||
sphereRef.current.appendChild(renderer.domElement) | ||
|
||
const target = new WebGLRenderTarget(renderWidth, renderHeight, { | ||
samples: 8 | ||
}) | ||
composer = new EffectComposer(renderer, target) | ||
|
||
const renderPass = new RenderPass(scene, camera) | ||
composer.addPass(renderPass) | ||
|
||
controls = new OrbitControls(camera, renderer.domElement) | ||
controls.enableDamping = false | ||
controls.enableZoom = false | ||
controls.enablePan = false | ||
|
||
window.addEventListener( | ||
'resize', | ||
() => { | ||
camera.aspect = renderAspectRatio | ||
camera.updateProjectionMatrix() | ||
composer.setSize(renderWidth, renderHeight) | ||
}, | ||
false | ||
) | ||
|
||
renderTickManager.startLoop() | ||
} | ||
|
||
export const getRenderer = () => renderer | ||
|
||
export const getRenderSize = () => ({ width: renderWidth, height: renderHeight }) | ||
|
||
export const getScene = () => scene | ||
|
||
export const getCamera = () => camera | ||
|
||
export const getControls = () => controls | ||
|
||
export const getComposer = () => composer | ||
|
||
|
||
export const addPass = (pass) => { | ||
composer.addPass(pass) | ||
} | ||
|
||
export const getTick = (fn) => { | ||
if (renderTickManager) { | ||
const _tick = (e) => { | ||
fn(e.data) | ||
} | ||
renderTickManager.addEventListener('tick', _tick) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { getComposer, getControls, getRenderer } from './init.js'; | ||
|
||
// animation params | ||
const localData = { | ||
timestamp: 0, | ||
timeDiff: 0, | ||
frame: null, | ||
}; | ||
const localFrameOpts = { | ||
data: localData, | ||
}; | ||
|
||
const frameEvent = new MessageEvent('tick', localFrameOpts); | ||
|
||
class TickManager extends EventTarget { | ||
constructor({ timestamp, timeDiff, frame } = localData) { | ||
super(); | ||
|
||
this.timestamp = timestamp; | ||
this.timeDiff = timeDiff; | ||
this.frame = frame; | ||
} | ||
startLoop() { | ||
const composer = getComposer(); | ||
const renderer = getRenderer(); | ||
const controls = getControls(); | ||
|
||
if (!renderer) { | ||
throw new Error('Updating Frame Failed : Uninitialized Renderer'); | ||
} | ||
|
||
let lastTimestamp = performance.now(); | ||
|
||
const animate = (timestamp, frame) => { | ||
this.timestamp = timestamp ?? performance.now(); | ||
this.timeDiff = timestamp - lastTimestamp; | ||
|
||
const timeDiffCapped = Math.min(Math.max(this.timeDiff, 0), 100); | ||
|
||
// performance tracker start | ||
|
||
controls.update(); | ||
|
||
composer.render(); | ||
// renderer.render(scene, camera); | ||
|
||
this.tick(timestamp, timeDiffCapped, frame); | ||
|
||
// performance tracker end | ||
}; | ||
|
||
renderer.setAnimationLoop(animate); | ||
} | ||
tick(timestamp, timeDiff, frame) { | ||
localData.timestamp = timestamp; | ||
localData.frame = frame; | ||
localData.timeDiff = timeDiff; | ||
this.dispatchEvent(frameEvent); | ||
} | ||
} | ||
|
||
export default TickManager; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
precision mediump float; | ||
|
||
|
||
varying vec3 vPosition; | ||
varying vec2 vUv; | ||
varying vec3 vNormal; | ||
varying float vDisplacement; | ||
|
||
void main() { | ||
|
||
gl_FragColor = vec4(vec3(vDisplacement), 1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
normal = perturbNormalArb( - vViewPosition, normal, vec2(dFdx(vDisplacement), dFdy(vDisplacement)), faceDirection ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
|
||
uniform float uTime; | ||
varying float vDisplacement; | ||
|
||
|
||
vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) { | ||
|
||
vec3 vSigmaX = dFdx( surf_pos.xyz ); | ||
vec3 vSigmaY = dFdy( surf_pos.xyz ); | ||
vec3 vN = surf_norm; // normalized | ||
|
||
vec3 R1 = cross( vSigmaY, vN ); | ||
vec3 R2 = cross( vN, vSigmaX ); | ||
|
||
float fDet = dot( vSigmaX, R1 ) * faceDirection; | ||
|
||
vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 ); | ||
return normalize( abs( fDet ) * surf_norm - vGrad ); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
// Pattern | ||
vec3 coords = normal; | ||
coords.y += uTime; | ||
|
||
vec3 noisyPattern = vec3(noise(coords)); | ||
float pattern = wave(noisyPattern + uTime); | ||
// Varying | ||
vDisplacement = pattern; | ||
|
||
float displacement = vDisplacement / 3.0; | ||
|
||
transformed += normalize(objectNormal) * displacement; |
Oops, something went wrong.