Raytracing, ближайшее пересечение объекта не работает должным образом в моем коде - PullRequest
0 голосов
/ 20 февраля 2020

Сцена содержит 3 сферы, два красных шара и один зеленый. В верхнем правом углу должен быть красный шарик, но по какой-то причине он не появляется, а фон черный, когда должен быть серым. Также освещение работает только для красного шара, а не для зеленого. pi c:

enter image description here https://imgur.com/a/AHP5tsi

Я думаю, что ошибка заключается в большей части цвета

vec color(const ray& r)
{
    vector <Light> lighting;
    vector <sphere> objects;

    lighting.push_back(Light(vec(0, 0, 50), vec(0, -1, 0)));
    lighting.push_back(Light(vec(10, 20, -2), vec(0, -1, 0)));
    //ighting.push_back(Light(vec(-10, 30, -4), vec(0, -1, 0)));


    objects.push_back(sphere(vec(0,-100.5,-3), 100, vec(0, 1, 0)));
    objects.push_back(sphere(vec(0, 0, -1), 0.5, vec(1, 0, 0)));
    objects.push_back(sphere(vec(5, 5,-2), 3, vec(1, 0, 0)));


    float t_near = 2000.0;
    float t = 0.0;
    int pos = 0;
    vec frame_buffer = vec(0.502, 0.502, 0.498);//grey background color
    vec totalLight{0, 0, 0};
    float depth = 0.0;
        for(int j = 0; j < objects.size(); j++)
        {
            t = objects[j].intersect(r);
            if(t > 0.0)
                depth = t;
            else
                depth = t_near;
            if(depth < t_near)
            {
                t_near = depth;
                frame_buffer = objects[j].col();
                pos = j;
            }
        else
            {
                t = t_near;
                frame_buffer = frame_buffer;
                pos = pos;
            }
        }
        if(depth > 0.0)
        {
            for(int i = 0; i < lighting.size(); i++)
            {
                vec hit = unit_vector(r.p_at_par(depth) - objects[pos].centre);
                vec L = unit_vector(lighting[i].position() - r.p_at_par(depth));
                vec R = L - 2.0*dot(L, hit)*hit;
                vec S = vec(1, 1, 1)*pow(max(0.f, dot(R, vec(0, 0, -1))), 50);//Specular component
                vec D = (frame_buffer * max(0.f, dot(L, hit)) * 1.0);//Diffuse component
                totalLight += S + D;
            }
                return totalLight; //+= A;  
        }
        else
            return vec(0.502, 0.502, 0.498);
}

это остальная часть основного. cpp

#include <iostream>
#include <cstdio>
#include "vec.h"
#include "ray.h"
#include "Light.h"
#include "sphere.h"
#include "object.h"
#include <vector>
#include <functional>
#include <random>
#include <math.h>
using namespace std;

inline double random_double() {
    static std::uniform_real_distribution<double> distribution(0.0, 1.0);
    static std::mt19937 generator;
    static std::function<double()> rand_generator =
    std::bind(distribution, generator);
    return rand_generator();
  }

vec color(const ray& r)
{
    vector <Light> lighting;
    vector <sphere> objects;

    lighting.push_back(Light(vec(0, 0, 50), vec(0, -1, 0)));
    lighting.push_back(Light(vec(10, 20, -2), vec(0, -1, 0)));
    //ighting.push_back(Light(vec(-10, 30, -4), vec(0, -1, 0)));


    objects.push_back(sphere(vec(0,-100.5,-3), 100, vec(0, 1, 0)));
    objects.push_back(sphere(vec(0, 0, -1), 0.5, vec(1, 0, 0)));
    objects.push_back(sphere(vec(5, 5,-2), 3, vec(1, 0, 0)));


    float t_near = 2000.0;
    float t = 0.0;
    int pos = 0;
    vec frame_buffer = vec(0.502, 0.502, 0.498);//grey background color
    vec totalLight{0, 0, 0};
    float depth = 0.0;
        for(int j = 0; j < objects.size(); j++)
        {
            t = objects[j].intersect(r);
            if(t > 0.0)
                depth = t;
            else
                depth = t_near;
            if(depth < t_near)
            {
                t_near = depth;
                frame_buffer = objects[j].col();
                pos = j;
            }
        else
            {
                t = t_near;
                frame_buffer = frame_buffer;
                pos = pos;
            }
        }
        if(depth > 0.0)
        {
            for(int i = 0; i < lighting.size(); i++)
            {
                vec hit = unit_vector(r.p_at_par(depth) - objects[pos].centre);
                vec L = unit_vector(lighting[i].position() - r.p_at_par(depth));
                vec R = L - 2.0*dot(L, hit)*hit;
                vec S = vec(1, 1, 1)*pow(max(0.f, dot(R, vec(0, 0, -1))), 50);//Specular component
                vec D = (frame_buffer * max(0.f, dot(L, hit)) * 1.0);//Diffuse component
                totalLight += S + D;
            }
                return totalLight; //+= A;  
        }
        else
            return vec(0.502, 0.502, 0.498);
}

float clamp(float a)
{
    return (a > 255)? 255: (a < 0)? 0: a;
}

int main()
{
    const int w = 200, h = 100;
    FILE *fp;
    fp = fopen("img.ppm", "wb");
    fprintf(fp, "P6\n%d %d\n255\n", w, h);
    vec lower_corner(-2.0, -1.0, -1.0);
    vec horizontal(4.0, 0.0, 0.0);
    vec vertical(0.0, 2.0, 0.0);
    vec origin(0.0, 0.0, 0.0);
    for(int j = h - 1; j >= 0; j--)
    {
        for(int i = 0; i < w; i++)
        {
            vec col(0, 0, 0);
            static unsigned char pixel[3];
            for(int s = 0; s < 200; s++){
                float u = float(i + random_double())/float(w);
                float v = float(j + random_double())/float(h);
                ray r(origin, lower_corner + u*horizontal + v*vertical);
                col += color(r);
            }
            col /= float(200);
            pixel[0] = int(clamp(col.r() * 255));
            pixel[1] = int(clamp(col.g() * 255));
            pixel[2] = int(clamp(col.b() * 255));
            fwrite(pixel, 3, 1, fp);
        }


    }
    fclose(fp);
    return 0;
}

Спасибо

...