На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела "Программирование графики"
1) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с чтением, сохранением, обработкой, созданием, отрисовкой графической информации (в том числе - 3D [OpenGL, Direct3D] и анимации [в т.ч. VFW, DirectShow, OpenDML]).
Флэш обсуждают здесь!.

2) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе.

3) Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно.



Ваше мнение о модераторах: user posted imageBarazuk, user posted imageOpenGL, user posted imageMikle
Модераторы: OpenGL, Mikle
  
> Совсем глупые вопросы по OpenGL
    Тут буду постить мелкие вопросы по OpenGL (на абстрактном ЯП), ответ на которые либо не понял, либо понял, но не до конца, либо вообще не нашёл в интернетах.

    1) В чём отличие задавать меши с помощью вершинного шейдера:

    ExpandedWrap disabled
      attribute vec4 a_Position;
      void main() {
        gl_Position = a_Position;
      }
       
      ....
       
      // a_Position - ссылка на атрибут a_Position
      gl.vertexAttrib3f(a_Position, x1, y1, .0);
      gl.drawArrays(gl.POINTS, 0, 1);
       
      gl.vertexAttrib3f(a_Position, x2, y2, .0);
      gl.drawArrays(gl.POINTS, 0, 1);
       
      gl.vertexAttrib3f(a_Position, x3, y3, .0);
      gl.drawArrays(gl.POINTS, 0, 1);


    И с помощью нативных вызовов:

    ExpandedWrap disabled
      gl.begin(gl.POINTS);
      gl.vertex2f(x1, y1);
      gl.end();
       
      gl.begin(gl.POINTS);
      gl.vertex2f(x2, y2);
      gl.end();
       
      gl.begin(gl.POINTS);
      gl.vertex2f(x3, y3);
      gl.end();


    В чём отличия, преимущества, смысл вообще существования двух разных способов отрисовки трёх точек?

    *Я в курсе, что begin\end - это GL1+, а drawArrays - GL2+. Просто совмещал примеры вообще на разных языках =)
    Сообщение отредактировано: Serafim -
      При модификации координат при вращение анимации и других расчётах
      Шейдоры работают на GPU, begin-end на CPU.
      Плюс на CPU можете модифицировать длину массива, а на GPU только с шейдеров 5 версии.

      begin-end он как бы не для точек. А для динамически изменяющейся сцены.
      А шейдоры для статики. Или есть технология предварительного расчёта.

      На begin-end больше возможностей, на шейдерах зависит от версии .
        Цитата Pavia @
        Плюс на CPU можете модифицировать длину массива, а на GPU только с шейдеров 5 версии.

        хмхм? Имеется ввиду кидать в шейдер больше чем v4f за раз?
          Давай немного проясним вопрос. Вас интересует конкретная предметная область вывод точки? Или вместо точек любой другой примитив к примеру мэшь?Т.е. вас интересует конкретный пример или интересуют потенциальные возможности OpenGL?

          Почему есть два метода? Пожалуй это дело вкуса кто-то ест рис ложкой, ктото вилкой, а иные палочками.
          Есть старый метод, есть новый. У каждого есть свои ограничения. Для 3-х точек они не принципиальны. Правда стоит сказать чтр второй пример ужастный. Вместо того что-бы сразу отдать на обработку весь массив из N точек он дёргает по одной точке. Запомните групповые операции работают быстрее. В данном случае такой подход сбивает движёк opengl, но не сильнее чем в примере с begin-end.
          Сообщение отредактировано: Pavia -
            Цитата Pavia @
            Вас интересует конкретная предметная область вывод точки? Или вместо точек любой другой примитив к примеру мэшь?

            насколько я понял по примерам - отличия только в способе рендера, в моём случае POINTS, но ничего не мешает мне заменить на QUADS или лучше даже TRIANGLE_STRIP (но тогда надо либо всё поместить между begin\end, либо вызвать drawArrays только один раз), так что нет. В моём случае не стоило применять термин "меш", т.к. в примере это всё же просто точки.

            Цитата Pavia @
            Т.е. вас интересует конкретный пример или интересуют потенциальные возможности OpenGL?

            Второе; Пример - это лишь частный случай в попытке понять возможности и разобраться с АПИ.

            Цитата Pavia @
            Вместо того что-бы сразу отдать на обработку весь массив из N точек он дёргает по одной точке. Запомните групповые операции работают быстрее.

            Это для того, что бы пример походил на первый, конечно же, в реальной жизни я написал бы все три точки между begin\end :)
              Цитата Serafim @
              в моём случае POINTS, но ничего не мешает мне заменить на QUADS или лучше даже TRIANGLE_STRIP
              Вроде бы у шейдеров есть некоторые затруднения с QUADS'ами. Так что безопаснее через TRIANGLE_STRIP прокрутить, если что. :unsure:
                2) Eсть функция\метод gl.ortho он определяет координатную сетку, например:
                ExpandedWrap disabled
                  gl.ortho(0, 800, 0, 600, 1, -1)

                Это просто абстрактные координаты, которые помимо указания направления осей XYZ задают соответсвие между размерами будущих объектов, их позицией и этой системой. Т.е. точка (видимый объект) в точке (координатной) 400, 300, 0 будет ровно по середине (в случае нулевой камеры). Верно?

                2.1) В этом случае камера (пока опустим реализацию) - точка взгляда на эту систему координат с отсечением по near и far и наличием угла обзора (fov). Так?


                2.1) viewport - способ соотношения "взгляда" камеры на монитор?

                В результате получаем примерно вот такое:
                Прикреплённая картинка
                Прикреплённая картинка


                Добавлено
                Цитата Славян @
                Вроде бы у шейдеров есть некоторые затруднения с QUADS'ами. Так что безопаснее через TRIANGLE_STRIP прокрутить, если что.

                там в любом случае жопа какая-то будет (скорее всего просто ничего не нарисуется, т.к. GL отбрасывает лишнее по-дефолту), точек же всего три, а квадрат состоит из 4х :whistle: да и просто квадраты - это изврат.
                  Цитата Serafim @
                  да и просто квадраты - это изврат.
                  Кому - как: рисуя QUADS'ы я всё время жду, что нарисуется честная билинейная гладкая поверхность, но все движки/дрова так сделаны, что рисуется то одна, то другая пара треугольников. :'(
                    Цитата Serafim @
                    Это просто абстрактные координаты,

                    Слово абстрактные тут не к месту. Абстракция это по сути общение нескольких реализаций. Выделения общего для всех вариантов. А где тут обобщение?

                    Цитата Serafim @
                    случае нулевой камеры). Верно?

                    Да.


                    Цитата Serafim @
                    В этом случае камера (пока опустим реализацию) - точка взгляда на эту систему координат с отсечением по near и far и наличием угла обзора (fov). Так?

                    Несуществует такого понятия как "точка взгляда". Есть точка положения камеры и вектор направления взгляда. У ортогональной проекции нет угла обзора.

                    Как сказал молодой клон профессора из футурамы. Поймите двигатель не двигает корабль, двигатель двигает вселенную.
                    Так же и тут.

                    viewport по сути переводит ближнюю плоскость камеры в экранные координаты.
                    В viewport мы указываем окно или лучше рамки в которых будет отображаться результат растеризации.

                    Цитата Serafim @
                    В результате получаем примерно вот такое:

                    Картинка не правильная. glOrto и glPerpective это два вида проекции от сюда у вас и путаница. Отсюда имеет два вида камер.


                    Вам надо разделить термины на два лагеря.
                    Термины предметной области и термины OpenGl для реализации первых.
                    Как переменные и типы.
                    К примеру
                    ExpandedWrap disabled
                      var
                        Boy, Girl: TBody;
                      переменные:
                        Мальчик, Девочка: Человек;

                    1)
                    Так вот терминам предметной области стоит отнести следующие понятия: сцена, камера, объект, видовое окно.

                    2)
                    glOrto, glPerspective, матрицы, glViewport это инструмент для реализации понятий описанных в первой группе.

                    Надо структурировать подход к разработке выделив объекты Сцена, камера, объект.
                    И в дальнейшем при создании рендера работать уже с ними. А вот для реализации методов, свойств этих объектов использовать opengl.

                    Не старайтесь охватить это одновременно.
                    Сообщение отредактировано: Pavia -
                      Ну я пытаюсь перейти от высокоуровневых реализаций (движков) до низкоуровневого апи, отсюда такая путаница, когда я вместо инструмента оперирую целым понятием (реализацией некой сущности), есть такое :rolleyes:
                        Так-с, вроде понятно, что ортогональная проекция и перспективная - немного разные, взаимозаменяемые штуки. На картинке, камера есть ни что иное, как perspective, а ortho - ортогональная.

                        Есть вот такой пример, более или менее понятный и максимально облегчённый:

                        ExpandedWrap disabled
                          GL11.glMatrixMode(GL11.GL_PROJECTION);
                          GL11.glLoadIdentity();
                          //GL11.glOrtho(-10, 10, -10, 10, 10, -10);
                          GLU.gluPerspective(65.0f, (float)(8.0/6.0), 0.1f, 100.0f);
                          GL11.glMatrixMode(GL11.GL_MODELVIEW);
                          GL11.glViewport(0, 0, 800, 600);
                           
                           
                          while (!Display.isCloseRequested()) {
                              GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
                              GL11.glColor3f(.5f, .5f, 1.0f);
                           
                              GL11.glBegin(GL11.GL_TRIANGLES);
                                  GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
                                  GL11.glVertex3f(-1.0f,-1.0f, 0.0f);
                                  GL11.glVertex3f( 1.0f,-1.0f, 0.0f);
                              GL11.glEnd();
                           
                           
                              Display.update();
                          }


                        Если использовать glOrtho, то всё ок, если переключиться на gluPerspective, то экран пустой.

                        Думал что это из-за того, что near перспективы 0.1, а треугольник рисуется за границей отсечки (на 0.0). Поигравшись с позицией по Z понял, что нет. Скорее всего что-то пропустил, что-то существенное, а именно координатную сетку, которую я задавал ранее с помощью glOrtho. Или ещё что-то?

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

                        Добавлено
                        Если учитывать эту логику:
                        Цитата Pavia @
                        1)
                        Так вот терминам предметной области стоит отнести следующие понятия: сцена, камера, объект, видовое окно.

                        и
                        Цитата Pavia @
                        2)
                        glOrto, glPerspective, матрицы, glViewport это инструмент для реализации понятий описанных в первой группе.

                        то получаем то, что камеры без сцены не может существовать, по-этому пробовал использовать одновременно и perspective и ortho, но результат не меняется.

                        Добавлено
                        Цитата Pavia @
                        Надо структурировать подход к разработке выделив объекты Сцена, камера, объект.
                        И в дальнейшем при создании рендера работать уже с ними. А вот для реализации методов, свойств этих объектов использовать opengl.

                        пока не хочется разносить всё на объекты и абстрагироваться от opengl вызовов, надо вкурить базис, а потом уже начинать развлекаться, иначе абстракция получится костыльная. По-этому стараюсь пока писать максимально лаконичные процедурные шняжки, имея на экране минимальный работоспособный функционал, поигравшись с ним уже вводить новые методы и разделять уже более-менее готовое для выноса.
                          Цитата Serafim @
                          GLU.gluPerspective(65.0f, (float)(8.0/6.0), 0.1f, 100.0f);


                          Цитата

                          zNear

                          The distance from the viewer to the near clipping plane (always positive).
                          zFar

                          The distance from the viewer to the far clipping plane (always positive).


                          ExpandedWrap disabled
                                    GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
                                    GL11.glVertex3f(-1.0f,-1.0f, 0.0f);
                                    GL11.glVertex3f( 1.0f,-1.0f, 0.0f);

                          Т.е. Уже ошибка мы не видим треугольник так как он не попадает во внутрь усечённой пирамиды.
                          Надо
                          ExpandedWrap disabled
                             
                                    GL11.glVertex3f( 0.0f, 1.0f, 1.0f);
                                    GL11.glVertex3f(-1.0f,-1.0f, 1.0f);
                                    GL11.glVertex3f( 1.0f,-1.0f, 1.0f);


                          Но лучше просто glTransform(0,0,-Near); Тогда все точки подвинуться. Что принципе будет выражаться перемещения центра камеры. Фокус будет выходить за камеру, находится позади неё.
                            Цитата Pavia @
                            Т.е. Уже ошибка мы не видим треугольник так как он не попадает во внутрь усечённой пирамиды.

                            Цитата Serafim @
                            Думал что это из-за того, что near перспективы 0.1, а треугольник рисуется за границей отсечки (на 0.0). Поигравшись с позицией по Z понял, что нет.

                            Как следствие единица тоже не работает (пробовал 10 и 50, сейчас проверил с единицей).

                            Добавлено
                            С транслейтом тоже пусто, что на отрицательные значения, что на положительные. Смена fov тоже ничего не даёт.

                            Добавлено
                            Надо было вызвать
                            ExpandedWrap disabled
                              GL11.glLoadIdentity();
                            после очистки экрана. Пользуясь случаем, хочу спросить, что она делает. Написано что сбрасывает матрицу до дефолтной, чтоб пересчитало. Но что считать тогда дефолтной? До чего оно сбрасывает? :wacko:
                              Цитата Serafim @
                              L11.glLoadIdentity();parseOne('code_8','java',false) после очистки экрана.

                              Вы отменили GL11.glViewport(0, 0, 800, 600);

                              Забыл сказать что при использование glViewport надо ещё правильно размеры фигур высчитать. Вроде как в 800 раз увеличить.

                              glLoadIdentity
                              Присваивает текущей матрице единичную матрицу.
                              1 0 0 0
                              0 1 0 0
                              0 0 1 0
                              0 0 0 1

                              OpenGl не оперирует понятиями объект, сцена. Он оперирует матрицами. И честно математика оторванная от жизни.
                              Сообщение отредактировано: Pavia -
                                Цитата Pavia @
                                Забыл сказать что при использование glViewport надо ещё правильно размеры фигур высчитать. Вроде как в 800 раз увеличить.

                                Вроде как всё нормально работает:
                                Прикреплённая картинка
                                Прикреплённая картинка


                                Цитата Pavia @
                                Вы отменили GL11.glViewport(0, 0, 800, 600);

                                Если указать вьюпорт в два раза меньше, то результат (треугольник) соответственно рисуется в два раза меньше. :-? Ничего вроде не отменяется.

                                Цитата Pavia @
                                glLoadIdentity
                                Присваивает текущей матрице единичную матрицу.

                                Ну так вроде я не применял никаких матриц преобразований (по крайней мере явно). Разве что glTranslatef в моём примере, если думать логично, должен накладывать матрицу:

                                ExpandedWrap disabled
                                  -6  0  0 0
                                   0 -6  0 0
                                   0  0 -6 0
                                   0  0  0 1
                                Сообщение отредактировано: Serafim -
                                  Цитата Serafim @
                                  Ну так вроде я не применял никаких матриц преобразований

                                  Как работает OpenGL?

                                  ExpandedWrap disabled
                                    GL11.glMatrixMode(GL11.GL_PROJECTION);
                                    GL11.glLoadIdentity();
                                    //GL11.glOrtho(-10, 10, -10, 10, 10, -10);
                                    GLU.gluPerspective(65.0f, (float)(8.0/6.0), 0.1f, 100.0f);
                                    GL11.glMatrixMode(GL11.GL_MODELVIEW);
                                    GL11.glViewport(0, 0, 800, 600);
                                     
                                     
                                    while (!Display.isCloseRequested()) {
                                        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
                                        GL11.glColor3f(.5f, .5f, 1.0f);
                                     
                                        GL11.glBegin(GL11.GL_TRIANGLES);
                                            GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
                                            GL11.glVertex3f(-1.0f,-1.0f, 0.0f);
                                            GL11.glVertex3f( 1.0f,-1.0f, 0.0f);
                                        GL11.glEnd();
                                     
                                     
                                        Display.update();
                                    }


                                  Каждая функция преобразуется в команду которая записывается в список.
                                  Дойдя до Display.update(); Этот список отдаётся на исполнения.

                                  OpenGL представляет собой конвейер. Что такое конвейер?
                                  Это куча роликов на которых находится полета - доска такая.
                                  И она катится по этим роликам от одного конца комнаты к другому.
                                  Вдоль конвеера стоят рабочии. Первый рабочий кладёт половину корпуса на палету.
                                  Второй рабочий кладёт плату.
                                  Третий рабочий вставляет и прикручивает винткии. Скрепляя плату с корпусом.
                                  Четвертый рабочий кладет вторую половинку.
                                  Пятый рабочий соединяет две половинки, винтами.
                                  Шестой упаковывает в корпус.

                                  Так же и в OpenGL.
                                  Каждый обработчик получает список с командами и выполняет свою операцию.
                                  Первый обработчик разбивает ленту TRIANGLE_STRIP на триугольники.
                                  Второй обработчик выполняет преобразование координат.
                                  У него есть матрица MODELVIEW и он просто умножает вектора на эту матрицу. Как у рабочего отвертка так у этого обработчика матрица.

                                  Следующий обработчик выполняет перспективное преобразование. Т.е. умножает на перспективную матрицу и делит первые три координаты на последнюю x/w, y/w, z/w.


                                  В конвейере есть много всего. И матрицы присутствуют всегда. Притом не одна.
                                  Про конвейер лучше посмотреть в спецификации 1.3
                                  https://www.opengl.org/registry/doc/glspec14.pdf

                                  В современных части конвейера заменены шейдерами.
                                  https://www.opengl.org/registry/doc/glspec4...re.20120806.pdf
                                    Цитата Pavia @
                                    У него есть матрица MODELVIEW и он просто умножает вектора на эту матрицу. Как у рабочего отвертка так у этого обработчика матрица.

                                    Следующий обработчик выполняет перспективное преобразование. Т.е. умножает на перспективную матрицу и делит первые три координаты на последнюю x/w, y/w, z/w.


                                    В конвейере есть много всего. И матрицы присутствуют всегда. Притом не одна.

                                    Таки одна. World, View и Proj перемножаются заранее, по крайней мере так в DirectX, и я очень сомневаюсь, что в OpenGL не так, это просто было бы непрактично.
                                    Другие матрицы есть, но это уже матрицы, не относящиеся к трансформации геометрии, например, трансформация текстурных координат.
                                    Сообщение отредактировано: Mikle -
                                      Ох, вот это рассказ целый :D И ссылочки очень крутые, я дальше вики пока не добирался, а тут целый Клондайк :good:

                                      Единственное пока непонятно, стоит ли мне дальше вдаваться в историю (версия 1.1) или стоит браться сразу за более-менее современные 3.2+\ES2.0+ (если не путаю). Там АПИ местами отличается, мне, как ньюблу, приходится иногда недоумевать, например почему задепрекейтили fbo, крутая штука была.

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

                                      Добавлено
                                      Цитата Mikle @
                                      Таки одна. World, View и Proj перемножаются заранее, по крайней мере так в DirectX, и я очень сомневаюсь, что в OpenGL не так, это просто было бы непрактично.

                                      я в курсе наличия лишь view и proj, по крайней мере они точно есть.

                                      Добавлено
                                      Раз уж начали про матрицы, есть ли вариант как-то покидаться вменяемыми ссылками (или объяснениями) на смысл существования оных, обычно всё описывается лаконичными "а давайте применим, чтоб преобразовать\привести к ..." без подробностей? Чисто теоретически я могу представить зачем они, точнее только одна, а вот отличия и смысл иметь их столько - хоть убей.

                                      Добавлено
                                      Цитата Serafim @
                                      точнее только одна

                                      Её описал Pavia
                                      Цитата Pavia @
                                      Следующий обработчик выполняет перспективное преобразование.


                                      Добавлено
                                      хотя в теории, помимо преобразования к нужной перспективе - ещё должна быть матрица поворота :rolleyes:

                                      Добавлено
                                      лучше не буду выдумывать своих сущностей, а подожду опровержений моих теорий от знатоков :blush:

                                      Добавлено
                                      Цитата Pavia @
                                      Следующий обработчик выполняет перспективное преобразование. Т.е. умножает на перспективную матрицу и делит первые три координаты на последнюю x/w, y/w, z/w.

                                      вот тут https://en.wikipedia.org/wiki/Graphics_pipeline написано что перспективное преобразование - это деление x/z, y/z для каждой вершины :unsure: что-то я запутался совсем :crazy:
                                      Сообщение отредактировано: Serafim -
                                        В DirectX 3 матрицы в OpenGL их тоже 3.
                                        В DirectX ViewModel обозвана как World.
                                        Во время программирования можно их всегда считать и независимо изменять. LoadIndenty сбрасывает только одну из них, текущую. Такое разделение нужно для удобства. Перспективная матрица отвечает за камеру. А матрица модели за объекты сцены.

                                        По поводу рациональности. Чтобы каждый раз не вычислять, не делать умножения матриц. Во время выполнения графический движок создаёт общую матрицу, путем перемножения этих 3-х матриц OGL.

                                        x/z, y/z Это упрощённо на Z. Если выводить перспективное преобразование, то там будет X/(1+Z). Эту единицу хранят в 4-координате и берегут как зеницу ока.
                                        Потом для Z-буффера Z надо отнормировать Z/(Far- Near).
                                        Поэтому эти две операции объединяют.
                                        Доказательство Формула в OpenGL с делением на w


                                        Есть такое определение алгебра - это умение жонглировать формулами. В ком.графике очень много математики и она сложная. Её пробуют всячески упростить.

                                        К примеру, разделяй и властвуй. Поэтому и делят на две матрицы. Так проще так удобнее. К примеру у вас есть игрушка снайпер. При переключение с обычного вида на прицел изменяется угол fov камеры. Потом матрицы перемножаются. А если бы не было матрицы, то пришлось бы выполнить цикл из методов translate, rotate (перемещение, вращение) Что очень долго бы работало. А так хранят две матрицы и можно быстро переключится.

                                        Но зачастую такое упрощение математики основано на аналогии, семантики, и интуитивном понятии команд. Но зачастую такое упрощение только вносит недопонимание.

                                        Некто не хочет работать с формулами дольше 5 минут. Поэтому и пишут сделаем так. Что-бы не разводить объяснения на страницы. Но в принципе такие книги есть.
                                        К примеру:
                                        Математические методы компьютерной графики.
                                        Хотя в моей любимой книжке данный материал уложен максимум в 10 страниц.
                                        Сообщение отредактировано: Pavia -
                                        1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                        0 пользователей:


                                        Рейтинг@Mail.ru
                                        [ Script execution time: 0,1158 ]   [ 18 queries used ]   [ Generated: 17.07.25, 23:10 GMT ]