Форум программистов, компьютерный форум, киберфорум
DirectX
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30

Неполадки с точечным светом/нормалями

26.07.2015, 17:23. Показов 1500. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день всем! У меня проблема с реализацией точечного освещения в DX11, может я не очень хорошо разбираюсь в этой области, но мне нужна Ваша помощь/консультация.
Конкретно у меня есть сфера, которая вращается вокруг своей оси и на неё падает свет. Но освещается она неправильно: сначала по нарастанию начинает освещаться одна сторона сферы, потом затухает, и начинает освещаться другая, в общем как-то странно, в чем конкретно проблема я докумекать сам так и не сумел. Прилагаю скриншоты, код шейдеров, которые могут повлиять на освещение, и код загрузки 3д объекта сферы с нормалями и текстурными координатами (может проблема в загрузке нормалей)

Код подгрузки 3д объекта сферы:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Assimp::Importer importer;
    const aiScene* spherescene = importer.ReadFile("sphere.obj", 
        aiProcess_CalcTangentSpace |
        aiProcess_Triangulate |
        aiProcess_JoinIdenticalVertices |
        aiProcess_MakeLeftHanded |
        aiProcess_FlipUVs |
        aiProcess_FlipWindingOrder |
        aiProcess_FindInvalidData
        );
 
    buffers = new Buffers[1];
    buffers[0].vertexcount = spherescene->mMeshes[0]->mNumVertices;
    buffers[0].indexcount = (spherescene->mMeshes[0]->mNumFaces * spherescene->mMeshes[0]->mFaces->mNumIndices) * 2;
    buffers[0].vertices = new Vertex[buffers[0].vertexcount];
    
    for (int i = 0; i < buffers[0].vertexcount; i++)
    {
        buffers[0].vertices[i].Pos = XMFLOAT3(spherescene->mMeshes[0]->mVertices[i].x, spherescene->mMeshes[0]->mVertices[i].y, spherescene->mMeshes[0]->mVertices[i].z);
        buffers[0].vertices[i].Tex = XMFLOAT2(spherescene->mMeshes[0]->mTextureCoords[0][i].x, spherescene->mMeshes[0]->mTextureCoords[0][i].y);
        buffers[0].vertices[i].Norm = XMFLOAT3(spherescene->mMeshes[0]->mNormals[i].x, spherescene->mMeshes[0]->mNormals[i].y, spherescene->mMeshes[0]->mNormals[i].z);
    }
 
    buffers[0].indices = new WORD[buffers[0].indexcount];
    int j = 0;
    for (int i = 0; i < spherescene->mMeshes[0]->mNumFaces; i++)
    {
        buffers[0].indices[j] = spherescene->mMeshes[0]->mFaces[i].mIndices[0];
        buffers[0].indices[j+1] = spherescene->mMeshes[0]->mFaces[i].mIndices[2];
        buffers[0].indices[j+2] = spherescene->mMeshes[0]->mFaces[i].mIndices[1];
 
        buffers[0].indices[j+3] = spherescene->mMeshes[0]->mFaces[i].mIndices[0];
        buffers[0].indices[j+4] = spherescene->mMeshes[0]->mFaces[i].mIndices[1];
        buffers[0].indices[j+5] = spherescene->mMeshes[0]->mFaces[i].mIndices[2];
        j += 6;
    }
Код шейдеров:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//--------------------------------------------------------------------------------------
// Вершинные шейдеры
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input)
{   
    PS_INPUT output = (PS_INPUT)0;
    output.Pos = mul( input.Pos, World );
    output.worldPos = output.Pos;
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );
    output.Norm = mul(input.Norm, World);
//  float PI = 3.141592654f;
    output.Tex = input.Tex;
    return output;
}
//--------------------------------------------------------------------------------------
// Пиксельные шейдеры
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT input) : SV_Target
{
    float cutoff = 0.005f;
    float lightRadius = 100000.0f;
    float4 lightColor = float4(1.0f, 1.0f, 1.0f, 1.0f);
    float3 lightCenter = float3(400.0f, 0.0f, 0.0f);
    float4 diffuse = txDiffuse.Sample(samLinear, input.Tex);
    float r = lightRadius;
    float3 L = lightCenter - input.worldPos;
    float distance = length(L);
    float d = max(distance - r, 0);
    L /= distance;
    float denom = d/r + 1;
    float attenuation = 1 / (denom*denom);
    attenuation = (attenuation - cutoff) / (1 - cutoff);
    attenuation = max(attenuation, 0);
     
    float dt = max(dot(L, input.Norm), 0);
    return diffuse * lightColor * dt * attenuation;
}
Миниатюры
Неполадки с точечным светом/нормалями   Неполадки с точечным светом/нормалями  
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.07.2015, 17:23
Ответы с готовыми решениями:

TOpenGLControl. Косяк с нормалями?
При отображении фигур (куб, треугольники) с использованием компонента TOpenGLControl происходит неправильная передача освещённости. ...

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

Сложности с формированием массива с нормалями
Всем привет! Возникли сложности с формированием буфера, в котором будут нормали. Делаю по уроку: https://habr.com/ru/post/333932/ ...

10
61 / 54 / 21
Регистрация: 19.10.2013
Сообщений: 117
28.07.2015, 20:31
Обычно солнечное освещение считают параллельным и незатухающим. В этом случае пиксельный шейдер значительно проще чем у Вас.

