Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modified colors of rain particles via applying vertex shader to built in Three.js MeshStandardMaterial #4

Merged
merged 4 commits into from
Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 57 additions & 38 deletions src/components/particles/rainParticles.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import * as THREE from 'three';
import React, {useRef,useEffect} from 'react'
import {useFrame} from 'react-three-fiber'
import React, {useRef,useEffect, useFrame} from 'react'
// import {useFrame} from 'react-three-fiber'
import RainMat from "../shaders/RainParticleMaterial.js";
import RainMat2 from "../shaders/RainParticleMaterialTwo.js";

export default function RainParticles({enabled}) {

var mParticleSystem;
var prefabGeometry;
var prefabBufferGeometry;
var mSphere;

var startYheight = 20;
var endYheight = -20;
var startYheight = 50;
var endYheight = -50;

var multiplier;

var particleCount;
var mTime = 0;
var mDuration = 0.5;
var mTimeStep = (1/2000);
var S = 80; // particleDimension
var mDuration = 100;
var mTimeStep = 1/20;
var S = 100; // particleDimension
var progress = 0;

var pLight;
Expand Down Expand Up @@ -77,7 +79,7 @@ export default function RainParticles({enabled}) {

for (let x = -S; x < S; x += 1) {
for (let z = -S; z < S; z += 1) {
xzcoords.push(x / (S / 150) + 1, z / (S / 150) + 1);
xzcoords.push(x / (S / 200) + 2, z / (S / 200) + 2);
// this meanss between -S and S, the xz coordinates will

// x/4 + 1 , z/4 + 1 // iterate every z/4 + 1 (offset). // -19 .... 1, 5/4, 6/4, 7/4, 2, 9/4, 10/4, 11/4, 3 ... -19 (difference of 1/4) //
Expand All @@ -93,14 +95,14 @@ export default function RainParticles({enabled}) {
// prefabBufferGeometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(particleCount * prefabVerticiesLength),3)); // keep for consistency
prefabBufferGeometry.setAttribute('aPositionStart', new THREE.BufferAttribute(new Float32Array(multiplier *3 * prefabVerticiesLength),3));
prefabBufferGeometry.setAttribute('aPositionEnd', new THREE.BufferAttribute(new Float32Array(multiplier *3 * prefabVerticiesLength),3));
prefabBufferGeometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(multiplier *3 * prefabVerticiesLength),3));
// prefabBufferGeometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(multiplier *3 * prefabVerticiesLength),3));
prefabBufferGeometry.setAttribute("aOffset", new THREE.BufferAttribute(new Float32Array(multiplier * prefabVerticiesLength),1));

// var posBuffer = prefabBufferGeometry.getAttribute('position');
var aStartPosBuffer = prefabBufferGeometry.getAttribute('aPositionStart');
var aEndPosBuffer = prefabBufferGeometry.getAttribute('aPositionEnd');
var aOffset = prefabBufferGeometry.getAttribute('aOffset');
var aColor = prefabBufferGeometry.getAttribute('color');
// var aColor = prefabBufferGeometry.getAttribute('color');



Expand Down Expand Up @@ -147,29 +149,29 @@ export default function RainParticles({enabled}) {
// value: [0, 0, 0]
// }
// };
var color = new THREE.Color();
var h,s,l;

for(var i = 0, offset = 0; i < multiplier; i++) {
// h = i/particleCount * 50;
// // s = THREE.MathUtils.randFloatSpread(0.59, 0.61);
// l = THREE.MathUtils.randFloatSpread(0.7, 0.9);
// s = 0.8;
// l = 0.5;
h = 0.7;
l = 0.6;
s = 0.8;

color.setHSL(h,s,l);
// console.log("loop")
for(var j = 0; j < prefabGeometry.vertices.length; j++) {
aColor.array[offset++] = 0.5;
aColor.array[offset++] = 0;
aColor.array[offset++] = 0;
// console.log('loop');
}
// var color = new THREE.Color();
// var h,s,l;

// for(var i = 0, offset = 0; i < multiplier; i++) {
// // h = i/particleCount * 50;
// // // s = THREE.MathUtils.randFloatSpread(0.59, 0.61);
// // l = THREE.MathUtils.randFloatSpread(0.7, 0.9);
// // s = 0.8;
// // l = 0.5;
// h = 0.7;
// l = 0.6;
// s = 0.8;

// color.setHSL(h,s,l);
// // console.log("loop")
// for(var j = 0; j < prefabGeometry.vertices.length; j++) {
// aColor.array[offset++] = 0.5;
// aColor.array[offset++] = 0;
// aColor.array[offset++] = 0;
// // console.log('loop');
// }

}
// }

})

Expand All @@ -178,6 +180,7 @@ export default function RainParticles({enabled}) {

mParticleSystem = useRef();
pLight = useRef();
mSphere = useRef();
// particleDimension; // check
prefabGeometry = new THREE.OctahedronGeometry(1,0) // dont use buffer geometries
// since we want verticies
Expand Down Expand Up @@ -217,7 +220,7 @@ export default function RainParticles({enabled}) {
// console.log(newColor);
let color = [newColor.r, newColor.g, newColor.b]
pLight.current.color = newColor;

mSphere.current.material.emissive = newColor;
// mParticleSystem.current.material.uniforms['color'].value = color;
})

Expand All @@ -227,19 +230,35 @@ export default function RainParticles({enabled}) {
// mParticleSystem.current.material.uniforms['uProgress'] =
return (
<group>
<mesh geometry={new THREE.IcosahedronGeometry(1, 2)} material={new THREE.MeshStandardMaterial({
<mesh ref={mSphere} geometry={new THREE.IcosahedronGeometry(1, 2)} material={new THREE.MeshStandardMaterial({
flatShading: false,
roughness: 0.1,
metalness: 0.7
})} position={[0,0,0]}/>
<mesh geometry={new THREE.BoxGeometry(440, 440, 440)} material={new THREE.MeshPhongMaterial({color: "black", emissive: "black", side: THREE.BackSide })}/>
<mesh ref={mParticleSystem} args={[prefabBufferGeometry, RainMat]} castShadow={true}>
<mesh ref={mParticleSystem} args={[prefabBufferGeometry, RainMat2]} castShadow={true}>
</mesh>

{/* <ambientLight color={"white"} distance={0.1}/> */}
<ambientLight color={"white"} distance={0.1}/>

<spotLight position={[0,30,0]} intensity={0.1} distance={5} decay={Math.PI/2} />
<spotLight position={[0,-30,0]} intensity={0.1} distance={5} decay={Math.PI/2} />

<pointLight ref={pLight} color={"#EFEFEF"} position={[0,0,0]} intensity={20} distance={20} decay={Math.PI/2} />

<pointLight color={"#EFEFEF"} position={[30,0,0]} intensity={100} distance={20} decay={Math.PI/2} />
<pointLight color={"#EFEFEF"} position={[-30,0,0]} intensity={100} distance={20} decay={Math.PI/2} />
<pointLight color={"#EFEFEF"} position={[0,0,40]} intensity={200} distance={40} decay={Math.PI/2} />
<pointLight color={"#EFEFEF"} position={[0,0,-40]} intensity={200} distance={40} decay={Math.PI/2} />


{/* <pointLight ref={pLight} color={"#EFEFEF"} position={[10,0,10]} intensity={100} distance={20} decay={Math.PI/2} />
<pointLight ref={pLight} color={"#EFEFEF"} position={[-10,0,-10]} intensity={100} distance={20} decay={Math.PI/2} />
<pointLight ref={pLight} color={"#EFEFEF"} position={[-10,0,10]} intensity={100} distance={20} decay={Math.PI/2} />
<pointLight ref={pLight} color={"#EFEFEF"} position={[10,0,-10]} intensity={100} distance={20} decay={Math.PI/2} /> */}



<spotLight position={[0,30,30]} intensity={0.1} distance={5} decay={Math.PI/2} />
<pointLight ref={pLight} color={"black"} position={[0,25,0]} intensity={5} distance={200} decay={Math.PI/2} />

</group>
)
Expand Down
21 changes: 16 additions & 5 deletions src/components/shaders/RainParticleMaterial.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ const RainMat = new RainParticleMaterial({
uPosition: {type: 'v3', value: [0,0,0]},
uDuration: {type: 'f', value: 0.5},
uProgress: {type: 'f', value: 0},
color: {type: 'v3', value: [0.7,0.1,0]},
opacity: {type: 'f', value: 0.1}
color: {type: 'v3', value: [1,0,0]},
opacity: {type: 'f', value: 0}
},

emissive: "#212121",
Expand Down Expand Up @@ -104,7 +104,7 @@ const RainMat = new RainParticleMaterial({
'basePosition *= scale;',
'basePosition *= min(1.0, max(0.0, -10.0 + distance(vec3(uPosition.x, uPosition.y, newPosition.z), newPosition)));',
'vec3 finalPos = newPosition + basePosition;',
'gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(finalPos, 1.0);'
'gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(finalPos, 1.0);'
]

}, {
Expand All @@ -113,8 +113,19 @@ const RainMat = new RainParticleMaterial({
// shininess: 50
})

console.log(RainMat.fragmentShader);
console.log(THREE.ShaderLib['shadow'].fragmentShader);
// console.log(RainMat.fragmentShader);
// console.log(THREE.ShaderChunk['common'])
// console.log(THREE.ShaderChunk['packing'])
// console.log(THREE.ShaderChunk['bsdfs']);
// console.log(THREE.ShaderChunk['shadowmap_pars_fragment'])
// console.log(THREE.ShaderChunk['shadowmask_pars_fragment'])
// console.log(THREE.ShaderLib['shadow'].fragmentShader);
// console.log(THREE.ShaderChunk['tonemapping_fragment'])
// console.log(THREE.ShaderChunk['encodings_fragment'])
// console.log(THREE.ShaderChunk['fog_fragment'])



// const vertexShader = `
// attribute vec3 aPositionStart;
// attribute vec3 aPositionEnd;
Expand Down
121 changes: 121 additions & 0 deletions src/components/shaders/RainParticleMaterialTwo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import * as THREE from "three";
import particleMaterial from "./ParticleMaterial";

var ShaderChunk = {};

ShaderChunk['quat_from_axis_angle'] = "vec4 quatFromAxisAngle(vec3 axis, float angle) \n {\n float halfAngle = angle * 0.5; \n return vec4(axis.xyz * sin(halfAngle), cos(halfAngle));\n}\n";

ShaderChunk['rotate_vector'] = "vec3 rotateVector(vec4 q, vec3 v) \n { \n return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); \n} \n";

ShaderChunk['ease_in_ease_out_sin'] = "float easeInOutSin(float t) \n{ \n return (1.0 + sin(3.141618 * t - 3.141618/ 2.0)) / 2.0; \n} \n";

const vertex = `
attribute vec3 aPositionStart;
attribute vec3 aPositionEnd;
attribute float aOffset;

uniform vec3 uPosition;
uniform float uProgress;
uniform float mDuration;

vec4 quatFromAxisAngle(vec3 axis, float angle) {
float halfAngle = angle * 0.5;
return vec4(axis.xyz * sin(halfAngle), cos(halfAngle));
}

vec3 rotateVector(vec4 q, vec3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
}

float easeInOutSin(float t){
return (1.0 + sin(3.1416 * t - 3.1416 / 2.0)) / 2.0;
}

void main(){
float tProgress = easeInOutSin(min(1.0, max(0.0, (uProgress - aOffset))/mDuration));
vec3 newPosition = mix(aPositionStart, aPositionEnd, tProgress);

vec4 quatX = quatFromAxisAngle(vec3(1.0, 0.0, 0.0), 3.1416 / 2.0);
vec3 basePosition = rotateVector(quatX, position);

float scale = tProgress * 2.0 - 1.0;
scale = 1.0 - scale * scale;
basePosition *= scale;
basePosition *= min(1.0, max(0.0, -10.0 + distance(vec3(uPosition.x, uPosition.y, newPosition.z), newPosition)));
gl_Position = newPosition + basePosition;
}
`;

class RainParticleMaterialTwo extends THREE.MeshStandardMaterial {
constructor(params, uniformValues) {
super(params);

this.uniforms = params.uniforms;

this.vertexShader = params.vertexShader;
this.fragmentShader = null;
this.replacedShader = null;
// this.onBeforeCompile(s); // compilethe

}

// https://codepen.io/prisoner849/pen/BvxBPW

// why this is built in /// modify built in material's shaders before compilation
// https://github.com/mrdoob/three.js/issues/11475



// for this to work,
// you have to know which shaders to replace
onBeforeCompile(shader){

Object.assign(shader.uniforms, this.uniforms);

// retrieve the shader from existing vertex shader
const vertexShader = this.vertexShader.replace(/(\r\n|\n|\r)/gm, '');
// console.log('vertex shader :' + vertexShader)

// matching regex https://www.w3schools.com/jsref/jsref_obj_regexp.asp
// get the attribtues
const attributes = vertexShader.match(/.+?(?=void)/)[0];

// console.log('attributes ' + attributes)

// get the main function from the vertex function
const main = vertexShader.match(/main\(\){(.*?)}/)[1];
// console.log('main '+ main);

shader.vertexShader = `${attributes} \n ${shader.vertexShader}`;

// add the main function
shader.vertexShader = shader.vertexShader.replace(
'#include <begin_vertex>',
main.replace('gl_Position =', 'vec3 transformed =')
);

console.log(shader.fragmentShader);
}

}

var RainMat2 = new RainParticleMaterialTwo({
color: "#4EEE94",
// color: "#27408B",
emissive: "#212121",
flatShading: true,
roughness: 0.1,
metalness: 0.7,

uniforms: {
uPosition: {type: 'v3', value: [0,0,0]},
mDuration: {type: 'f', value: 100},
uProgress: {type: 'f', value: 0},
},

vertexShader: vertex

})


export default RainMat2;
6 changes: 3 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const CameraControls = (() => {
// const Camera = new THREE.PerspectiveCamera({fov: 60, position: [0, 600, 600], near: 0.1, far: 5000});
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 20;
camera.position.z = 120;
camera.fov = 40;
camera.near = 0.1;
camera.far = 10000;
Expand Down Expand Up @@ -62,8 +62,8 @@ function App() {

return (
<div className="App">
<button onClick={onSwitchToRainParticles}>Switch to Particle Stream</button>
<Canvas style={{height: 500, color: "FF0000"}}>
{/* <button onClick={onSwitchToRainParticles}>Switch to Particle Stream</button> */}
<Canvas style={{height: 750, color: "FF0000"}}>
<CameraControls/>
<scene name="Scene">

Expand Down