代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>08.Materials(MeshLambertMaterial)</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script id="vertexShader" type="x-shader/x-vertex">
uniform vec3 camera;
uniform vec3 light;
uniform mat4 normalMatrixOfWorld;
out vec3 varNormal;
out vec3 varEyeDir;
out vec3 lightDirection;
void main()
{
// vertex position (in world space)
vec4 worldPosition=modelMatrix * vec4( position, 1.0 );
// vertex normal
varNormal = (normalMatrixOfWorld*vec4(normal,0.0)).xyz;
varEyeDir = normalize(camera-worldPosition.xyz);
lightDirection=normalize(light-worldPosition.xyz);
gl_Position = projectionMatrix * viewMatrix*worldPosition;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
in vec3 lightDirection;
in vec3 varNormal;
in vec3 varEyeDir;
uniform vec3 lightColor;
layout(location=0) out vec4 color;
void main()
{
// set important material values
float roughnessValue = 0.3; // 0 : smooth, 1: rough
float F0 = 0.8; // fresnel reflectance at normal incidence
float k = 0.2; // fraction of diffuse reflection (specular reflection = 1 - k)
// interpolating normals will change the length of the normal, so renormalize the normal.
vec3 normal = normalize(varNormal);
// do the lighting calculation for each fragment.
float NdotL = max(dot(normal, lightDirection), 0.0);
float specular = 0.0;
if(NdotL > 0.0)
{
vec3 eyeDir = normalize(varEyeDir);
// calculate intermediary values
vec3 halfVector = normalize(lightDirection + eyeDir);
float NdotH = max(dot(normal, halfVector), 0.0);
float NdotV = max(dot(normal, eyeDir), 0.0); // note: this could also be NdotL, which is the same value
float VdotH = max(dot(eyeDir, halfVector), 0.0);
float mSquared = roughnessValue * roughnessValue;
// geometric attenuation
float NH2 = 2.0 * NdotH;
float g1 = (NH2 * NdotV) / VdotH;
float g2 = (NH2 * NdotL) / VdotH;
float geoAtt = min(1.0, min(g1, g2));
// roughness (or: microfacet distribution function)
// beckmann distribution function
float r1 = 1.0 / ( 4.0 * mSquared * pow(NdotH, 4.0));
float r2 = (NdotH * NdotH - 1.0) / (mSquared * NdotH * NdotH);
float roughness = r1 * exp(r2);
// fresnel
// Schlick approximation
float fresnel = pow(1.0 - VdotH, 5.0);
fresnel *= (1.0 - F0);
fresnel += F0;
specular = (fresnel * geoAtt * roughness) / (NdotV * NdotL * 3.14);
}
vec3 finalValue = lightColor * NdotL * (k + specular * (1.0 - k));
color = vec4(finalValue, 1.0);
}
</script>
<script type="module">
import * as THREE from '/build/three.module.js';
import { PointerLockControls } from '/jsm/controls/PointerLockControls.js';
//生成场景
const scene = new THREE.Scene();
//设置光照
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
const pointLight = new THREE.PointLight(0xFFFFFF, 1, 100);
pointLight.position.set(0, 0, 10);
scene.add(pointLight);
//设置相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
//设置渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
//renderer.setClearColor(0xFFFFFF);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//生成模型
const geometry = new THREE.BoxGeometry();
const group = new THREE.Group()
const material = new THREE.ShaderMaterial({
uniforms: {
camera: { value: camera.position },
light: { value: pointLight.position },
lightColor:{value:new THREE.Vector3(0.9, 0.1, 0.1) },
normalMatrixOfWorld: {value:new THREE.Matrix4()}
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent,
glslVersion:THREE.GLSL3
});
const cube = new THREE.Mesh(geometry, material);
const wireframeMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000, wireframe: true });
const cubeWireframe = new THREE.Mesh(geometry, wireframeMaterial);
//设置场景
group.add(cube)
group.add(cubeWireframe)
scene.add(group);
scene.add(camera)
const controls = new PointerLockControls(camera, document.body);
//点击屏幕触发lock
document.onclick = function (event) {
controls.lock();
}
//用键盘控制移动
document.onkeydown = function (event) {
switch (event.key) { // 获取当前按下键盘键的编码
//wsad移动
case 'w':
controls.moveForward(0.5);
break;
case 's':
controls.moveForward(-0.5);
break;
case 'a':
controls.moveRight(- 0.5);
break;
case 'd':
controls.moveRight(0.5);
break;
}
}
function animate() {
group.rotation.x+=0.01;
renderer.render(scene, camera);
requestAnimationFrame(animate);
var modelMatrix=cube.matrixWorld.clone();
const normalMatrixOfWorld=modelMatrix.invert().transpose();
material.uniforms.camera.value = camera.position
material.uniforms.normalMatrixOfWorld.value = normalMatrixOfWorld
}
//开始动画
animate()
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。