Геометрический шейдер?
получил некоторые результаты, есть вопрос:
подскажите как сделать линии постоянной толщины через вершнинный шейдер, так возможно? кто подобное пробовал?
пока оба конца линии на экране - линия похоже что постоянной толщины
как только один из концов за экраном - становится заметно изменение толщины линии
делал так:
рисую двумя трианглами, для концов линии считаю толщину линии как зависимость расстояния до камеры
в вершинном шейдре к вершинам триангла прибавляю нормаль, посчитанную по вектору направления линии, умноженную на толщину (коэффициент зависящий от расстояния до камеры)
void main(){ vec3 dir = normalize( position.xyz - second.xyz); float width = color.z;// коэффициент зависящий от расстояния до камеры vec3 n = normalize( cross( dir,position.xyz-cam_position)); gl_Position = matrix * vec4( position.xyz+n*width,1.0f); }
пологаю, что при пересечении линией экрана, нужно посчитать толщину в точке пересечения, но как?
Нашёл!!! Помнил же, что был похожий вопрос.
FordPerfect
спасибо за ссылку, но видимо я тупой и не нашёл полезного, там мало того что пользуют геометрический шейдер так часть ещё и фрагментном
>фрагментном шейдере считаются расстояния фрагмента до трех вершин. Т. е. часть работы из геометрического шейдера переносится во фрагментый
геометрический не пользую для линий из-за поддержки старого железа - всего то линии нарисовать, базовый функционал, это как атомной бомбой голубей шугать
нагуглить примитивные линии постоянной толщины не удалось, уже сомниваюсь что так можно
glBegin(GL_LINES) же както рисует - может месу поковырять?
slax
> линии постоянной толщины
В screen-space?
Или в world-space?
v1c
для каждого пикселя проходить по всем линиям - это перебор
FordPerfect
да, постоянной толшины на экране
slax
> семь корней на каждый пиксель кажется жирновато чтобы рисовать линии
По-моему там нужно 0 корней:
#define resolution vec2(500.0, 500.0) #define Thickness 0.03 float cross2d( vec2 a,vec2 b) { return a.x*b.y-a.y*b.x; } float drawLine( vec2 p1, vec2 p2) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec2 N=p2-p1; float N2=dot( N,N); float y=cross2d( uv-p1,N); float x=max( dot( p1-uv,N),0.0); x=max( dot( uv-p2,N),x); float d=x*x+y*y - Thickness*Thickness*N2; return d<0.0?1.0:0.0; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 p1 = vec2( 0.8 + sin( iTime)*0.5, 0.1); vec2 p2 = vec2( 0.8 + cos( iTime)*0.5, 0.5); fragColor = vec4( drawLine( p1, p2)); }
FordPerfect
т.к. пишешь в fragColor - значит линию рисуешь в фрагментном шейдере
а на какой примитив рисуешь как два триангла в экран 500x500?
если рисовать таким образом 1 000 000 линий это будет быстрее чем столькоже через glBegin(GL_LINES) ? на старых видяхах
и каждый из 500х500 пикселей будут считать расстояния до каждой из 1 000 000 линий .... всёравно кажется жирновато
видать я плохо объясняю задачу
slax
Дак а зачем полный экран-то?
Рисовать OBB отрезка с таким шейдером.
В смысле, если не нужен anti-aliasing, так можно и OBB сплошной заливкой + круги.
Но AA в шейдере может быть дешевле/качественнее.
Ну что-то типа
#define AA 1 // Anti-aliasing #define SCALE 4.0 // Size of a virtual pixel, to make AA more visible #define Thickness 4.0 // In virtual pixels float cross2d(vec2 a,vec2 b) { return a.x*b.y-a.y*b.x; } float drawLine( vec2 p1, vec2 p2) { vec2 uv = gl_FragCoord.xy; uv=floor( uv/SCALE)*SCALE; float T=Thickness*SCALE; vec2 N=p2-p1; float N2=dot( N,N); float y=cross2d( uv-p1,N); float x=max( dot( p1-uv,N),0.0); x=max( dot( uv-p2,N),x); float d=x*x+y*y - T*T*N2; #if AA // NOTE: this is an approximation. d=-d/( 2.0*N2*T); // Distance (approximated) of sample point from edge. d/=float( SCALE); float k=abs( abs( N.x)-abs( N.y))/( abs( N.x)+abs( N.y)); // tan(slope), 0<=slope<=45 deg. k=mix( sqrt( 0.5),1.0,k); // Or you can just approximate as k=1. d=clamp( 0.5+k*d,0.0,1.0); return d; #else return d<0.0?1.0:0.0; #endif } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 p1 = iResolution.xy*vec2( 0.8 + sin( iTime)*0.5, 0.1); vec2 p2 = iResolution.xy*vec2( 0.8 + cos( iTime)*0.5, 0.8); fragColor = vec4( drawLine( p1, p2)); }
FordPerfect
Тут бесполезно что либо советовать. Человек слушает только себя.
FordPerfect
>Рисовать OBB отрезка с таким шейдером.
так ооб отрезка будет иметь перспективу, для линии в скрин-спейс толщины это не хорошо, да филрейт будет ниже
>так можно и OBB сплошной заливкой + круги
вот - этот ооб построить в скринспейс у меня и не получается
получается только с перспективными искажениями а нужно без них
MrShoor
>Тут бесполезно что либо советовать. Человек слушает только себя.
я учёл твой совет про убийственный филлрейт,
и не только себя слушаю, а пытаюсь объяснить, что нужно без геометрического/фрагментного/ffp выводить 3d линии в скрин-спейс одной толщиной через вершинный шейдер, эффективно рисовать много линий
и при расчёте вершин, задающих толщину, у меня не получается сделать её одинаковой толщины по всей длинне линии на экране
на что получаю советы ... про другое и реализованное другими техниками, значит плохо объясняю -
как правильно сформулировать чтоб сразу всем понятно стало?
slax
> а пытаюсь объяснить, что нужно без геометрического/фрагментного/ffp
Но почему без фрагментного то? Без геометрического - могу понять, но фрагментный шейдер он ведь есть на железе даже 15-ти летней давности. Почему без него то?
Тема в архиве.