Matlab останавливает интерполяцию цветов на сетке правильно, если она больше 120 треугольников
Я пытаюсь нарисовать большую сетку в Matlab, используя функцию trimesh
, с координатами z вершин, контролирующих цвет. К сожалению, Matlab перестает корректно интерполировать цвета, когда размер сетки превышает 120 треугольников. Вот изображение, демонстрирующее проблему, с 120 треугольниками слева и 121 треугольником справа.
Как вы можете видеть, для больших сеток Matlab интерполирует непосредственно от цвета одной вершины к цвету другой. остальные вершины. Возможно, это было сделано из соображений производительности, но я пытаюсь создать красивые картинки для своей диссертации, и мне все равно, сколько времени займет их вычисление. Есть ли способ отключить это приближение?
Вот код для создания изображения:
function test(n)
%%% Generate a mesh with n triangles.
oneTriVerts = [0 0 0;
1 0 0;
1 0 1];
offset = [0 (1/n) 0;
0 (1/n) 0;
0 (1/n) 0];
verts = zeros(0,3);
tris = zeros(0,3);
for i = 0:(n-1)
verts = [verts; (oneTriVerts + i * offset)];
tris = [tris; i*3+1, i*3+2, i*3+3];
end
%%% Draw the mesh, with color corresponding to the z coordinate.
trimesh(tris, verts(:,1), verts(:,2), verts(:,3), verts(:,3));
title(sprintf('n = %d', n))
shading interp
axis equal
1 ответ:
Я думаю, что после определенного порога MATLAB переключилась на рендеринг OpenGL для повышения производительности (аппаратное ускорение). К сожалению, не обошлось и без багов.
Я не рассматривал подробно, как вы строите треугольные грани (может возникнуть проблема с тем, как они упорядочены), но простое решение-это явно задать метод визуализации. Просто добавьте следующий вызов в конце функции:
set(gcf, 'Renderer','zbuffer')
EDIT
Обходной путь выше должен делай просто отлично. Теперь реальная проблема заключается не в багги OpenGL, а в документированном ограничении:
Обратите внимание, что вызов TRIMESH эквивалентен следующему:OpenGL не выполняет интерполяцию цветовой карты. Если вы создаете поверхность или патч с использованием индексированного цвета и интерполированной окраски грани или края, OpenGL интерполирует цвета через цветовой куб RGB вместо через цветовую карту.
patch('Faces',tris, 'Vertices',verts, 'FaceVertexCData',verts(:,3), ... 'EdgeColor','none', 'FaceColor','interp', 'CDataMapping','scaled')
Таким образом, для каждой вершины вы задаете цвет, равный к его z-координате (у вас есть только два уникальных значения, либо 0, либо 1). Это интерпретируется как индексированный цвет в цветовой карте текущего рисунка с помощью масштабированного отображения (по умолчанию используется цветовая карта jet). Таким образом, два цвета в конечном итоге:
clr = jet(64); % default colormap clr(1,:) % blueish color [0 0 0.5625] mapped from 0 clr(end,:) % reddish color [0.5 0 0] mapped from 1
К сожалению, как поясняется в приведенной выше цитате, OpenGL renderer не будет выполнять интерполяцию с использованием цветов палитры colormap, а выполнит интерполяцию в цветовом пространстве RGB между двумя цветами выше. Таким образом мы получаем сине-красный градиент ты же видел.
Таким образом, ваш единственный вариант-использовать один из двух других рендеров,zbuffer
являющийся лучшим методом здесь.
Вот код, чтобы увидеть разницу между двумя методами визуализации:
% plot patch clf patch('Faces',tris, 'Vertices',verts, 'FaceVertexCData',verts(:,3), ... 'EdgeColor','none', 'FaceColor','interp', 'CDataMapping','scaled') view(3) axis vis3d colorbar % choose one of the two set(gcf, 'Renderer','opengl') set(gcf, 'Renderer','zbuffer')
OpenGL
Z-Буфер