Как мога да изобразя безкрайна 2D мрежа в GLSL?

В идеалния случай това, което бих искал да направя, е да начертая единичен квадрат и да накарам GLSL да се справи със създаването на действителните линии на мрежата.

В моя опит досега върховият шейдър:

#version 400

layout (location = 0) in vec4 in_position;
layout (location = 2) in vec3 in_UV;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

smooth out vec3 ex_UV;
smooth out vec3 ex_originalPosition;

void main()
{
    gl_Position = projection * view * model * in_position;

    ex_UV = in_UV;
    ex_originalPosition = vec3(in_position.xyz);
}

Матрицата на модела увеличава четириъгълника с голямо число, като 10 000.

#version 400

layout (location = 0) out vec4 color;

smooth in vec3 ex_UV;
smooth in vec3 ex_originalPosition;

uniform vec4 lineColor;

void main(void)
{
    if(fract(ex_UV.x / 0.001f) < 0.01f || fract(ex_UV.y / 0.001f) < 0.01f)
        color = lineColor;
    else
        color = vec4(0);
}

Опитах се да използвам както координатите на текстурата, така и позициите на световното пространство за това. И двете водят до един и същ ефект, който изглежда добре под някои ъгли, но при други започва да изглежда ужасно.

въведете описание на изображението тук

въведете описание на изображението тук

Мислех, че може би мога да мащабирам алфата в зависимост от разстоянието, така че решетката ми да изчезне в нищо, но проблемът е, че можете да видите във второто изображение, от центъра на екрана, можете да видите, че дори тези линии са се изобразяват с пропуски през тях (точката на решетката е да даде визуална референтна рамка около началото).

Има ли по-прост начин да направите това?

РЕДАКТИРАНЕ

Екранни снимки според заявката:

VBO линии с x8 Multisampled Framebuffer

въведете описание на изображението тук

VBO линии с x8 Multisampled Framebuffer и glEnable(GL_LINE_SMOOTH)

въведете описание на изображението тук

Спрях се

Спрях се на едното от горните (няма значение кое) и просто намалих алфата като функция на разстоянието от началото. Това служи на моята цел, въпреки че това не е въпросът, който зададох. въведете описание на изображението тук


person NeomerArcana    schedule 15.06.2015    source източник
comment
Ще ми е интересно да видя резултата с GL_LINES и мултисемплиране. Бихте ли публикували екранна снимка като актуализация?   -  person jozxyqk    schedule 15.06.2015
comment
Резултатите по същество са идентични с вашия въпрос. В крайна сметка обаче открих, че всъщност не се нуждая от безкрайна равнина, така че вместо това използвах много по-малка четворка с кръгъл градиент от началото като алфа. Обслужва целите ми, въпреки че признавам, че отговорът ви е правилен по отношение на действителния въпрос, който зададох.   -  person NeomerArcana    schedule 16.06.2015


Отговори (2)


Прост случай на псевдоним. Точно както при изобразяването на полигони, вашият фрагментен шейдър се изпълнява веднъж на пиксел. Цветът се изчислява само за една централна координата и не е представителен за истинския цвят.

въведете описание на изображението тук

  1. Можете да създадете FBO с множество проби и да активирате суперизвадка. Но това е скъпо.
  2. Бихте могли математически да изчислите точно колко линейна площ и празна решетка има под всеки пиксел, след което да ги оцветите съответно във фрагментния шейдър. Като се има предвид, че е еднаква решетка, това може да е възможно, но математиката все още може да стане доста сложна.
  3. Mipmapping вече прави това за текстури. Създайте мрежова текстура само с няколко реда и я картографирайте, така че да се повтаря за вашия наистина голям квадрат (не забравяйте да зададете GL_REPEAT). Настройте правилните параметри за филтриране на mipmap за текстурата и извикайте glGenerateMipmap . Когато извикате texture2D()/texture() във фрагментния шейдър, OpenGL автоматично изчислява кое ниво на mipmap да се използва въз основа на делтата на координатната текстура между съседните пиксели. И накрая, настройте анизотропно филтриране за още по-удивително изглеждаща мрежа.

    въведете описание на изображението тук

Ако искате мрежата да бъде наистина „безкрайна“, виждал съм някои океански рендери да свързват краищата на мрежата с хоризонта с вертикална геометрия. Ако имате достатъчно решетка преди тях, бихте могли да се измъкнете, като им зададете един плосък цвят - цветът на най-горното ниво на вашата mipmap.


Примери (свързани с коментари):

1024x2 GL_LINES, изтеглени от VBO
въведете описание на изображението тук
45fps (начертано 100 пъти за бенчмарк при HD резолюция)

Вижте коментарите относно мултисемплирането, за да се справите с псевдонимите на GL_LINES.

Текстура 32^2, картографирана към четворка с mipmapping
въведете описание на изображението тук
< sup>954 кадъра в секунда (нарисувани 100 пъти за бенчмарк при HD резолюция)

