
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
![]() |
Сообщ.
#1
,
|
|
Тут буду постить мелкие вопросы по OpenGL (на абстрактном ЯП), ответ на которые либо не понял, либо понял, но не до конца, либо вообще не нашёл в интернетах.
1) В чём отличие задавать меши с помощью вершинного шейдера: ![]() ![]() 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); И с помощью нативных вызовов: ![]() ![]() 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+. Просто совмещал примеры вообще на разных языках =) |
Сообщ.
#2
,
|
|
|
При модификации координат при вращение анимации и других расчётах
Шейдоры работают на GPU, begin-end на CPU. Плюс на CPU можете модифицировать длину массива, а на GPU только с шейдеров 5 версии. begin-end он как бы не для точек. А для динамически изменяющейся сцены. А шейдоры для статики. Или есть технология предварительного расчёта. На begin-end больше возможностей, на шейдерах зависит от версии . |
![]() |
Сообщ.
#3
,
|
|
Цитата Pavia @ Плюс на CPU можете модифицировать длину массива, а на GPU только с шейдеров 5 версии. хмхм? Имеется ввиду кидать в шейдер больше чем v4f за раз? |
Сообщ.
#4
,
|
|
|
Давай немного проясним вопрос. Вас интересует конкретная предметная область вывод точки? Или вместо точек любой другой примитив к примеру мэшь?Т.е. вас интересует конкретный пример или интересуют потенциальные возможности OpenGL?
Почему есть два метода? Пожалуй это дело вкуса кто-то ест рис ложкой, ктото вилкой, а иные палочками. Есть старый метод, есть новый. У каждого есть свои ограничения. Для 3-х точек они не принципиальны. Правда стоит сказать чтр второй пример ужастный. Вместо того что-бы сразу отдать на обработку весь массив из N точек он дёргает по одной точке. Запомните групповые операции работают быстрее. В данном случае такой подход сбивает движёк opengl, но не сильнее чем в примере с begin-end. |
![]() |
Сообщ.
#5
,
|
|
Цитата Pavia @ Вас интересует конкретная предметная область вывод точки? Или вместо точек любой другой примитив к примеру мэшь? насколько я понял по примерам - отличия только в способе рендера, в моём случае POINTS, но ничего не мешает мне заменить на QUADS или лучше даже TRIANGLE_STRIP (но тогда надо либо всё поместить между begin\end, либо вызвать drawArrays только один раз), так что нет. В моём случае не стоило применять термин "меш", т.к. в примере это всё же просто точки. Цитата Pavia @ Т.е. вас интересует конкретный пример или интересуют потенциальные возможности OpenGL? Второе; Пример - это лишь частный случай в попытке понять возможности и разобраться с АПИ. Цитата Pavia @ Вместо того что-бы сразу отдать на обработку весь массив из N точек он дёргает по одной точке. Запомните групповые операции работают быстрее. Это для того, что бы пример походил на первый, конечно же, в реальной жизни я написал бы все три точки между begin\end ![]() |
Сообщ.
#6
,
|
|
|
Цитата Serafim @ Вроде бы у шейдеров есть некоторые затруднения с QUADS'ами. Так что безопаснее через TRIANGLE_STRIP прокрутить, если что. в моём случае POINTS, но ничего не мешает мне заменить на QUADS или лучше даже TRIANGLE_STRIP ![]() |
![]() |
Сообщ.
#7
,
|
|
2) Eсть функция\метод gl.ortho он определяет координатную сетку, например:
![]() ![]() 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х ![]() |
Сообщ.
#8
,
|
|
|
Цитата Serafim @ Кому - как: рисуя QUADS'ы я всё время жду, что нарисуется честная билинейная гладкая поверхность, но все движки/дрова так сделаны, что рисуется то одна, то другая пара треугольников. да и просто квадраты - это изврат. ![]() |
Сообщ.
#9
,
|
|
|
Цитата Serafim @ Это просто абстрактные координаты, Слово абстрактные тут не к месту. Абстракция это по сути общение нескольких реализаций. Выделения общего для всех вариантов. А где тут обобщение? Цитата Serafim @ случае нулевой камеры). Верно? Да. Цитата Serafim @ В этом случае камера (пока опустим реализацию) - точка взгляда на эту систему координат с отсечением по near и far и наличием угла обзора (fov). Так? Несуществует такого понятия как "точка взгляда". Есть точка положения камеры и вектор направления взгляда. У ортогональной проекции нет угла обзора. Как сказал молодой клон профессора из футурамы. Поймите двигатель не двигает корабль, двигатель двигает вселенную. Так же и тут. viewport по сути переводит ближнюю плоскость камеры в экранные координаты. В viewport мы указываем окно или лучше рамки в которых будет отображаться результат растеризации. Цитата Serafim @ В результате получаем примерно вот такое: Картинка не правильная. glOrto и glPerpective это два вида проекции от сюда у вас и путаница. Отсюда имеет два вида камер. Вам надо разделить термины на два лагеря. Термины предметной области и термины OpenGl для реализации первых. Как переменные и типы. К примеру ![]() ![]() var Boy, Girl: TBody; переменные: Мальчик, Девочка: Человек; 1) Так вот терминам предметной области стоит отнести следующие понятия: сцена, камера, объект, видовое окно. 2) glOrto, glPerspective, матрицы, glViewport это инструмент для реализации понятий описанных в первой группе. Надо структурировать подход к разработке выделив объекты Сцена, камера, объект. И в дальнейшем при создании рендера работать уже с ними. А вот для реализации методов, свойств этих объектов использовать opengl. Не старайтесь охватить это одновременно. |
![]() |
Сообщ.
#10
,
|
|
Ну я пытаюсь перейти от высокоуровневых реализаций (движков) до низкоуровневого апи, отсюда такая путаница, когда я вместо инструмента оперирую целым понятием (реализацией некой сущности), есть такое
![]() |
![]() |
Сообщ.
#11
,
|
|
Так-с, вроде понятно, что ортогональная проекция и перспективная - немного разные, взаимозаменяемые штуки. На картинке, камера есть ни что иное, как perspective, а ortho - ортогональная.
Есть вот такой пример, более или менее понятный и максимально облегчённый: ![]() ![]() 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 вызовов, надо вкурить базис, а потом уже начинать развлекаться, иначе абстракция получится костыльная. По-этому стараюсь пока писать максимально лаконичные процедурные шняжки, имея на экране минимальный работоспособный функционал, поигравшись с ним уже вводить новые методы и разделять уже более-менее готовое для выноса. |
Сообщ.
#12
,
|
|
|
Цитата 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). ![]() ![]() 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.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); Тогда все точки подвинуться. Что принципе будет выражаться перемещения центра камеры. Фокус будет выходить за камеру, находится позади неё. |
![]() |
Сообщ.
#13
,
|
|
Цитата Pavia @ Т.е. Уже ошибка мы не видим треугольник так как он не попадает во внутрь усечённой пирамиды. Цитата Serafim @ Думал что это из-за того, что near перспективы 0.1, а треугольник рисуется за границей отсечки (на 0.0). Поигравшись с позицией по Z понял, что нет. Как следствие единица тоже не работает (пробовал 10 и 50, сейчас проверил с единицей). Добавлено С транслейтом тоже пусто, что на отрицательные значения, что на положительные. Смена fov тоже ничего не даёт. Добавлено Надо было вызвать ![]() ![]() GL11.glLoadIdentity(); ![]() |
Сообщ.
#14
,
|
|
|
Цитата 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 не оперирует понятиями объект, сцена. Он оперирует матрицами. И честно математика оторванная от жизни. |
![]() |
Сообщ.
#15
,
|
|
Цитата Pavia @ Забыл сказать что при использование glViewport надо ещё правильно размеры фигур высчитать. Вроде как в 800 раз увеличить. Вроде как всё нормально работает: Прикреплённая картинка
Цитата Pavia @ Вы отменили GL11.glViewport(0, 0, 800, 600); Если указать вьюпорт в два раза меньше, то результат (треугольник) соответственно рисуется в два раза меньше. ![]() Цитата Pavia @ glLoadIdentity Присваивает текущей матрице единичную матрицу. Ну так вроде я не применял никаких матриц преобразований (по крайней мере явно). Разве что glTranslatef в моём примере, если думать логично, должен накладывать матрицу: ![]() ![]() -6 0 0 0 0 -6 0 0 0 0 -6 0 0 0 0 1 |
Сообщ.
#16
,
|
|
|
Цитата Serafim @ Ну так вроде я не применял никаких матриц преобразований Как работает OpenGL? ![]() ![]() 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 |
![]() |
Сообщ.
#17
,
|
|
Цитата Pavia @ У него есть матрица MODELVIEW и он просто умножает вектора на эту матрицу. Как у рабочего отвертка так у этого обработчика матрица. Следующий обработчик выполняет перспективное преобразование. Т.е. умножает на перспективную матрицу и делит первые три координаты на последнюю x/w, y/w, z/w. В конвейере есть много всего. И матрицы присутствуют всегда. Притом не одна. Таки одна. World, View и Proj перемножаются заранее, по крайней мере так в DirectX, и я очень сомневаюсь, что в OpenGL не так, это просто было бы непрактично. Другие матрицы есть, но это уже матрицы, не относящиеся к трансформации геометрии, например, трансформация текстурных координат. |
![]() |
Сообщ.
#18
,
|
|
Ох, вот это рассказ целый
![]() ![]() Единственное пока непонятно, стоит ли мне дальше вдаваться в историю (версия 1.1) или стоит браться сразу за более-менее современные 3.2+\ES2.0+ (если не путаю). Там АПИ местами отличается, мне, как ньюблу, приходится иногда недоумевать, например почему задепрекейтили fbo, крутая штука была. Пока я возьму за правило обнулять матрицы после каждых преобразований, чтоб ничего никуда не улетало, и иметь ввиду, что под капотом оно постоянно её(их) меняет. Добавлено Цитата Mikle @ Таки одна. World, View и Proj перемножаются заранее, по крайней мере так в DirectX, и я очень сомневаюсь, что в OpenGL не так, это просто было бы непрактично. я в курсе наличия лишь view и proj, по крайней мере они точно есть. Добавлено Раз уж начали про матрицы, есть ли вариант как-то покидаться вменяемыми ссылками (или объяснениями) на смысл существования оных, обычно всё описывается лаконичными "а давайте применим, чтоб преобразовать\привести к ..." без подробностей? Чисто теоретически я могу представить зачем они, точнее только одна, а вот отличия и смысл иметь их столько - хоть убей. Добавлено Цитата Serafim @ точнее только одна Её описал Pavia Цитата Pavia @ Следующий обработчик выполняет перспективное преобразование. Добавлено хотя в теории, помимо преобразования к нужной перспективе - ещё должна быть матрица поворота ![]() Добавлено лучше не буду выдумывать своих сущностей, а подожду опровержений моих теорий от знатоков ![]() Добавлено Цитата Pavia @ Следующий обработчик выполняет перспективное преобразование. Т.е. умножает на перспективную матрицу и делит первые три координаты на последнюю x/w, y/w, z/w. вот тут https://en.wikipedia.org/wiki/Graphics_pipeline написано что перспективное преобразование - это деление x/z, y/z для каждой вершины ![]() ![]() |
Сообщ.
#19
,
|
|
|
В 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 страниц. |