Рендирайте големи кръгли точки в съвременния OpenGL

Искам да изобразя запълнени кръгове с динамично променящ се радиус около набор от точки, чиито 2D координати се съхраняват във VBO. Досега използвах GL_POINT_SMOOTH, но след като преминах към OpenGL 4.0, тази опция вече не е налична. Виждал съм подобен въпрос тук, но това не отговаря съвсем на нуждите ми тъй като центровете на кръговете в този пример са твърдо кодирани във фрагментния шейдър. Как бих направил това?

В момента моят вертекс шейдър изглежда така:

#version 400

layout(location=0) in vec2 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;

uniform vec4 bounds;

void main(void){
    float x = -1+2/(bounds.y-bounds.x)*(in_Position.x-bounds.x);
    float y = -1+2/(bounds.w-bounds.z)*(in_Position.y-bounds.z);
    gl_Position = vec4(x,y,0,1);
    ex_Color = in_Color;
}

И моят фрагментен шейдър изглежда така:

#version 400

in vec4 ex_Color;
out vec4 out_Color;

void main(void){
    out_Color = ex_Color;
}

С тези шейдъри получавам квадратни точки.


person jaideep777    schedule 24.11.2014    source източник


Отговори (1)


„Модерният“ начин за рисуване на точки работи по следния начин:

  1. Активирайте режима за размер на програмната точка:

    glEnable(GL_PROGRAM_POINT_SIZE);
    
  2. Рендирайте върхове с GL_POINTS примитивен режим.

  3. В върховия шейдър задайте вградената променлива gl_PointSize на желания размер на отделната точка:

    gl_Position = ...;
    gl_PointSize = ...;
    

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

  4. Това ще генерира фрагменти за квадратна точка с размера, определен от стойността на gl_PointSize. Във фрагментния шейдър можете да използвате вградената променлива gl_PointCoord, която ви дава относителната координата на фрагмента в точката. Работи много подобно на координатите на текстурата, като предоставя диапазон от [0, 1] във всяка посока.

    Например, ако искате текстурирани точки, което е много полезно за системи от частици, фрагментният шейдър код може да съдържа:

    outColor = texture(particleTex, gl_PointCoord);
    

    Или ако искате кръгли точки, можете да изхвърлите всичко извън кръг въз основа на разстоянието от центъра:

    vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
    if (dot(circCoord, circCoord) > 1.0) {
        discard;
    }
    

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

Обърнете внимание, че диапазонът от поддържани размери на точки зависи от изпълнението. Можете да направите заявка за наличния диапазон с:

GLfloat sizeRange[2] = {0.0f};
glGetFloatv(GL_POINT_SIZE_RANGE, sizeRange);
person Reto Koradi    schedule 24.11.2014
comment
Перфектно! Моето объркване възникна от липсата на разбиране на фрагментния шейдър. Сега разбирам как работи това! Благодаря ти много. - person jaideep777; 24.11.2014