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   8  

1 ответ:

Я думаю, что после определенного порога MATLAB переключилась на рендеринг OpenGL для повышения производительности (аппаратное ускорение). К сожалению, не обошлось и без багов.

Я не рассматривал подробно, как вы строите треугольные грани (может возникнуть проблема с тем, как они упорядочены), но простое решение-это явно задать метод визуализации. Просто добавьте следующий вызов в конце функции:

set(gcf, 'Renderer','zbuffer')

EDIT

Обходной путь выше должен делай просто отлично. Теперь реальная проблема заключается не в багги OpenGL, а в документированном ограничении:

OpenGL не выполняет интерполяцию цветовой карты. Если вы создаете поверхность или патч с использованием индексированного цвета и интерполированной окраски грани или края, OpenGL интерполирует цвета через цветовой куб RGB вместо через цветовую карту.

Обратите внимание, что вызов TRIMESH эквивалентен следующему:
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

рендерер opengl

Z-Буфер

zbuffer renderer