ln = float4(0, 1, 0, 0); //Откуда светит солнце
float dt = dot(input.Norm, normalize(ln));
float4 diffuse = txDiffuse.Sample(samLinear, input.Tex);
return float4(dt * diffuse);
1
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
28.07.2015, 22:16  [ТС]
Цитата Сообщение от KolDub Посмотреть сообщение
В этом случае пиксельный шейдер значительно проще чем у Вас
Насчет этого аспекта Вы верно подметили, за что спасибо.
Но с другой стороны опробовав приведенный Вами способ ничего не изменилось. Все же проблема с сответствием нормалей к вершинам скорее всего.

Попробую как-то подробнее описать как именно освещается планетка у меня: она вращается; вначале освещается одна ее половина, после чего когда она прокрутилась примерно градусов на 45, начинает затухать РАВНОМЕРНО И ПОЛНОСТЬЮ ВСЯ половина которая освещалась, а потом начинает освещаться другая. (такое впечатление будто нормали всего две: для двух половин сферы, но я проверял через разные 3д виюверы: нормали есть у каждого треугольника, и освещение в порядке)
0
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
28.07.2015, 22:26  [ТС]
Поправка: поставил брейкпоинт на момент загрузки нормалей: в меше значения присутствуют, но в структуру почему-то не загружаются. Скрин прилагаю.
Миниатюры
Неполадки с точечным светом/нормалями  
0
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
28.07.2015, 22:34  [ТС]
А нет, вывел значения нормалей в файл, все имеется, но что за фигня тогда происходит, помогите(
0
61 / 54 / 21
Регистрация: 19.10.2013
Сообщений: 117
29.07.2015, 09:57
В исходнике Вы не привели структуры входных и выходных параметров вершинного шейдера.
Подозреваю, что размерность нормалей у Вас float3.
Если это так, попробуйте в вершинном шейдере
вместо:
output.Norm = mul(input.Norm, World);
написать:
output.Norm = mul(input.Norm, (float3x3)World);
1
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
29.07.2015, 10:14  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//--------------------------------------------------------------------------------------
// Форматы данных
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float4 Pos : POSITION;
    float2 Tex : TEXCOORD0;  
    float3 Norm : NORMAL;
};
 
struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float4 worldPos : POSITION;
    float2 Tex : TEXCOORD0;  
    float3 Norm : NORMAL;
};
Поменял как Вы посоветовали, ничего не изменилось... хм.

Может скинуть архивчик с экзешником, чтобы Вы посмотрели на характер освещения? он очень странный, я не могу понять в какую сторону копать даже, пробовал подгружать разные модели.
0
61 / 54 / 21
Регистрация: 19.10.2013
Сообщений: 117
29.07.2015, 11:33
Спасибо, но экзешник не нужен.
Для правильного освещения нужно, чтобы нормали не просто были, а:
были перпендикулярны поверхности
были направлены наружу
были одиночной длины (нормализованы).
В моделях, скорее всего, все в порядке.
Характер освещения зависит от положения источника, объекта и камеры. Ошибки могут быть везде.
0
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
29.07.2015, 20:37  [ТС]
Хорошо, я это понимаю. Можно тогда такой вопрос: у меня есть алгоритм по которому я делаю сферу вручную (без подгрузки моделей), но как мне имея позиции вершин вычислить нормали к ним? не могли бы Вы подсказать алгоритм по которому это делается?
0
61 / 54 / 21
Регистрация: 19.10.2013
Сообщений: 117
29.07.2015, 21:58
Лучший ответ Сообщение было отмечено Despairon как решение

Решение

Цитата Сообщение от Despairon Посмотреть сообщение
как мне имея позиции вершин вычислить нормали к ним?
Для вершин треугольника примерно так:
C++
1
2
3
4
5
D3DXVECTOR3 a, b, c, sba, sca, norm; //a, b, c - вершины треугольника norm - нормаль
D3DXVec3Subtract(&sba, &b, &a); //вектор ab
D3DXVec3Subtract(&sca, &c, &a); //вектор ac
D3DXVec3Cross(&norm, &sba, &sca); //векторное произведение
D3DXVec3Normalize(&norm, &norm);
Для сферы еще проще:
C++
1
2
3
D3DXVECTOR3 a, c, norm; //a - точка на сфере, c - центр сферы, norm - нормаль
D3DXVec3Subtract(&norm, &a, &c); //вектор ca
D3DXVec3Normalize(&norm, &norm);
1
0 / 0 / 0
Регистрация: 28.12.2014
Сообщений: 30
29.07.2015, 22:23  [ТС]
Вот! этим вот я и воспользуюсь! очень странно что я не мог найти этого в интернете...
В любом случае, спасибо большое за Ваши ответы)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.07.2015, 22:23
Помогаю со студенческими работами здесь

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

Постройть график точечным методом
del] шестой вариант, условия там же в картинке. Что значит точечным методом? (новичок в графике). Нарушение правил форума, п. 5.18

Напряженность поля создаваемое точечным зарядом
Помогите составить прогу :Напряженность поля создаваемое точечным зарядом вычисляется по формуле E=\frac{q}{4\pi {\varepsilon...

Особенности настройки освещения при работе с нормалями
Вектор нормали к плоскости может иметь 2 направления и из-за этого портится освещение. Подскажите, пожалуйста, какой-нибудь простенький...

Рассчитать световой поток, испускаемый точечным изотропным источником
сила света I= dФ/d(омега) ,, омега-телесный угол. если источник изотропный то сила света всегда равна I=Ф/4pi. а мне дана задача: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru