Добавление управления яркостью к фрагментному шейдеру
Если это просто простой контроль яркости, вы можете умножить цвет фрагмента на скаляр.
Пример фрагмента шейдера
uniform sampler2D texture;
uniform vec3 color;
uniform float brightness; // added uniform to control brightness
varying vec2 vUv;
void main(void) {
vec3 tColor = texture2D( texture, vUv ).rgb;
float a = (length(tColor - color) - 0.5) * 7.0;
gl_FragColor = vec4(tColor * brightness, a); // scale brightness of rgb channels
}
Затем в Javascript код для поддержки новой униформы
const BRIGHTNESS_MAX = 1; // default value. MAX brightness DO not change this
// DO NOT CHANGE this value to set upper limit
// Use the const LUX_MAX (see below) to set upper limit
const BRIGHTNESS_MIN = 0.7; // The darkest you want A value of 0 is black
// add brightness The same uniforms object as you
// got with uniforms = THREE.UniformsUtils.clone(THREE.UniformsLib["lights"]);
uniforms.brightness = {value: BRIGHTNESS_MAX}; // default to max
Для изменения значения униформы
uniforms.brightness.value = brightness; // set the new value
С Три документа
"Все значения униформ можно свободно изменять (например, цвета, текстуры, прозрачность и т. Д. c), значения отправляются в шейдер каждый кадр."
Так что это все, что нужно для добавления регулировки яркости.
Использование датчика окружающей среды
Я предполагаю, что у вас есть доступ к значению датчика. Датчик удерживает уровень освещенности как абсолютное значение LUX
10 темно ~ 707 нормально и 10000 плюс ярко.
Вам нужно будет откалибровать показания датчика, изменив значение LUX, соответствующее BRIGHTNESS_MAX
и установив BRIGHTNESS_MIN
на самое темное, каким вы хотите, чтобы изображение стало.
Поскольку диапазон масштабирования и динамический диапазон c для датчика освещенности и устройства отображения сильно различаются, следующая функция предполагает, что MAX_LUX и белый цвет на отображаемом изображении имеют ту же яркость
Следующая функция преобразует значение LUX
в значение яркости
const MAX_LUX = 5000; // This LUX value and above will set brightness to max
function LUX2Brightness(lux) {
if (lux >= MAX_LUX) { return BRIGHTNESS_MAX }
const MIN = (BRIGHTNESS_MIN ** 2.2) * MAX_LUX; // do not manually set this value
// Set BRIGHTNESS_MIN to control
// low light level
if (lux <= MIN) { return BRIGHTNESS_MIN }
return (lux ** (1 / 2.2)) / (MAX_LUX ** (1 / 2.2));
}
Для использования вышеуказанной функции с шейдером
// luminosity is value from ambient light sensor event
uniforms.brightness.value = LUX2Brightness(luminosity);
Предполагается, что вы устанавливаете MAX_LUX
на фактический выходной сигнал LUX полностью белого изображения (удачи с этим).
ВАЖНО !!
не является абсолютным решением уровней.
Человеческое зрение адаптивно. То, как вы откалибруете минимальное и максимальное значения, будет меняться в зависимости от того, как ваши глаза адаптировались к текущим уровням освещенности, текущей настройке яркости, цвета и т. Д. На устройстве, отображающем отображаемый контент, текущей настройке камеры, экспозиции, баланс белого (и так далее), ваши личные предпочтения художника.
Все эти вещи обычно устанавливаются автоматически, поэтому любая настройка, которая выглядит хорошо сейчас, может не соответствовать желаемой утром или при возвращении с кофе-брейка.
Весь код
Фрагментный шейдер
uniform sampler2D texture;
uniform vec3 color;
uniform float brightness;
varying vec2 vUv;
void main(void) {
vec3 tColor = texture2D( texture, vUv ).rgb;
float a = (length(tColor - color) - 0.5) * 7.0;
gl_FragColor = vec4(tColor * brightness, a);
}
JavaScript код настройки
const BRIGHTNESS_MAX = 1; // Don't change this value
const BRIGHTNESS_MIN = 0.7;
const MAX_LUX = 2000;
uniforms.brightness = {value: BRIGHTNESS_MAX};
function LUX2Brightness(lux) {
if (lux >= MAX_LUX) { return BRIGHTNESS_MAX }
const MIN = (BRIGHTNESS_MIN ** 2.2) * MAX_LUX;
if (lux <= MIN) { return BRIGHTNESS_MIN }
return (lux ** (1 / 2.2)) / (MAX_LUX ** (1 / 2.2));
}
Показание датчика
Вставьте следующую строку в событие датчика. Например, "devicelight"
слушатель событий.
uniforms.brightness.value = LUX2Brightness(event.value);