У меня есть очень подробная текстура (с информацией о ложном цвете, которую я визуализирую с помощью поиска ложного цвета во фрагментном шейдере). Моя проблема в том, что иногда пользователь отдаляется от этой текстуры, и мелкие детали теряются: тонкие линии в текстуре не видны. Я хотел бы изменить свой код, чтобы эти строки выскочили.
Я думаю, что я могу запустить быстрый фильтр по соседним текстам и выбрать самое большое/наименьшее/самое интересное значение для рендеринга. Что я не уверен, как это сделать, так это узнать, нужно ли (и сколько) это делать. Когда пользователь увеличен в треугольнике, мне нужен стандартный поиск. При уменьшении масштаба один пиксель на экране сопоставляется многим пикселям текстуры.
Как мне получить оценку этого? Я делаю это как с ортогональными, так и с перспективными камерами.
Я думаю, что я мог бы каким-то образом использовать вершинный шейдер, чтобы получить оценку того, насколько велик один экранный пиксель в пространстве UV, и передать это как изменение фрагментному шейдеру, но я все еще не имею четкого представления ни о преобразованиях. и места достаточно, чтобы понять идею.
Мой текущий вершинный шейдер довольно прост:
varying vec2 vUv;
varying vec3 vPosition;
varying vec3 vNormal;
varying vec3 vViewDirection;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vPosition = (modelMatrix *
vec4(position,1.0)).xyz;
gl_Position = projectionMatrix * mvPosition;
vec3 transformedNormal = normalMatrix * vec3( normal );
vNormal = normalize( transformedNormal );
vViewDirection = normalize(mvPosition.xyz);
}
Как мне получить что-то вроде vDeltaUV, которое дает расстояние между пикселями экрана в единицах UV?
Ограничения: я работаю в WebGL внутри three.js.
Вот пример одного изображения, где пользователь приблизил перспективу к моей текстуре:

Вот тот же пример, но в уменьшенном масштабе; особенность выше — едва заметная диагональная линия рядом с центром (см. координаты, чтобы получить представление о масштабе). Я хочу, чтобы эта строка отображалась путем рендеринга всех пикселей с самым красным цветом соответствующего массива текстов.
Дополнение (относительно комментария ЖЖ)... Нет, я не думаю, что мипмэппинг сделает то, что я хочу, по двум причинам.
Во-первых, я на самом деле не накладываю текстуру; то есть я делаю что-то вроде этого:
gl_FragColor = texture2D(mappingtexture, texture2d(vec2(inputtexture.g,inputtexture.r))
Пользователь динамически создает текстуру отображения, что позволяет мне изменять карту искусственных цветов в реальном времени. Я думаю, что это действительно очень элегантное решение для моего приложения.
Во-вторых, я не хочу рисовать СРЕДНЕЕ значение соседних пикселей (т. е. сглаживание), я хочу максимальное ЭКСТРЕМАЛЬНОЕ значение соседних пикселей (т. е. что-то более похожее на поиск краев). «Экстремальность» в данном случае технически определяется моей кодировкой значений цвета g/r во входной текстуре.
Решение: Благодаря ответу ниже у меня теперь есть рабочее решение.
В моем коде javascript мне пришлось добавить:
extensions: {derivatives: true}
к моему объявлению ShaderMaterial. Затем в моем фрагментном шейдере:
float dUdx = dFdx(vUv.x); // Difference in U between this pixel and the one to the right.
float dUdy = dFdy(vUv.x); // Difference in U between this pixel and the one to the above.
float dU = sqrt(dUdx*dUdx + dUdy*dUdy);
float pixel_ratio = (dU*(uInputTextureResolution));
Это позволяет мне делать такие вещи:
float x = ... the u coordinate in pixels in the input texture
float y = ... the v coordinate in pixels in the input texture
vec4 inc = get_encoded_adc_value(x,y);
// Extremum mapping:
if (pixel_ratio>2.0) {
inc = most_extreme_value(inc, get_encoded_adc_value(x+1.0, y));
}
if (pixel_ratio>3.0) {
inc = most_extreme_value(inc, get_encoded_adc_value(x-1.0, y));
}
Эффект слабенький, но точно есть! Линии выскакивают намного четче.
Спасибо за помощь!





Вы не можете сделать это в вершинном шейдере, так как это этап предварительной растеризации, следовательно, выходное разрешение не зависит, но во фрагментном шейдере вы можете использовать dFdx, dFdyи ширина с помощью расширения GL_OES_standard_derivatives (которое доступно практически везде) для оценки площади выборки.
Если вы не обновляете текстуру в реальном времени, более простым и эффективным решением будет создание для нее пользовательских мип-уровней на ЦП.
Графический процессор уже делает это за вас, вот что такое мип-маппинг, выбирая мип-уровень, наиболее близкий к соотношению тексель/экран-пиксель 1:1. Использование вашего подхода (например, не использование предложенного метода создания пользовательских мип-карт) быстрее только в том случае, если ваша текстура генерируется каждый кадр, а ваши уровни масштабирования довольно малы (например, минимизация 2-4), в любом другом случае мип-карты будут быть намного быстрее, и если процессор станет узким местом, вы также можете перенести эту нагрузку на графический процессор.
@LJ Я так не думаю; добавление выше
Это выглядит интересно. Я посмотрю, есть ли какие-либо учебники по этим функциям. Текстуры действительно генерируются динамически, поэтому в приложении реального времени это занимает много времени. Даже если бы они у меня были, мне все равно нужен был бы надежный способ выбора текстуры для использования.