LINUX.ORG.RU

Как в шейдерах рисовать простые геометрические фигуры?

 


2

5

Всем снова привет!

Собственно, сабж. Хочется уметь рисовать нечто вроде glutWireSphere, glutWireCube, но я пока не понимаю, как это лучше всего сделать. В идеале хочется, чтобы шейдер принимал от меня 3-4 флоата, а дальше сам все отрисовывал. OpenGL 4.2.

★★

Набей их вершинами в массив. Чтоб руками не составлять можно через assimp:

Assimp::Importer as;
const auto sc=as.ReadFileFromMemory("hex 0 0 0 0",11,0,"nff");

anonymous
()

Vboшка надо из линий и fragment shader.

slapin ★★★★★
()
Ответ на: комментарий от anonymous

А без набивания в массив - никак? Шейдер сам не сумеет себе сгенерить вершины и их соединить?

aido ★★
() автор топика
Ответ на: комментарий от aido

Лучше делать так, как делают в играх, тк аппаратное устройство видеокарт затачивается под них.

anonymous
()
Ответ на: комментарий от aido

Можно сгенерить вершины в текстуру однтм шейдером и потом отдать на отрисовку другому, но это будет медленнее при большом количестве вершин чем на cpu.

slapin ★★★★★
()
Ответ на: комментарий от aido

Если glfw не может рисовать примитивы, на кой черт она тебе нужна?

anonymous
()
Ответ на: комментарий от anonymous

Извращение это как раз НЕ через шейдеры. Если любишь всё делать на процессоре через glBegin() - тебе опенгл не нужен.

anonymous
()
Ответ на: комментарий от aido

Возьми какой-нибудь игровой движок, в котором есть примитивы и который под капотом использует видеокарту нормально.

anonymous
()
Ответ на: комментарий от anonymous

Кто мешает в нормальной библиотеке воткнуть шейдеры «под капотом» glBegin?

Что за маразматический дебилизм, что каждому приходится ручками рисовать примитивы? Это вообще верх мудачества!!!

anonymous
()
Ответ на: комментарий от anonymous

Используй нормальную библиотеку glBegin-ов. Опенгл это для работы с видеокартой так, как она работает, а не для glBegin-ов.

anonymous
()
Ответ на: комментарий от anonymous

Чувак, хватит херню нести! В нормальной библиотеке все эти glBegin'ы превратились бы в набор шейдеров, и на видюхе бы влет работали!

Но библиотеки пишут передасты, и мы имеем то, что имеем...

anonymous
()
Ответ на: комментарий от anonymous

Изначально у меня было сделано на glBegin-ах, но потом я сильно уперся в недостаток свободы в действиях. Ну типа, когда захочется нарисовать тот же самый wired, но с эффектом гало, то начинается ад. А также, кривая математика, не позволяющая сделать простыми средствами движение камеры, а не движение мира (я понимаю, что внутри это так и работает, но в коде хочу, чтобы было понятно, когда движется камера, а когда - объекты).

aido ★★
() автор топика
Ответ на: комментарий от anonymous

Ищите immediate geometry library и будет счастье. Но я продолжаю использовать glBegin и оно все еще работает... так как под капотом делает массив...

slapin ★★★★★
()
Ответ на: комментарий от anonymous

В нормальной библиотеке все эти glBegin'ы превратились бы в набор шейдеров

Это абсолютно не верно. Компилятор gcc обращается с функциями openGL как с обычными функциями любой библиотеки, то есть по-честному вызывает ее из библиотеки. Он понятия не имеет, что есть еще какой-то опенгл, который надо превращать в шейдеры, да еще и оптимизировать.

В случае с шейдерами, мы четко и грубо говорим компилятору заткнуться, отдать текст на компилирование opengl и использовать оптимизированный им код для видеокарты.

aido ★★
() автор топика
Ответ на: комментарий от anonymous

Ты несёшь херню. Всё это выкинули из core profile как раз потому, что не превращалисьи не работали влёт а являлись диким процессорным боттлнеком. Вскоре и core profile опенгл стал процессорным боттлнеком, потому изобрели vulkan, dx12, mantle, metal.

anonymous
()
Ответ на: комментарий от anonymous

ты еще скажи, что единственный верный способ программировать графику - напрямую в CUDA рисовать!!!

anonymous
()
Ответ на: комментарий от anonymous

Да, в vulkan вывода на дисплей это вообще необязательное расширение.

Тебе уже сказали - используй высокоуровневые библиотеки, а не лезь в апи для работы с железом.

anonymous
()
Ответ на: комментарий от aido

Это необходимая инициализация. Потом казалось бы «большие» фичи туда добавляются не таким большим количеством строк.

А так нужно правильно выбирать инструмент.

anonymous
()
Ответ на: комментарий от anonymous

Не. я лучше буду развлекаться с рисованием простых полигонов через шейдеры, чем с необходимым инитом в 1100 строк кода.

aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от aido

Лучше ещё потому, что без необходимых знаний вероятно будет работать медленнее, чем опенгл. Просто меньше будет жрать проц.

anonymous
()

