Войти
ФлеймФорумПроЭкты

Я пишу несмещной пат-трейсер (3 стр)

Страницы: 1 2 3 4 511 Следующая »
#30
1:08, 5 дек. 2019

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

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


#31
3:02, 5 дек. 2019

gamedevfor
> Ты усложняешь на ровном месте. Не нужно это всё, обычной аналитической геометрии предостаточно для решения этой задачи.
какой-нибудь брутфорсный pathtracer ещё можно написать, не понимая, как он работает, просто отскакивая лучики. bidirectional ты уже не напишешь таким образом. а что-то более продвинутое вроде MLT — ноль шансов.

#32
4:05, 5 дек. 2019

Suslik
MLT обычный рандом поиск пути с отбором более ценных путей из-за чего метод быстрее сходится и шума меньше НО это если ты знаешь c какой сценой ты имеешь дело то можно сделать оценочную функцию пути, а если о сцене ничего заранее не известно то писать оценочную функцию это всё равно что играть в спортлото.

#33
(Правка: 5:00) 4:58, 5 дек. 2019

gamedevfor
Знаешь, а я вот уверен, что есть что-то такое, что отличает меня, Суслика и Смайла от тебя. Что-то такое, из-за чего мы всё-таки смогли повернуть картинку, а ты - не смог.
И вот сейчас человек, который не смог, рассказывает людям, которые смогли; что то, что они делают - это излишнее усложнение элементарной задачи.
_

Ну типа это, приступаем к интегрированию.
Конечно, берём самый топорный вариант, лишь бы хоть что-то показывало.
1. Полигоны разбираем на предмет наличия слова "light" в имени текстуры; если есть - ставим эмиссию 1 и альбедо 0; в противном случае - эмиссию 0 и альбедо 0.5.

void Geometry::LoadFromT3D(char const* path)
{
    std::ifstream f(path);
    int trindex = -1;
    FPoint pts[3];
    int ptindex = 0;
    int row = 0;
    float emissive = 0;
    float albedo = 0;
    while (!f.eof()) {
        std::string line;
        std::getline(f, line);
        row += 1;
        unsigned int flags = 0;
        unsigned char texture[256] = "";
        if (sscanf(line.c_str(), " Begin Polygon Item=%*s Texture=%256s Flags=%u", texture, &flags) != 0) {
            trindex += 1;
            ptindex = 0;
        } else if (sscanf(line.c_str(), " Begin Polygon Texture=%256s Flags=%u", texture, &flags) != 0) {
            trindex += 1;
            ptindex = 0;
        } else if (sscanf(line.c_str(), " Begin Polygon Item=%*s Flags=%u", &flags) != 0) {
            trindex += 1;
            ptindex = 0;
        } else if (sscanf(line.c_str(), " Begin Polygon Flags=%u", &flags) != 0) {
            trindex += 1;
            ptindex = 0;
        }
        for (unsigned char* ch = texture; *ch != 0; ++ch) {
            *ch = tolower(*ch);
        }
        if (texture[0] != 0) {
            if (strstr((char*)texture, "light") != nullptr) {
                emissive = 1.0f;
                albedo = 0.0f;
            } else {
                emissive = 0.0f;
                albedo = 0.5f;
            }
        }
        float x = 0;
        float y = 0;
        float z = 0;
        if (trindex >= 0 && sscanf(line.c_str(), " Vertex%f ,%f, %f", &x, &y, &z) != 0) {
            if (ptindex < 2) {
                pts[ptindex] = FPoint{ - x, y, z };
                ptindex += 1;
            } else {
                pts[2] = FPoint{ - x, y, z };
                Face face;
                if (BuildFace(pts[0], pts[1], pts[2], face)) {
                    faces.push_back(face);
                    faces.back().emissive = emissive;
                    faces.back().albedo = albedo;
                }
                pts[1] = pts[2];
            }
        }
    }
}
2. Расписываем наши генераторы:
void RendererThread::GenerateUniform(float& q)
{
    std::uniform_real_distribution<float> dist;
    q = dist(rand);
}

void RendererThread::GenerateCircle(float& u, float& v)
{
    while (true) {
        GenerateUniform(u);
        u = u * 2.0f - 1.0f;
        GenerateUniform(v);
        v = v * 2.0f - 1.0f;
        float uvsqr = u * u + v * v;
        if (uvsqr > 1.0f) {
            continue;
        }
        float inv = 1.0f / sqrtf(uvsqr);
        u *= inv;
        v *= inv;
        return;
    }
}

