Перейти к содержимому


Свернуть чат Чат Открыть чат во всплывающем окне

Folgen : (вчера) Спс.
GranMinigun : (вчера) Готово. Добро пожаловать на форум, механоид.
GranMinigun : (вчера) Указать, кого именно активировать, например.
Гость : (2 дней назад) Активируйте акк. Хз, нужно что-либо указывать дополнительно для этого в чате, или админы сами всех подряд активируют, кто в очереди на активацию?
GranMinigun : (неделю назад) https://forums.unrea...sed-on-gis-data
Yakim (Watco... : (неделю назад) Аа да? Ну окей)
GranMinigun : (неделю назад) А это даже не обсуждается!
Yakim (Watco... : (неделю назад) А кто сказал что мы пьянели?)
GranMinigun : (неделю назад) Ну что, товарищи, протрезвели?
Yakim (Watco... : (2 недель назад) сяп)
Гость : (2 недель назад) Егорыч на праздники с каникул вернулся. За это тост! Всем маны!
lz : (3 недель назад) Наоборот.
Гость : (3 недель назад) Позвольте уточнить, для будущего наркомана прошлое это будущее или наоборот?
lz : (3 недель назад) Как ты его поймаешь, когда он знает, где ты его будешь ловить?
GranMinigun : (3 недель назад) Ловите наркомана из будущего!
PA3UJIb : (3 недель назад) С новым 2018 годом! А то старый-то 2018 мы и не видели даже
Yakim (Watco... : (3 недель назад) С наступающим)
Yakim (Watco... : (3 недель назад) гы
lz : (3 недель назад) Посоны, с наступающим всех!
Yakim (Watco... : (3 недель назад) +
lz : (3 недель назад) Много капитанства.
lz : (3 недель назад) +
Yakim (Watco... : (3 недель назад) ну такое
Gaantro : (3 недель назад) Описывает принцип работы.
Gaantro : (3 недель назад) Антиграв*
Gaantro : (3 недель назад) Система Grable в Star Citizen (Антигуа) : https://youtu.be/2VkzHbJiCAo
Yakim (Watco... : (3 недель назад) Ага :lol:
lz : (3 недель назад) Чё там у нас? Пошла жара? Главное, чтобы не такое генерилось https://youtu.be/RvAwB7ogkik
Moh : (3 недель назад) Мне, да привет? Ну привет )
Гость : (3 недель назад) И с Новым годом.
Гость : (3 недель назад) Шучу. От Крогота.
Гость : (3 недель назад) От Гостя.
Гость : (3 недель назад) Увидите моха передайте ему привет.
Yakim (Watco... : (3 недель назад) :lol: :P
lz : (3 недель назад) Лан, чё ты, нормально же общались, это нарицательное)
Yakim (Watco... : (4 недель назад) Еще и "Мехах" с маленькой буквы, бесстыжий :D
GranMinigun : (4 недель назад) Был.
lz : (4 недель назад) В мехах был такой рейтинг? Не помню уже.
lz : (4 недель назад) Опасный Яким)
Yakim (Watco... : (4 недель назад) За "маханойдов" и двор, стреляю в упор :D
GranMinigun : (4 недель назад) Я не это имел в виду!
Yakim (Watco... : (4 недель назад) :lol:
lz : (4 недель назад) За механойдов наверное.
lz : (4 недель назад) Всё, рубанул.
lz : (4 недель назад) Ща мы их.

Фотография
- - - - -

[Camera.hpp] - камера с реалистичными свойствами

OpenGL Camera FBO Deferred shading

  • Авторизуйтесь для ответа в теме
В этой теме нет ответов

#1 OFFLINE   Yandersen

Yandersen

    Диванный теоретик

  • Админ
  • 454 сообщений
  • Откуда:Canada
  • Настоящее имя:Ян

Отправлено 21 Апрель 2015 - 02:18

Класс камеры CCamera, реализующий перспективную проекцию с реалистичными свойствами (нет дальней плоскости отсечения, сверхмалая ближняя плоскость отсечения):

 

Camera.hpp

 

:!: Требует LoadGL.h, GLSL.hpp, Origin.hpp, FBO.hpp. Плюс необходима поддержка OpenGL4.5 (DSA, ARB_clip_control).

 

Кидаем файл в проект, подключаем:

#include "Camera.hpp"

Изменяем настройку glClipControl:

glClipControl(<...>, GL_ZERO_TO_ONE);

:!: С дефолтной настройкой (GL_NEGATIVE_ONE_TO_ONE) камера не будет работать корректно!

 

Каждая камера класса CCamera имеет свой собственный FBO и использует floating-point depth buffer (буффер глубины). Буффера трафарета (stencil buffer) нет. Цветовых буфферов может быть до 8. В качестве буфферов используются текстуры (создаются и удаляются классом CCamera):

GLuint CCamera::AddDepthBuffer(int Width, int Height, bool WithMipmaps = true);
GLuint CCamera::AddColorBuffer(unsigned ID, GLenum internalFormat,
                               int Width, int Height, bool WithMipmaps = true);

Width и Height - размеры требуемого буффера, флаг WithMipmaps определяет, будут ли у текстуры мипмапы (если false, то мипмапов не будет). В случае создания буффера цвета нужно указать индекс ID создаваемого буффера (0...7) и формат пикселя текстуры (значения internalFormat см. тут). Возвращённое значение - имя созданной текстуры или 0 если создать текстуру не удалось.

:!: Свойства текстуры позволяется менять (glTexPartameter), но изменять размеры или удалять - нельзя. Для удаления требуемого буффера используйте 0 в качестве аргумента Width или Height.

 

Для изменения размеров сразу всех буфферов используйте

bool CCamera::ResizeBuffers(int Width, int Height);

:!: Все свойства каждого из буфферов будут воссозданы, но имена текстур могут измениться.

Чтобы узнать имя текстуры конкретного буффера используйте

inline GLuint GetColorBufferTextureName(unsigned ID)const;
inline GLuint GetDepthBufferTextureName()const;

Эффективные размеры фреймбуффера равны минимуму размеров всех его буфферов. Узнать можно так:

inline ivec2 GetFrameSize()const;

Геометрические свойства камеры показаны на следующей схеме:

 

Camera.png

 

Используемая матрица перспективной проекции имеет следующий вид:

     | 2*zNear                      |
     | -------    0      0      0   |
     |  xSize                       |
     |         2*zNear              |
     |    0    -------   0      0   |
     |          ySize               |
 P = |                              |
     |    0       0      0    zNear |
     |                              |
     |                              |
     |    0       0     -1      0   |
     |                              |

Перспектива задаётся следующей функцией:

inline bool CCamera::SetupPerspective(float FOVy, float NearClippingPlane);

FOVy - угол обзора (по вертикали). NearClippingPlane - это расстояние до ближней плоскости отсечения (zNear на рисунке). FOVy должен быть больше 0 и меньше 180 градусов, а NearClippingPlane (zNear) - больше нуля. Геометрические размеры проекционной плоскости (xSize, ySize) будут вычислены автоматически и их отношение будет соответствовать отношению ширины и высоты фреймбуффера.

:!: При изменении размеров фреймбуффера размеры проекционной плоскости и zNear могут измениться, однако угол обзора по вертикали останется тем же.

 

Угол обзора можно менять так:

inline void CCamera::ChangeFOV(float FOVy);

Изменение угла обзора будет достигнуто за счёт приближения/удаления проекционной плоскости (изменение zNear); размеры проекционной плоскости (xSize, ySize) при этом останутся неизменными.

Узнать размеры проекционной плоскости можно так:

inline vec2 CCamera::GetPlaneSize()const;

Изменить размеры проекционной плоскости можно функцией SetPlaneSize, принимающей в качестве параметра желаемый размер проекционной плоскости - её текущие размеры будут отмасштабированы таким образом, что наибольшее из измерений станет равно заданной величине:

CCamera MyCamera;
... //Setup buffers, configure perspective
vec2 Dims = MyCamera.GetPlaneSize(); //Assume that Dims.x==640.f, Dims.y==480.f

float SquareApertureWidth = 0.01f; //Aperture has square shape, 1cm in width
MyCamera.SetPlaneSize(SquareApertureWidth);
Dims = MyCamera.GetPlaneSize(); //Dims.x==0.01f, Dims.y==0.0075f

:!: zNear при этом изменится, а угол обзора останется прежним.

 

Расстояние до проекционной плоскости (ближняя плоскость отсечения, zNear) читается так:

inline float CCamera::GetNearClippingPlane()const;

Угол обзора по диагонали всегда больше угла обзора по вертикали. Узнать его можно так:

float CCamera::GetViewAngleMax()const;

:!: Половина этого значения - это угол между высотой и образующей конуса видимости, в который вписана усечённая пирамида видимого камерой объёма.

 

Класс CCamera содержит указатель на объект класса COriginf (система координат). Ориентация камеры в пространстве привязана к ориентации системы координат Origin. Если указателя нет, то используется ориентация по-умолчанию: Ox={1,0,0}, Oy={0,1,0},Oz={0,0,1}, Center={0,0,0}.

Направление взгляда - это ось -Oz, направление направо - ось Ox, вверх - Oy. Узнать направление взгляда можно так:

inline vec3 CCamera::GetViewDirection()const;

Узнать координаты вектора, соответствующего направлению от центра координат до пикселя фреймбуффера с указанными координатами можно так:

inline vec3 CCamera::PixelToRay(const ivec2& PixelCoordinates)const;

:!: Учтите, что перед вычислением этого направления указанные координаты пикселя будут ограничены нулём, шириной и высотой фреймбуффера.

 

CCamera умеет работать с тремя матрицами:

mat4 ModelViewMatrix: трансформация из мировой системы координат в систему координат камеры (поворот, смещение);

mat4 ProjectionMatrix: из системы координат камеры в проеционное пространство (проекция);

mat4 TransformationMatrix: из мировой системы координат в проекционное пространство (поворот, смещение, проекция).

А также соответствующими им обратными матрицами ModelViewMatrixInverse, ProjectionMatrixInverse, TransformationMatrixInverse.

Конструируют эти матрицы следующие функции класса:

//Return ModelView matrix
inline mat4 CCamera::GetModelViewMatrix()const;
//Return Inverse of the ModelView matrix
inline mat4 CCamera::GetModelViewMatrixInverse()const;
//Return the Projection matrix
mat4 CCamera::GetProjectionMatrix()const;
//Return inverse of the Projection matrix
mat4 CCamera::GetProjectionMatrixInverse()const;
//Return the full transformation matrix
inline mat4 CCamera::GetTranformationMatrix()const;
//Return inverse of the full transformation matrix
inline mat4 CCamera::GetTranformationMatrixInverse()const;

Перенаправляем рендер во фреймбуффер требуемой камеры так:

inline void CCamera::StartCapturing()const;

Очистка буфферов:

//Clear one of the color buffers (it's index is specified as BufferID); color
//must be specified as vec4, ivec4 or uvec4
template<class T>
inline void CCamera::ClearColorBuffer(unsigned int ID, const T& tvecRGBA);
//Clear all of the color buffers simultaneously with the same value
inline void CCamera::ClearColorBuffers(const vec4& vecRGBA){ FBO.ClearColor(vecRGBA); }
//Clear the depth buffer
inline void CCamera::ClearDepthBuffer(GLfloat Value=0.f){ FBO.ClearDepth(Value); }
//Clear all of the color buffers and the depth buffer
inline void CCamera::ClearBuffers(const vec4& ColorRGBA, float Depth=0.f);

По оканчании рендера скопировать картинку на экран можно с помощью этой функции:

inline void CCamera::ShowFrame(unsigned ColorBufferID=0,
                               GLint ScreenWidth=0, GLint ScreenHeight=0)const;

Тут ColorBufferID - индекс буффера цвета, в котором находится желаемое изображение. ScreenWidth, ScreenHeight - размеры экрана: если указаны (отличны от нуля), то картинка будет растянута/сжата под размер экрана; если же размер экрана не указан, то копирование пойдёт пиксель-в-пиксель, и если размеры фреймбуффера камеры и экрана не равны, картинка либо обрежется, либо не замостит весь экран.







Темы с аналогичным тегами OpenGL, Camera, FBO, Deferred shading

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных