我在写一个交互式程序,用户可以在其中更改显示的材质,光线和对象。我写了所有HTML表格和JavaScript事件来处理用户交互的部分,我认为这很好,所以我只在这里发布相关部分,我将添加一个链接到整个文件。光线运动不起作用
在这里,我创建场景,对象,光和呈现功能:
var scene= new THREE.Scene();
var camera= new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
var renderer= new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.z=5;
var geometry= new THREE.SphereGeometry(1,15,15);
var material= new THREE.MeshLambertMaterial({color:0xffffff, ambient:0xffffff, emissive:0xffffff});
var object= new THREE.Mesh(geometry,material);
material.name= "lambert";
object.name= "sphere";
scene.add(object);
var light= new THREE.PointLight(0xffffff);
light.position.set(0,0,20);
light.name= "point";
scene.add(light);
var render= function() {
requestAnimationFrame(render);
renderer.render(scene,camera);
}
render();
然后每个用户,通过按钮,改变一个参数的时间,我使用这些函数来改变材料光特性:
function changeLightParameters() {
var lightParameters= getLightParameters();
if(lightParameters== null) {
alert("Invalid values");
return;
}
if(light.name!= lightParameters.type) {
scene.remove(light);
if(lightParameters.type== "spot") {
light= new THREE.SpotLight(lightParameters.color);
}
else if(lightParameters.type== "point") {
light= new THREE.PointLight(lightParameters.color);
}
else if(lightParameters.type== "ambient") {
light= new THREE.AmbientLight(lightParameters.color);
}
else if(lightParameters.type== "area") {
light= new THREE.AreaLight(lightParameters.color);
}
else if(lightParameters.type== "directional") {
light= new THREE.DirectionalLight(lightParameters.color);
}
light.position.set(lightParameters.position.x, lightParameters.position.y, lightParameters.position.z);
light.name= lightParameters.name;
scene.add(light);
}
else {
light.position= lightParameters.position;
light.color= new THREE.Color(lightParameters.color);
}
}
function changeMaterialParameters() {
var materialParameters= getMaterialParameters();
if(materialParameters== null) {
alert("Invalid values");
return;
}
if(materialParameters.type!= material.name) {
scene.remove(object);
if(materialParameters.type== "lambert") {
material= new THREE.MeshLambertMaterial({
color:materialParameters.diffuse,
ambient:materialParameters.ambient,
emissive:materialParameters.emissive });
}
else if(materialParameters.type== "normal") {
material= new THREE.MeshNormalMaterial();
}
else if(materialParameters.type== "phong") {
material= new THREE.MeshPhongMaterial({
color:materialParameters.diffuse,
ambient:materialParameters.ambient,
emissive:materialParameters.emissive,
specular:materialParameters.specular,
shininess:materialParameters.shininess });
}
material.name= materialParameters.type;
object= new THREE.Mesh(geometry,material);
scene.add(object);
}
else {
material.color= new THREE.Color(materialParameters.diffuse);
material.ambient= new THREE.Color(materialParameters.ambient);
material.emissive= new THREE.Color(materialParameters.emissive);
material.specular= new THREE.Color(materialParameters.specular);
material.shininess= new THREE.Color(materialParameters.shininess);
material.needsUpdate= true;
}
}
在这些功能中我使用getMaterialParameters()
和getLightParameters()
得到包含一些文本字段来处理值的两个表,将所有的参数。我已经测试过这些函数,它们都可以工作,所以没必要看代码。这些函数返回一个对象,具有这样的结构:
Light : color (number)
position (THREE.Vector3)
type (string, possibile values "ambient", "point", "spot", "point", "directional")
Material: diffuse (number)
ambient (number)
emissive (number)
specular (number)
shininess (number)
type (string, possible values "phong", "normal", "lambert")
一旦拿到的材料特性,如果材料类型发生了变化,我创建了一个新材料从头开始,如果而不只是它的属性被更改更新它。灯光相同。
问题是,对象似乎对灯光变化没有反应:如果我改变灯光位置/颜色,什么都不会发生。我也可以将光线的z设置为-1000,即没有任何变化。 Phong模型对我来说看起来并不正确,但是物体并不像它应该发光一样。例如:
的参数是:蓬材料,反光100,漫射光0x00abb1,发射光0x006063,镜面光0xa9fcff,反光光在位置(20,20,200)100白点的光。如果我将光移动到(0,0,0),那么球看起来是一样的。这看起来应该不现实,我认为我做错了什么。
请告诉我,如果我需要添加更多的细节,完整的代码是在这里:http://pastebin.com/3uwgwvfE
更新
我发现,问题在于这样的事实,我不能够添加场景已经初始化时的新灯。我做了一个新的程序,这是一个如何重现问题的例子:我开始使用射灯,然后当用户点击画布时,我从场景中移除光线,并添加一个新光线(方向)。但它不起作用:没有照明,我只看到环境组件。代码在这里:http://pastebin.com/BVU0dPi3
参见维基文章[如何更新WebGLRenderer事情(https://github.com/mrdoob/three.js/wiki/Updates)。同时删除所有'needsUpdate'标志并将它们仅添加回需要的地方。避免'material.color = new THREE.Color()';改为使用'material.color.copy(color)'。 “闪亮”不是“THREE.Color”。 – WestLangley
它说:“这些变化需要建立新的着色器程序,你需要将material.needsUpdate标志设置为true”。所以当我将灯光设置为material.needsUpdate为true时,我需要做什么?它不起作用(仍然是同样的问题)。 –
如果您只是移动灯光,则不需要设置'material.needsUpdate = true'。设置'material.emissive = 0x000000'。设置'material.specular = 0x050505'。将'material.ambient'设置为与'material.color'相同的值。 – WestLangley