雑に書きます。
1.実装したいもの
こちらが今回react-three-fiberを使って実装するものです...
https://threejs.org/examples/?q=shader#webgl_shader
shaderを読み込むだけですねー
2.ディレクトリ構成&コード
ディレクトリ構成を関係ありそうなところだけ書いておきます。
root/
├ build/
├ public/
└ src/
├ components/
│ └ Shader.js
│ └ PurpleShader.js
├ App.js
└ index.js
package.json(一部)
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-three-fiber": "4.0.7",
"three": "^0.115.0"
src/components/Shader.js
import React, { Suspense, useRef } from "react"
import { Canvas, useFrame } from "react-three-fiber"
import { PurpleShader } from "./PurpleShader"
function Plane() {
const ref = useRef()
useFrame(({ clock }) => {
const time = clock.getElapsedTime()
ref.current.material.uniforms.time.value = time;
})
return (
<mesh ref={ref}>
<planeBufferGeometry attach="geometry" args={[2,2,2]} />
<shaderMaterial
attach="material"
args={[PurpleShader]}
/>
</mesh>
)
}
const Shader = () => {
return (
<Canvas camera={{ position: [- 1, 1, 1], near: 0.01, far: 10000, fov: 60 }}>
<ambientLight intensity={0.85} />
<Suspense fallback={null}>
<Plane />
</Suspense>
</Canvas>
)
}
export { Shader };
src/components/PurpleShader.js
const PurpleShader = {
uniforms: {
time: { type: "f", value: 1.0 }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( position, 1.0 );
}
`,
fragmentShader: `
varying vec2 vUv;
uniform float time;
void main() {
vec2 p = - 1.0 + 2.0 * vUv;
float a = time * 40.0;
float d, e, f, g = 1.0 / 40.0 ,h ,i ,r ,q;
e = 400.0 * ( p.x * 0.5 + 0.5 );
f = 400.0 * ( p.y * 0.5 + 0.5 );
i = 200.0 + sin( e * g + a / 150.0 ) * 20.0;
d = 200.0 + cos( f * g / 2.0 ) * 18.0 + cos( e * g ) * 7.0;
r = sqrt( pow( abs( i - e ), 2.0 ) + pow( abs( d - f ), 2.0 ) );
q = f / r;
e = ( r * cos( q ) ) - a / 2.0;
f = ( r * sin( q ) ) - a / 2.0;
d = sin( e * g ) * 176.0 + sin( e * g ) * 164.0 + r;
h = ( ( f + d ) + a / 2.0 ) * g;
i = cos( h + r * p.x / 1.3 ) * ( e + e + a ) + cos( q * g * 6.0 ) * ( r + h / 3.0 );
h = sin( f * g ) * 144.0 - sin( e * g ) * 212.0 * p.x;
h = ( h + ( f - e ) * q + sin( r - ( a + h ) / 7.0 ) * 10.0 + i / 4.0 ) * g;
i += cos( h * 2.3 * sin( a / 350.0 - q ) ) * 184.0 * sin( q - ( r * 4.3 + a / 12.0 ) * g ) + tan( r * g + h ) * 184.0 * cos( r * g + h );
i = mod( i / 5.6, 256.0 ) / 64.0;
if ( i < 0.0 ) i += 4.0;
if ( i >= 2.0 ) i = 4.0 - i;
d = r / 350.0;
d += sin( d * d * 8.0 ) * 0.52;
f = ( sin( a * g ) + 1.0 ) / 2.0;
gl_FragColor = vec4( vec3( f * i / 1.6, i / 2.0 + d / 13.0, i ) * d * p.x + vec3( i / 1.3 + d / 8.0, i / 2.0 + d / 18.0, i ) * d * ( 1.0 - p.x ), 1.0 );
}
`
}
export { PurpleShader }
src/components/App.js
import React from 'react'
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'
//import './css/index.css'
import { Home } from './components/Home'
import { Shader } from './components/Shader'
const App = () => {
return (
<BrowserRouter>
<div>{document.title}</div>
<Switch>
<Route exact path='/'><Home /></Route>
<Route path='/1'><Shader /></Route>
</Switch>
<Link to='/'>ホーム画面へ</Link>
<Link to='/1'> シェーダー</Link>
</BrowserRouter>
)
}
export default App;
3.参考にしたもの
https://codesandbox.io/s/t9-react-three-fiber-shadermaterial-1g4qq?file=/src/index.js
https://threejs.org/examples/?q=shader#webgl_shader
4.感想
shaderMaterilaはどう使うのかなーと思って、やってみました。
5.Three.jsサンプル実装シリーズ
TextureLoader
・https://qiita.com/drafts/56d211a47d139e424e5b/