Я пытаюсь установить дневной / ночной цикл с направленным светом в модели Земли с помощью пользовательских шейдеров.Ночные и дневные карты, а также свет в порядке, пока я не касаюсь камеры, т. Е. Земля вращается, когда источник света остается неподвижным, а ночи и дни обновляются корректно.Однако, когда я поворачиваю камеру с помощью мыши, кажется, что свет следует за камерой, поэтому вы всегда видите освещенную часть Земли.
Вот как я устанавливаю источник света:
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5,3,5);
scene.add(light);
Вот как я передаю параметры шейдеру:
uniforms_earth = {
sunPosition: { type: "v3", value: light.position },
dayTexture: { type: "t", value: THREE.ImageUtils.loadTexture( "daymap.jpg" ) },
nightTexture: { type: "t", value: THREE.ImageUtils.loadTexture( "images/nightmap.jpg" ) }
};
Это вершинный шейдер:
varying vec2 v_Uv;
varying vec3 v_Normal;
uniform vec3 sunPosition;
varying vec3 v_vertToLight;
void main() {
v_Uv = uv;
v_Normal = normalMatrix * normal;
vec4 worldPosition = modelViewMatrix * vec4(position, 1.0);
v_vertToLight = normalize(sunPosition - worldPosition.xyz);
gl_Position = projectionMatrix * worldPosition;
}
А вот фрагментный шейдер:
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
varying vec2 v_Uv;
varying vec3 v_Normal;
varying vec3 v_vertToLight;
void main( void ) {
vec3 dayColor = texture2D(dayTexture, v_Uv).rgb;
vec3 nightColor = texture2D(nightTexture, v_Uv).rgb;
vec3 fragToLight = normalize(v_vertToLight);
float cosineAngleSunToNormal = dot(normalize(v_Normal), fragToLight);
cosineAngleSunToNormal = clamp(cosineAngleSunToNormal * 10.0, -1.0, 1.0);
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
vec3 color = mix(nightColor, dayColor, mixAmount);
gl_FragColor = vec4( color, 1.0 );
}
Наконец, я использую ТРИ библиотеки для элементов управления камерой:
var controls = new THREE.TrackballControls(camera);
И я обновляю вращение Земли внутри функции рендеринга следующим образом:
function render() {
controls.update();
earth.rotation.y += rotation_speed;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
У меня уже естьпопытался изменить способ вычисления v_vertToLight
так, чтобы и вершина, и положение источника света находились в одном мире с:
v_vertToLight = normalize((modelViewMatrix*vec4(sunPosition, 1.0)).xyz - worldPosition.xyz);
. Это останавливает движение света при смене камеры, но затемтень ночного дня всегда остается в том же месте, в котором свет начинает вращаться вместе с самой Землей.
Я чувствую, что близок к решению этого вопроса, поэтому любая подсказка или помощь будут высоко оценены.Спасибо за ваше время.
Цитата