Three.js的ShaderMaterial光照效果不起作用。

4

我正在尝试使用Three.js ShaderMaterial并尝试实现照明。

我已经有了适用于r70版本的工作代码,但是相同的代码(稍作修改 - MAX_POINT_LIGHTS常量已更名为NUM_POINT_LIGHTS)不适用于r76版本。

通过WebGL Inspector中的跟踪,很明显没有将任何光数据发送到着色器。那么,是照明出了问题还是我需要设置其他东西才能使其工作?

使用r70(有效)

http://codepen.io/anon/pen/KzjXNr?editors=1010

片元着色器

uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
uniform vec3 pointLightColor[MAX_POINT_LIGHTS];
uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];
uniform float pointLightDistance[MAX_POINT_LIGHTS];

void main() {
  vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
  for(int l = 0; l < MAX_POINT_LIGHTS; l++) {
    vec3 lightDirection = normalize(vPos - pointLightPosition[l]);
    addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLightColor[l];
  }
  gl_FragColor = addedLights;
}

JavaScript - 使用UniformsUtils和UniformsLib设置Shadermaterial

var uniforms = THREE.UniformsUtils.merge([
    THREE.UniformsLib['lights'],
    { diffuse: { type: 'c', value: new THREE.Color(0xff00ff) } }
]);
var vertexShader = document.getElementById('vertexShader').text;
var fragmentShader = document.getElementById('fragmentShader').text;
material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: vertexShader,
      fragmentShader: fragmentShader,
      lights: true
    });

var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

使用r76(futzed)

http://codepen.io/anon/pen/ZWdXLZ?editors=1010

片元着色器
uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
uniform vec3 pointLightColor[NUM_POINT_LIGHTS];
uniform vec3 pointLightPosition[NUM_POINT_LIGHTS];
uniform float pointLightDistance[NUM_POINT_LIGHTS];

void main() {
  vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
  for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
    vec3 lightDirection = normalize(vPos - pointLightPosition[l]);
    addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLightColor[l];
  }
  gl_FragColor = addedLights;
}

JavaScript

未更改

1个回答

9

r74中(具体来说是在#7324中),轻便的制服已经被改成了struct。请注意,尽管将struct更改为发生在r74中,但以下内容适用于r75及更高版本。

给定每种灯光类型的单个struct数组。每个struct都有您需要的positioncolor属性。

片段着色器

uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;

struct PointLight {
  vec3 position;
  vec3 color;
};
uniform PointLight pointLights[ NUM_POINT_LIGHTS ];

void main() {
  vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
  for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
    vec3 adjustedLight = pointLights[l].position + cameraPosition;
    vec3 lightDirection = normalize(vPos - adjustedLight);
    addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLights[l].color;
  }
  gl_FragColor = addedLights;//mix(vec4(diffuse.x, diffuse.y, diffuse.z, 1.0), addedLights, addedLights);
}

请注意,光源位置现在相对于摄像机,因此您需要使用摄像机位置调整光源位置。

工作样例


谢谢。你从哪里得到这个信息的?我试着查看了更新日志但没有找到有用的东西。 - CarlBateman
我搜索了一个变更记录,其中修改了pointLightColor,然后找出它被包含在哪个发行版中。接着我查找了repo中应用这些属性的位置,并在lights_pars.glsl ShaderChunk中找到了它们。所以我进行了很多搜索 :) - Le Jeune Renard
既然cameraPosition是一个统一变量,那么它不是已经对两个着色器可用了吗?因此没有必要使用varying了,对吧? - CarlBateman
哇,那是很多搜索啊!不太直观或不言自明。 - CarlBateman
哦,你说的 cameraPosition 是对的!我以为我试过了,但显然没有。我会更新答案,去掉 varying。这需要花费很多时间来搜索。 - Le Jeune Renard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接