Пытаясь понять свет на Opengl, как имитировать реалистичный солнечный свет?

13

Я не знаю, делаю ли я что-то неправильно или что-то пропускаю, но я хочу имитировать солнечный свет, как в солнечный день.

Когда объект направлен на направленный свет, он хорошо освещен и там нет проблем. Если я обойду объект и посмотрю на него, оно темное. Это не слишком темно, потому что я использую, GL_AMBIENTно все еще слишком темно для солнечного дня. Если я увеличу значение, оно никогда не будет выглядеть лучше, потому что сторона объекта, обращенная к свету, будет слишком яркой.

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

Фронт объекта: http://i.stack.imgur.com/YW53X.png Фронт
объекта: http://i.stack.imgur.com/Qufha.png

Как вы можете легко видеть, лицевая сторона выглядит хорошо, вы можете увидеть форму этой красной вещицы. С обратной стороны, это просто, вы не можете увидеть ту же форму.

Теперь я знаю, что смотрю на заднюю часть объекта и смотрю в направлении света, и он должен быть темнее передней стороны. Но это не должно выглядеть так просто. Это не то, что мы видим, когда идем против солнечного света, глядя на какой-то объект, мы видим, что объекты формируют некоторую форму.

Как я могу иметь такой же (или похожий) эффект на OpenGL?

Мой свет в настоящее время определяется так:

float posLight0[4] = {-1.0f, 1.0f, 1.0f, 0.0f};
float ambLight0[4] = {0.5f, 0.5f, 0.5f, 0.5f};

glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight0);
rfgamaral
источник
Я предлагаю вам рассмотреть возможность использования шейдеров, если это возможно. В конвейере с фиксированными функциями OpenGL используется довольно простая модель освещения, тогда как шейдеры дают вам полный контроль над математикой.
Невероятный монах

Ответы:

11

При окружающем освещении ваши объекты кажутся слишком яркими, поскольку рассеянный свет добавляется к окружающему освещению, а рассеянный свет по умолчанию равен 1,0. Это добавляет до 1,5, и все выше 1,0 зажимается. Установите рассеянный свет на 0,5:

float difLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, difLight0);

Вторая проблема труднее решить. Вы можете попробовать добавить некоторые мелкие детали к поверхности, такие как текстура или карта рельефа. В OpenGL окружающий свет постоянен, но в реальном мире это не так. Чтобы моделировать реальный мир, необходима некоторая форма решения глобального освещения . Окружающая окклюзия здесь очень помогает, но ее сложнее реализовать, чем просто установка состояний OpenGL. Вы можете испечь эмбиентную окклюзию к вершинам вашей модели в программном обеспечении для трехмерного моделирования или использовать SSAO , но я не буду вдаваться в подробности.

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

Также рассмотрите возможность добавления бликов в ваше приложение. Это сделает объекты блестящими.

float specLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specLight0);
glMaterialfv(GL_FRONT, GL_SHININESS, 10.0f); // Shininess between 0 and 128

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

msell
источник
Так что в OpengGL нет простого и прямого способа сделать то, что я хочу ... Жаль. Может быть, я попробую добавить другой источник света, но как именно я могу указать интенсивность света?
rfgamaral
GL_SPECULARИ , GL_SHININESSкажется, не производят никакого эффекта , хотя ... Я сделал изменения , glMaterialfvчтобы , glMaterialiпотому что не компиляции. А также пробовал большее значение, как 128. Мне это выглядит одинаково ... Может быть, проблема в моей загруженной модели (obj / mtl), придется взглянуть.
rfgamaral
1
@Nazgulled Только что проверил, что light0 specular по умолчанию равен 1.0, но материал specular по умолчанию равен 0.0. Так что измените glLightfv (GL_LIGHT0, GL_SPECULAR, specLight0); в glMaterialfv (GL_FRONT, GL_SPECULAR, specLight0); Также хорошо установить glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); или зеркальное отражение может быть неправильно рассчитано при вращении камеры.
msell
1
@Nazgulled Для вторичного света, установите ambient и specular на ноль и небольшое значение, например 0.2, для diffuse. Вы также можете установить окружающее освещение всех источников на ноль и использовать вместо него глобальное окружающее с GL_LIGHT_MODEL_AMBIENT.
msell
2

Окружающее освещение OpenGL - один цвет, но окружающее освещение в реальном мире обычно ярче сверху и темнее снизу. Вы можете приблизить это в OpenGL, установив окружающий свет очень темно-синим и добавив темно-синий направленный свет, направленный вниз. Это, плюс яркий белый направленный свет, идущий от того места, где солнце, может очень хорошо приближаться к освещению на открытом воздухе.

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

bmcnett
источник
1

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

NotaBene
источник