void RendererThread::GenerateLambertian(FDisp const& n, FDisp& d)
{
    FDisp a{ 1, 0, 0 };
    if (n.x > 0.8f || n.x < -0.8f) {
        a = FDisp{ 0, 1, 0 };
    }
    FDisp b = cross(a, n);
    FDisp t = cross(b, n);
    float q;
    GenerateUniform(q);
    float z = sqrtf(1.0f - q);
    float r = sqrtf(q);
    float u;
    float v;
    GenerateCircle(u, v);
    u *= r;
    v *= r;
    d = z * n + u * b + v * t;
}
3. И, собственно, интегратор:
void RendererThread::ThreadFunc()
{
    Geometry geom;
    geom.LoadFromT3D("D:\\Program Files (x86)\\Unreal Tournament GOTY\\Maps\\CTF-Coret-FlagRoom.t3d");
    Camera camera = Camera::Targeted(
        FPoint{ -160, 228, 410 },
        FPoint{ 288, -384, 240 },
        1.0f * sqrtf(aspect), 1.0f / sqrtf(aspect));
    std::vector<float> frame(width * height, 0.0f);
    int iter = 0;
    float const passrate = 1.0f;
    while (!rterminate.load(std::memory_order_relaxed)) {
        iter += 1;
        for (int iy = 0; iy < height; ++iy) {
            auto& bits = bitbuf.Back();
            bits.resize(width * height * 4);
            uint8_t* pixels = bits.data();
            uint8_t* line = pixels + iy * width * 4;
            for (int ix = 0; ix < width; ++ix) {
                float q;
                GenerateUniform(q);
                if (passrate > q) {
                    float cx = 2.0f * (ix + 0.5f) / width - 1.0f;
                    float cy = 1.0f - 2.0f * (iy + 0.5f) / height;
                    TraceRequest tr;
                    tr.origin = camera.mwc * FPoint{ 0, 0, 0 };
                    tr.dir = camera.mwc * FDisp{ cx * camera.utan, cy * camera.vtan, 1.0f };
                    while (geom.Trace(tr)) {
                        frame[width * iy + ix] += tr.face->emissive;
                        float q;
                        GenerateUniform(q);
                        if (tr.face->albedo < q) {
                            break;
                        }
                        tr.origin = tr.hit;
                        FDisp norm{
                            tr.face->mwt[2],
                            tr.face->mwt[6],
                            tr.face->mwt[10] };
                        GenerateLambertian(norm, tr.dir);
                    }
                }
                uint8_t* pixel = line + ix * 4;
                float value = 100.0f * frame[width * iy + ix] / (iter * passrate);
                float tm = value / (1.0f + value);
                int v = (int)(sqrtf(tm) * 255.0f);
                pixel[0] = v;
                pixel[1] = v;
                pixel[2] = v;
                if (rterminate.load(std::memory_order_relaxed)) {
                    return;
                }
            }
            if (iy % 7 == 0) {
                bitbuf.Publish();
            }
            InvalidateRgn(hwnd, nullptr, false);
        }
    }
}
Изображение
Ну всё, пацаны, увидимся через неделю. :V
Правда, меня уже немного волнует вон то чёрное пятно в потолке вместо окна.

#34
(Правка: 5:18) 5:17, 5 дек. 2019

gamedevfor
> MLT обычный рандом поиск пути с отбором более ценных путей
лол, что ж ты тогда на форуме что-то плебеям доказываешь, если можешь написать свой MLT, наверняка лучше, чем все остальные и срубить кучу бабла? типичный синдром даннига-крюгера.

Delfigamer
я всё-таки ещё раз повторю — трудно брать за референс то, что сходиться будет несколько дней. к тому же код, который ты нопесал, прямым образом транслируется на GPU. писал бы сразу на GPU — не надо было бы переписывать.

#35
8:49, 5 дек. 2019

Suslik
> лол, что ж ты тогда на форуме что-то плебеям доказываешь, если можешь написать
> свой MLT, наверняка лучше, чем все остальные и срубить кучу бабла? типичный
> синдром даннига-крюгера.

На трейсерах очень сложно заработать - это я точно знаю. )))

#36
9:21, 5 дек. 2019

gamedevfor
> На трейсерах очень сложно заработать - это я точно знаю. )))
каэш, там думать надо. это тебе не игры мышкой в конструкторе шлёпать.

#37
(Правка: 9:49) 9:33, 5 дек. 2019

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

Delfigamer

> FDisp norm{
> tr.face->mwt[2],
> tr.face->mwt[6],
> tr.face->mwt[10] };
гиперговнокод, я считаю. во-первых, потому что ни черта не понятно при беглом взгляде, что это за компоненты. во-вторых, потому что запись полагается на внутренний memory layout. такое надо писать либо через произведение с вектором (0, 0, 0, 1), либо через метод GetColumn(3) или подобный.

#38
(Правка: 13:25) 13:25, 5 дек. 2019

Suslik
> гиперговнокод, я считаю.
Я тоже, на самом деле.
По-хорошему, надо будет запилить функции для сборки матрицы из базисных векторов и для обратной разборки.
_

Изображение

Ничерта не понятно.
И что это за дырка в крыше?
Ладно, так уж и быть, сделаю сцену попроще (благо поменять геометрию - не проблема).
Изображение
Изображение
#39
13:34, 5 дек. 2019
Надо было начинать с написания своего убийцы ispc
#40
14:06, 5 дек. 2019
Delfigamer
> Знаешь, а я вот уверен, что есть что-то такое, что отличает меня, Суслика и
> Смайла от тебя. Что-то такое, из-за чего мы всё-таки смогли повернуть картинку,
> а ты - не смог.
хе хе, был в той эпичной теме
#41
(Правка: 14:09) 14:07, 5 дек. 2019

Delfigamer
ещё для отладки бывает полезно рендерить только первичное, только вторичное изображение итп. то есть считаешь только вклад от первого отскока, только от второго итп. ну и, повторюсь ещё раз, сравнивать с почти сошедшимся изображением всегда приятнее, чем с говношумом. у тебя сейчас яркость каждого пикселя либо 0, либо [cht]+\infty[/cht], то есть оно ещё даже не начало сходиться.

#42
15:20, 5 дек. 2019

Delfigamer
> Зря, зря. Потому что...
Кaк будто я специально!
Вот смотрел видео и ничего не понял…

#43
15:22, 5 дек. 2019

Suslik
> > На трейсерах очень сложно заработать - это я точно знаю. )))
> каэш, там думать надо. это тебе не игры мышкой в конструкторе шлёпать.

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

#44
21:23, 5 дек. 2019

gamedevfor
> дело не в этом, все кому нужен трейсер думают что напишут свой трейсер лучше и
> еще продадут потом его другим, так и ходят "покупатели" каждый со своим
> трейсером.
Это ты людей по себе судишь?
_

Изображение

Легит? По-моему, легит.
Страницы: 1 2 3 4 511 Следующая »
ФлеймФорумПроЭкты