Geometry shader может выдавать больше геометрии, чем в него пихают, в отличие от vertex shader, который всегда выдаёт один к одному.

i-rinat ★★★★★
()

Такая каша в головах у присутствующих (кроме некоторых), даже лень объяснять. Почитайте какие-нибудь статьи или книги по компьютерной графике и работе GPU, прежде чем такую чушь писать.

* мимо-дартаньян

anonymous
()
Ответ на: комментарий от aido

Короче, аналог для wired_sphere у меня выглядит как-то так:

const char *vertex_sphere="#version 420 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";
const char *fragment_sphere = "#version 420 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\0";
static wired_sphere gen_sphere_points(float radius, uint32_t slices, uint32_t stacks)
{
    wired_sphere res;
    for (uint32_t i=1; i<slices; ++i)
    {
        for(uint32_t j=1; j<stacks; ++j)
        {
            float x=radius*sin(M_PI*j/stacks)*cos(2*M_PI*i/slices);
            float y=radius*sin(M_PI*j/stacks)*sin(2*M_PI*i/slices);
            float z=radius*cos(M_PI*j/stacks);
            res.vertexes.push_back(glm::vec3(x,y,z));
        }
    }
    for (uint32_t i=1; i<slices; ++i)
    {
        for(uint32_t j=1; j<stacks; ++j)
        {
            res.l.push_back({(j-1)*slices+i-1, (j-1)*slices+i});
        }
    }
    return res;
}
// bla bla bla
auto wired_coords=gen_sphere_points(1.0, 5, 5);
auto program_sphere=load_shaders(vertex_sphere, fragment_sphere);
while (!glfwWindowShouldClose(window))
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

        GLuint EBO;
        glGenBuffers(1, &EBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, wired_coords.lines.size(), wired_coords.lines.data(), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glDrawElements(GL_LINES, wired_coords.lines.size(), GL_UNSIGNED_INT, 0);
        GLuint VAO_sphere;
        glGenVertexArrays(1, &VAO_sphere);
        glBindVertexArray(VAO_sphere);
        GLuint VBO_sphere;
        glGenBuffers(1, &VBO_sphere);
        glBindBuffer(GL_ARRAY_BUFFER, VBO_sphere);
        glBufferData(GL_ARRAY_BUFFER, wired_coords.vertexes.size(), wired_coords.vertexes.data(), GL_STATIC_DRAW);
        // position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT,        GL_FALSE, sizeof(glm::vec3), (void*)0);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
        glUseProgram(program_sphere);
        glBindVertexArray(VAO_sphere);
        glDrawElements(GL_LINES, wired_coords.parallels.size(), GL_UNSIGNED_INT, (void*)wired_coords.lines.data());

Сделано пока бездумно. поздно уже.

aido ★★
() автор топика
Ответ на: комментарий от aido

Несколько glDrawElements() можно заменить на один glMultiDrawElementsBaseVertex() или glMultiDrawElementsIndirectCount() Всё кроме

glClear()
glUniformMatrix4fv()
glMultiDrawElementsBaseVertex()

выкинуть из цикла в предварительную инициализацию. В шейдере использовать переменные gl_DrawID и gl_BaseInstance как индексы в буферы.

Может не выйти упихать совсем всё в один glMultiDraw* если нужно менять настройки рендеринга.

anonymous
()
Ответ на: комментарий от aido

Vulkan еще более низкоуровневый апи, чем опенгл.

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

Unicode4all ★★★★★
()
Ответ на: комментарий от Unicode4all

Не проще ли взять нормальную высокоуровневую библиотеку

КАКУЮ????

Народ трещит о «высокоуровневой библиотеке», но никто не назвал ее! Может, потому, что ее просто не существует?

Давай, покажи примеры сишных высокоуровневых библиотек для опенгля. Крестовые не годятся, т.к. кресты - убогое дерьмо!

anonymous
()
Ответ на: комментарий от anonymous

Просто нужно написать самому.

anonymous
()
Ответ на: комментарий от anonymous

Из чисто графических либ я тебе назову пресловутые OpenSceneGraph и Ogre3d.

Ах да, забыл. Они же написаны на ненавистных тебе крестах, но ты наверняка сможешь разъяснить причины ненависти к крестам не так ли? Чем тупой набор макросов для ассемблера лучше более-менее высокоуровнего языка? Особенно для рисования тридэ.

Если ты или ТС не хочешь использовать высокоуровневые библиотеки только из-за того, что не нравится язык (промышленный стандарт, причем, ага), то... ну... придется да, жрать голый опенгл.

Unicode4all ★★★★★
()
Ответ на: комментарий от Unicode4all

ты наверняка сможешь разъяснить причины ненависти к крестам не так ли?

Слишком избыточно. Жирный нечитаемый ЯП. Поди проследи, какие шаблоны во что разворачиваются. Говно, да и только!

На С ты пишешь аккуратный код, и влет можешь найти нужную функцию, не копаясь в перегрузках и шаблонах по всем промежуточным классам!!!

anonymous
()
Ответ на: комментарий от anonymous

То что на С++ будет коротким аккуратным фрагментом кода, на С будет длинной портянкой. Я как-то сишную версию кода для работы с zmq перевел то на С++, то банально выкинул кучу кода и вся переделка. Определил конструктор и у тебя уже гарантия правильной инициализации и ты спокоен, что какой-нить чудак на букву «м» не забудет вызвать функцию `context_init(ctx);`. В больших проектах это многого стоит.

А по теме автору уже сказали, что нужно юзать геометрический шейдер. И да, мусора в тему навалили, бреда очень много.

yetanother ★★
()
Ответ на: комментарий от Unicode4all

Требования к приложухе такие:

1) Минимальное использование лишних библиотек. Графическая часть его будет не сильно меняться. Если конкретно, то это моделирование физического эксперимента.

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