Image img;
int w = 128;
int h = 128;
img.resize(w, h, 1);
for (int j = 0; j < h; ++j)
    for (int i = 0; i < w; ++i)
        img.data[j*w + i] = (i < w / 16 || j < h / 16 ? 255 : 0);

tex = img.upload();

glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);

...

//for the quick and dirty, immediate mode
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0,       0); glVertex3f(0, 0, 0);
glTexCoord2f(1024,    0); glVertex3f(1, 0, 0);
glTexCoord2f(1024, 1024); glVertex3f(1, 0, 1);
glTexCoord2f(0,    1024); glVertex3f(0, 0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
person jozxyqk    schedule 15.06.2015
comment
Текстурите изобщо не гарантират линии без пропуски. Освен това въвеждате много ненужна обработка на фрагменти и вземане на проби, където в подхода на линията ще се изпълняват само фрагментите, които действително допринасят за линиите. Целта беше просто да начертая 2D решетка и за мен всички ваши подходи са огромно прекаляване. - person Bartek Banachewicz; 15.06.2015
comment
Като първа точка, той конкретно предоставя техники за прилагане на текстури, за да се получат линии с изглаждане, последвано от сравнение на наивно текстуриране на четворка срещу това да го направите добре. За втората точка все още се нуждаем от цитат коя техника е по-бърза. - person Blarglenarf; 15.06.2015
comment
Интересни резултати от представянето. Вече мога да гласувам за това с чиста съвест :) - person Bartek Banachewicz; 15.06.2015

можете да видите, че дори тези линии се изобразяват с пропуски през тях

О, разбира се, че можем. И това е, защото сте обидили CG 101. (Без обида :))

Ние използваме GL_LINES с причина; рисуването на линии без пропуски на компютърен екран не е тривиално (макар и решено). Говоря за нещо подобно. Това, което направихте, извършва изчисления върху числа с плаваща запетая и ще доведе до изчертаване на субпикселни линии (т.е. пропуски).

Моето предложение би било да премахнете този GLSL код и да генерирате линиите като обикновени върхове. Вероятно ще бъде по-бързо и ще получите подходящи резултати.

Също така ще можете да получите ефекта на „избледняване в далечината“, който искате, като използвате редовни изчисления за мъгла.

person Bartek Banachewicz    schedule 15.06.2015
comment
... сега се чувствам глупаво. На върха на главата си знаете ли дали един геометричен шейдър може да има триъгълници като вход и линии като изход? - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Ако наистина искате да го направите в шейдъри (можете да го помиришете във въздуха :D), тогава бих нарисувал четворка и ще я теселирам до желаната плътност. Отново, това би използвало хардуерна поддръжка, направена предварително, за да поеме такива натоварвания. Освен това, можете да отрежете примитивите в геометричния шейдър, така че намаляването на всеки триъгълник до линия трябва да е ОК. само layout(triangles) in; layout(lines) out; - person Bartek Banachewicz; 15.06.2015
comment
Да, вече го има в Geometry Shader. Имам 2D квадрат, сега просто трябва да разделя. - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Само за пояснение, имах предвид да използвам Tesselation Shader; Извеждането на един ред на един триъгълник в GS е добре. Извеждане на хиляди редове на триъгълник няма да има! - person Bartek Banachewicz; 15.06.2015
comment
Начертаването на толкова много линии ще бъде много по-бавно от единичен квадрат и примитивите на линиите все още ще трябва да бъдат премахнати. GL_LINE_SMOOTH може да помогне, но все още се проваля при пресичане на линии. - person jozxyqk; 15.06.2015
comment
@jozxyqk [citation-needed] включеното ще бъде по-бавно. Също така не виждам изискване за примитивите на линията все пак ще трябва да бъдат антиалиасирани. Освен това има други алгоритми и подходи за изчертаване на антиалиазирани линии. - person Bartek Banachewicz; 15.06.2015
comment
Честна точка, не съм го сравнил, така че просто ще кажа, че подозирам, че ще бъде доста по-бавен. OP иска гладко изглеждаща мрежа. Чертането на примитиви на линия без никакво антиалиасинг, както този отговор описва в момента, няма да им даде желания резултат. - person jozxyqk; 15.06.2015
comment
Да, в идеалния случай те биха били хубави и антиалиасни. - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Тогава може би този GPU Gem може да помогне. Но от друга страна, както казах, рисуването на линии е много и аз все още бих се придържал към, е, рисуването на линии. Другият отговор от jozxyqk наистина премества проблема, тъй като все още работи във фрагментно пространство (дори ако е вземане на проби от текстура). - person Bartek Banachewicz; 15.06.2015
comment
Изглежда, че няма голямо значение, използвам буфер с множество проби и досега GL_LINES се изобразяват перфектно добре и са антиалиасирани. - person NeomerArcana; 15.06.2015
comment
Те ще бъдат изгладени, защото използвате мултисемплиране, а не защото използвате GL_LINES. - person Blarglenarf; 15.06.2015
comment
Да, разбирам това. Просто казвам, че получавам желания резултат без ръчно антиалиазиране на линиите. - person NeomerArcana; 15.06.2015