Pull to refresh

Comments 26

Нету «SMOOTH» ни для линий, ни для полигонов. Анитиалиасинг в WebGL встроен по умолчанию(можно отключать), что-то вроде FXAA, но работает только если если рисовать напрямую в канвас. В моих примерах рендер работает сначала в фреймбуфер, потом готовую картинку отправляет уже на канвас(удобно для постобработки). В этом случае встроенный антиалиасинг не работает.
Ага, я понял. Но glLineWidth то там есть… Можно попробовать задать толщину и отрисовать с альфаблендингом.
Тоже столкнулись с этой проблемой. Только вот причина, по которой толщина линий не поддерживается, на сколько я понимаю, гораздо интереснее. Формально, в WebGL она вроде как есть. Но большинство браузеров под Win эмулируют WebGL, используя DirectX через прокладку ANGLE. И где-то по пути эта толщина теряется. Если принудительно переключить браузер на работу с OpenGL вместо DirectX, то всё становится нормально. Ну и в Linux браузерах тоже вроде как всё хорошо, так как там нет DirectX :-).

PS: Острые углы я срезал немного по-другому:
как-то так


Мне такой вариант показался более симпатичным.
Плюс, его можно прокачать до аккуратных скруглённых углов, если добавить немного «магии» в пиксельный шейдер.
Отличный вариант! Этот вариант мне тоже кажется более симпатичным, и даже скорее всего правильнее, потому что удаление от центральной точки становится равномерным.
Есть более простой вариант, правда не уверен, что более производительный: в месте стыков и по краям рисовать круглую точку диаметром равным толщине линии.
Если не секрет, расскажите идею эффекта штрихования?

П.С.
У меня есть идея, сделать через текстурную маску, и с помощью маски задавать любой стиль штрихования.

Да, идея именно такая. Только там создается не маска, а distance-map, которая позволяет получить потрясающую точность. Еще там есть хак, чтобы запаковать float в цвет. Про distance map можно почитать здесь http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf

С круглыми точками в углах, боюсь могут возникнуть проблемы с полупрозрачными линиями.

Да, проблемы будут. Но для САПР прозрачности линий не требуется. К тому же круглые точки выглядят лучше для 3д полилиний.

О, классно. Как раз бодаюсь с этой темой.

Пока что ещё пришла немного сумасшедшая мысль нарисовать обычный прямоугольник, а линию рисовать во фрагментном шейдере.
2D пример начинает плохо работать для толстых линий:



SVG (который ИМХО в данной задаче можно считать своего рода ground truth) не накапливает прозрачность на самопересечениях, что, кажется правильнее. Но как решить это без стенсила, я пока не знаю.
Линию можно представить как нарисованную кисточкой, а можно представить сложенной полоской из бумаги(или полиэтиленового пакета). Мне больше нравится вариант с накапливаемой прозрачностью.

Вы правильно указали на ошибку с обрезанным треугольником внутри сложенных отрезков, я не решил эту проблему. Этот момент легко находится в шейдере, но я посчитал, что такие случаи бывают редко и решил оставить до поры до времени…
Непонятно, как оно тут поможет. Плюс, это надо включить MSAA, который в WebGL доступен только для дефолтного фреймбуфера.

ну здесь ручное управление масками… плохо совместимо с антиалиазингом.

Я не очень понял ваш комментарий. Но если я правильно понял спеку, вызов glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE) не возымеет никакого эффекта если для буфера не включен MSAA. Кроме того, я все равно не очень понял, даже если он у нас включен, как alpha-to-coverage поможет решить проблему на самопересечениях. Судя по спеке, результат интерпретации такой маски, вообще говоря, непредсказуем (а точнее, зависит от оборудования, на котором работает программа). Или я чего-то не понимаю?

Да, наверное я зря здесь написал про alpha-to-coverage, опыта разработки чего-то подобного у меня нет. Но я предположил, что есть вручную задавать маски для пикселя, для одинаковых масок наложение будет давать тот же результат, т.е. цвет не будет удваиваться. Если использовать разные маски для разных материалов, можно создать такой эффект, который требуется. Но это слишком сложно и все равно, что из пушки по воробьям. Тут важно понять, говорим ли мы о 2d или о 3d. С 2d очень просто все разруливается, про 3d надо что-то изобретать.

GL_SAMPLE_ALPHA_TO_COVERAGE нужно чтобы МСАА сглаживал альфатест, не более того. Листва там, решетки, травку))

хотя тут достаточно элементарного depth-test режима LESS вместо LEQUAL

Не всегда, может быть ситуация, когда разные линии (то есть, одна должна просвечивать через другую) могут иметь одинаковую Z-координату.

в этом случае для разных линий можно устанавливать разный POLYGON_OFFSET. Если мы говорим о 2d режиме, то и вовсе можно пользоваться z координатой для сортировки линий по порядку отрисовки.

Еще раз нашел статью, ностальгия нахлынула. Вспомнил, как я делал точно такие же шейдеры точно для такой же задачи (рисование орбит, и рисование на глобусе), и выплыла точно такая же необходимость делать отсечение znear/zfar.
Посмотрел, отсечение у меня было в геометрическом шейдере.
	// clip line begin
	if (position_1.z > -z_near) {
		float t = (position_1.z + z_near) / abs(position_2.z - position_1.z);
		position_1 = lerp(position_1, position_2, t);
		width_1 = lerp(width_1, width_2, t);
		texcoord_0_1 = lerp(texcoord_0_1, texcoord_0_2, t);
		texcoord_2_1 = lerp(texcoord_2_1, texcoord_2_2, t);
		texcoord_3_1 = lerp(texcoord_3_1, texcoord_3_2, t);
	}
	
	// clip line end
	if (position_2.z > -z_near) {
		float t = 1.0f - (position_2.z + z_near) / abs(position_2.z - position_1.z);
		position_2 = lerp(position_1, position_2, t);
		width_2 = lerp(width_1, width_2, t);
		texcoord_0_2 = lerp(texcoord_0_1, texcoord_0_2, t);
		texcoord_2_2 = lerp(texcoord_2_1, texcoord_2_2, t);
		texcoord_3_2 = lerp(texcoord_3_1, texcoord_3_2, t);
	}
Sign up to leave a comment.

Articles