threejs实现Lambert光照模型

本文章不做模型讲解,只分享代码。
在线地址 https://codepen.io/qinwei-liao/pen/BaqVegP
请添加图片描述
index.html

<canvas id="renderer"></canvas>


<script type="importmap">
{
  "imports":{
      "three":"https://cdn.jsdelivr.net/npm/three@0.152.2/build/three.module.min.js"
  }
  
}
</script>
<script src="./index.js" type="module"></script>

index.js


import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.152.2/build/three.module.min.js";
import {OrbitControls} from "https://cdn.jsdelivr.net/npm/three@0.152.2/examples/jsm/controls/OrbitControls.js"
import GUI from "https://cdn.jsdelivr.net/npm/lil-gui@0.18.1/dist/lil-gui.esm.min.js"

const gui = new GUI;

const vertexShader = `
precision highp float;
uniform vec3 lightPosition;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

attribute vec3 position;
attribute vec3 normal;

varying vec3 vNormal;

void main() {
	vNormal = normal;

	gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);
}
`
// 模拟的是方向光,没有计算光源的衰减
const fragmentShader = `
precision highp float;
uniform vec3 lightDirection;
uniform vec3 lightColor;
uniform float kd;
uniform bool halfLambert;

varying vec3 vNormal;

void main() {
	vec3 color = vec3(.5, .5, 0);
	vec3 diffuse = kd * color * lightColor * (clamp(dot(vNormal, lightDirection), 0., 1.));

	if(halfLambert) {
		diffuse = kd * color * lightColor * (clamp(dot(vNormal, lightDirection) * .5, 0., 1.) + .5);
	}

	gl_FragColor = vec4(diffuse, 1);
}
`



const canvas = document.querySelector("#renderer")

const renderer = new THREE.WebGLRenderer({ canvas, logarithmicDepthBuffer: false });
const fov = 75;
const aspect = 2;  // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 4; 

const controls = new OrbitControls(camera, canvas)

const scene = new THREE.Scene();

const intensity = 2;
const color = 0xFFFFFF;
const light = new THREE.DirectionalLight(color, intensity);
scene.add(light);


light.rotation.set(0,1.3,-1.1)
const uniforms = {
  lightDirection:{value:light.getWorldDirection(new THREE.Vector3)},
  lightColor:{value:light.color},
  kd:{value:1},
  halfLambert:{value:false}
}

const geometry = new THREE.TorusKnotGeometry(1, .5, 100, 16)
const material = new THREE.RawShaderMaterial({
  uniforms,
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
})
const change = (v)=>{
  material.uniforms.lightDirection.value = light.getWorldDirection(new THREE.Vector3)
}

gui.add(light.rotation,"x").step(.1).onChange(change)
gui.add(light.rotation,"y").step(.1).onChange(change)
gui.add(light.rotation,"z").step(.1).onChange(change)
gui.add({kd:1},"kd",0,1,.1).onChange((v)=>{

  material.uniforms.kd.value = v
})
gui.add({halfLambert:false},"halfLambert").onChange(v=>{
  material.uniforms.halfLambert.value = v
})
scene.add(new THREE.Mesh(geometry, material))




function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const needResize = canvas.width !== window.innerWidth || canvas.height !== window.innerHeight;
  if (needResize) {
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    renderer.setSize(window.innerWidth, window.innerHeight, false);
  }
  return needResize;
}

let then = 0;

function render(now) {

  now *= 0.001;  // convert to 
  const deltaTime = now - then;
  then = now;

  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

  renderer.render(scene, camera)
  
  requestAnimationFrame(render);
}

requestAnimationFrame(render);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值