3) возможность писать картинку в видеофайл. Идеально было бы просто задать траекторию камеры в файле, а на выходе получить mp4, с тем, что эта камера видит.

aido ★★
() автор топика
Ответ на: комментарий от yetanother

Не неси чушь! Подумаешь, «длинная портянка»! Зато читабельная.

А в говнокрестах с этой мешаниной классов, перегрузок, шаблонов и прочего, код получается вообще никак не читабельный!

anonymous
()
Ответ на: комментарий от aido

Вспомнил: vtk.org - плюсовая либа для всякой визуализации, (не игровой движок), весьма монструозная. Из мелкого mathgl.

anonymous
()

Шейдер так не работает. В видеокарте rendering pipeline. На входе у него вершины - массив произвольных структур данных, индексы в этом массиве, текстуры и может еще что-то. На выходе изображение (или еще что-то). Сам пайплайн состоит из десятка шагов, все они конфигурируются, но некоторые еще и программируются, их называют шейдерами. Если у тебя сцена типа как в майнкрафте, где геометрия простая и ее не сложно генерировать процедурно, то можно в шейдер передавать совсем мало, а остальное генерировать. Геометрический шейдер и какой-то из шейдеров тесселяции могут сделать несколько примитивов из одного. Опять же, возвращаясь к примеру майнкрафта, можно передать массив точек, а в геометрическом шейдере каждую точку превратить в кубик. Но обычно так не делают. Обычно вершины и индексы подготовлены заранее.

Это так и в opengl и в vulkan и в d3d. Только в вулкане еще и память нужно менеджить самому и синхронизировать процессоры (если многопоточность).

vlad9486
()

Если принципиально нужно передавать в шейдер только несколько флотов, то краткий ответ: Куб - возможно, гугли геометрический шейдер. Сфера - можно попробовать тесселяцию куба. Чайник - практически невозможно, нужно что-бы вершины легко генерировались процедурно.

vlad9486
()
Ответ на: комментарий от anonymous

Не неси чушь! Подумаешь, «длинная портянка»! Зато читабельная.

А в говнокрестах с этой мешаниной классов, перегрузок, шаблонов и прочего, код получается вообще никак не читабельный!

Не нужно быть категоричным школьником в своих суждениях. То? что ты видел только говнокод на крестах не значит что на нем нельзя писать адекватно. Говнокод на си пишется также на ура. Но на си ты никогда (от слова совсем) не сможешь писать такой же компактный код как с++. Для низкоуровневой библиотеки это нормально. А для высокого уровня уже не подходит однозначно. Нет, кресты тоже имеют кучу недостатков, но то что они более высокого уровня язык чем сишечка не сможешь отрицать даже ты.

yetanother ★★
()
Ответ на: комментарий от yetanother

Для низкоуровневой библиотеки это нормально.

Есть слухи, что в c++ за последние 20 лет завезли Zero-Cost Abstractions, думаю, что и для низкоуровневой библиотеки уже можно c++.

vlad9486
()
Ответ на: комментарий от vlad9486

Есть слухи, что в c++ за последние 20 лет завезли Zero-Cost Abstractions, думаю, что и для низкоуровневой библиотеки уже можно c++.

Я думаю, что достаточно давно уже можно. Мое утверждение было о другом - что в низкоуровневых приложениях, где ты оперирируешь на уровне байт, С вполне уместен. А в сложных системах, где ты оперируешь понятиями из предметной области, которые обычно плохо выражаются байтами и указателями, уровень абстракции у С явно недостаточен. А говнокод можно писать на всем.

И я не фанат С++, пишу на нем вынужденно. Просто для себя выбор между С и С++ я сделал в пользу последнего. Да, есть недостатки, но и возможностей больше.

yetanother ★★
()
Ответ на: комментарий от anonymous

Никто не переубедит меня, что в мире есть ЯП лучше С! Потому что нет таких ЯП!!!

Не то чтобы хотелось потроллить, но ты забыл добавить что-то вроде - я так сказал! Я знаю лучше всех! Я - лучше всех! И вообще, побольше восклицательных знаков и юношеской категоричности. Какие взвешенные суждения? Когда можно так экспрессивно и эмоционально самовыражаться? И АНОНИМНО. Модно, стильно, молодежно. Правда не имеет абсолютно никакого отношения к программированию.

Для каждой задачи есть свой наиболее подходящий инструмент.

yetanother ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.