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にライトを設定しました。

