2021年04月24日 - WebVR・Three.js
RawShaderMaterialにライトを設定
「平面にシェーダを設定」に続き「three.jsのShaderMaterialでシーン内のライトを使用する」を参考に、RawShaderMaterialにライトを設定しました。※Three.jsはr127を使用しています。
RawShaderMaterialにライトを設定
● PointLightを設置
PlaneGeometryにRawShaderMaterialを設定したものにPointLightを設置します。
//ポイントライト const pointLight = new THREE.PointLight(0XFFFFFF,1,5,1); pointLight.position.set(0,0,2.5); scene.add(pointLight); //ヘルパー const pointLightHelper = new THREE.PointLightHelper(pointLight,1); scene.add(pointLightHelper);
● RawShaderMaterialを修正
uniformsにGLSLで使用する拡散色と放射色を追加して、RawShaderMaterialのライトプロパティをtrueにし、ライト情報をGLSLに送信します。
const uniforms = { time:{type:'f',value:0.0}, //拡散色 diffuse:{type:'c',value:new THREE.Color(0xFFFFFF)}, //放射色 emissive:{type:'c',value:new THREE.Color(0x000000)} }; const geometry = new THREE.PlaneGeometry(10,10,2,2); const material = new THREE.RawShaderMaterial({ vertexShader:vertexShader, fragmentShader:fragmentShader, //ライト情報 uniforms:THREE.UniformsUtils.merge([ THREE.UniformsLib.lights, uniforms, ]), //ライトプロパティ lights:true, side:THREE.DoubleSide, }); plane = new THREE.Mesh(geometry,material); scene.add(plane);
● glsl.js
script.jsとbasescene.jsは、上記以外は「平面にシェーダを設定」と同じです。
const vertexShader =` precision mediump float; attribute vec3 position; //normalの宣言 attribute vec3 normal; attribute vec2 uv; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; //normalMatrixの宣言 uniform mat3 normalMatrix; varying vec2 vUv; varying vec3 vViewPosition; varying vec3 vNormal; void main(void){ vUv = uv; //フラグメントシェーダにnormalを転送 vNormal = normalMatrix * normal; vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); //フラグメントシェーダにmvPositionを転送 vViewPosition = mvPosition.xyz; gl_Position = projectionMatrix * mvPosition; } `; const fragmentShader =` precision mediump float; uniform float time; //拡散色 uniform vec3 diffuse; //放射色 uniform vec3 emissive; uniform mat4 viewMatrix; varying vec2 vUv; varying vec3 vViewPosition; varying vec3 vNormal; //Three.jsのShaderChunk読み込み #include <common> #include <bsdfs> #include <lights_pars_begin> void main(void){ vec3 mvPosition = vViewPosition; vec3 transformedNormal = vNormal; //ランバート・シェーディング GeometricContext geometry; geometry.position = mvPosition.xyz; geometry.normal = normalize(transformedNormal); geometry.viewDir = (normalize(-mvPosition.xyz)); vec3 lightFront = vec3(0.0); vec3 indirectFront = vec3(0.0); IncidentLight directLight; float dotNL; vec3 directLightColor_Diffuse; //ポイントライト #if NUM_POINT_LIGHTS > 0 #pragma unroll_loop_start for (int i = 0; i < NUM_POINT_LIGHTS; i++) { getPointDirectLightIrradiance(pointLights[ i ], geometry, directLight); dotNL = dot(geometry.normal, directLight.direction); directLightColor_Diffuse = PI * directLight.color; lightFront += saturate(dotNL) * directLightColor_Diffuse; } #pragma unroll_loop_end #endif //スポットライト #if NUM_SPOT_LIGHTS > 0 #pragma unroll_loop_start for (int i = 0; i < NUM_SPOT_LIGHTS; i++) { getSpotDirectLightIrradiance(spotLights[ i ], geometry, directLight); dotNL = dot(geometry.normal, directLight.direction); directLightColor_Diffuse = PI * directLight.color; lightFront += saturate(dotNL) * directLightColor_Diffuse; } #pragma unroll_loop_end #endif //ディレクショナルライト #if NUM_DIR_LIGHTS > 0 #pragma unroll_loop_start for (int i = 0; i < NUM_DIR_LIGHTS; i++) { getDirectionalDirectLightIrradiance(directionalLights[ i ], geometry, directLight); dotNL = dot(geometry.normal, directLight.direction); directLightColor_Diffuse = PI * directLight.color; lightFront += saturate(dotNL) * directLightColor_Diffuse; } #pragma unroll_loop_end #endif //へミスフィアライト #if NUM_HEMI_LIGHTS > 0 #pragma unroll_loop_start for (int i = 0; i < NUM_HEMI_LIGHTS; i++) { indirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry ); } #pragma unroll_loop_end #endif vec4 diffuseColor = vec4(diffuse, 1.0); ReflectedLight reflectedLight = ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0)); vec3 totalEmissiveRadiance = emissive; reflectedLight.indirectDiffuse = getAmbientLightIrradiance(ambientLightColor); reflectedLight.indirectDiffuse += indirectFront; reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert(diffuseColor.rgb); reflectedLight.directDiffuse = lightFront; reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert(diffuseColor.rgb); vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; //ドットアニメーション vec2 p = (vUv * 2.0 - 1.0); p.x -= time * 0.00075; p *= 8.0; p = mod(p,3.0)-1.0; float l = length(p); l = step(0.0,1.0-l); gl_FragColor = vec4(vec3(l,l,0.0) * outgoingLight,diffuseColor.a); } `; export { vertexShader, fragmentShader };
完成したデモになります。RawShaderMaterialにライトを設定しました。