Raytracing / Phong Model Diffuse компонент - PullRequest
0 голосов
/ 08 декабря 2018

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

Затенение второй сферы может быть трудно увидеть.Shaded spheres

Соответствующие структуры:

struct Ray
{
    vec3 origin;        // origin of the ray
    vec3 dir;           // direction of the ray
};

struct Sphere
{   
    vec3 center;
    float radius;       
    vec3 ka, kd, ks;
    vec3 reflectivity;
    float alpha;        

    Sphere(const vec3& ic=vec3(0.0f), const float& ir=0.0f, const vec3& ika=vec3(0.0f), const vec3& ikd=vec3(0.0f), const vec3& iks=vec3(0.0f), const float& ireflectivity=0.1f, const float& ialpha=1.0f):
    center(ic), radius(ir), ka(ika), kd(ikd), ks(iks), reflectivity(ireflectivity), alpha(ialpha)
    {}

    bool intersect(const Ray& ray, float& t0, float& t1);
};

struct PointLight
{
    vec3 location;
    vec3 id, is;    

    PointLight(const vec3& iloc=vec3(0.0f), const vec3& iid=vec3(0.0f), const vec3& iis=vec3(0.0f)):
    location(iloc), id(iid), is(iis)
    {}

};

    vec3 color;
    vec3 amb = my_sphere.ka* my_ambient_light.ia;   // I = ka * ia  ambient component
    int temp = my_point_lights.size() - 1;
    color += amb;

    vec3 diff;
    for (int i = my_point_lights.size() - 1; i >= 0; i--) {
        vec3 n = (ray.origin + ray.dir - my_sphere.center);
        normalize(n);

        vec3 L = (my_point_lights[temp].location - ray.origin);
        normalize(L);

        diff += my_sphere.kd * my_point_lights[temp].id * std::max(dot(n, L), 0.0f);
    }
    color += diff;

1 Ответ

0 голосов
/ 08 декабря 2018

То, что вы в основном хотите сделать в своем шейдере, это вычислить диффузное затенение заданной точки на сфере.Для этого вам в основном понадобятся две вещи: во-первых, нормаль к поверхности в той точке сферы, которую вы хотите заштриховать, и, во-вторых, направление, откуда свет падает на точку, которую вы хотите заштриховать.Теперь, прежде чем вы сможете продолжить и рассчитать затенение объекта в данной точке, вам, как правило, нужно знать фактическое положение той конкретной точки, которую вы хотите заштриховать.Поскольку вы на самом деле не предоставили никакого объяснения того, что именно вещи типа ray.dir фактически представляют в вашем коде, мне придется прибегнуть к догадкам.Я предполагаю, что вы делаете что-то вроде трассировки лучей в фрагментном шейдере.И я должен предположить, что ray.dir - это не просто какой-то вектор, указывающий в общем направлении луча, попадающего на сферу в интересующей вас точке, а на самом деле это вектор , которыйприведет вас от начала луча к точной точке попадания на сферу.В противном случае вам не хватает самой важной информации, чтобы действительно что-то сделать, это координаты точки, которую вы хотите заштриховать.В этом случае вам сначала нужно будет вычислить, где находится фактическое пересечение вашего луча и вашей сферы.

Теперь, если мы сделаем все эти предположения и, кроме того, предположим, что все эти векторы, которые вы имеете, действительно представляюткоординаты в той же системе координат, то ray.origin + ray.dir - my_sphere.center должен действительно дать вектор, указывающий от центра сферы к точке, которую вы хотите заштриховать.И этот вектор действительно должен указывать в направлении нормали поверхности сферы в точку, которую вы хотите заштриховать.Тем не менее, вторым вектором, который вам нужен для вычисления диффузного затенения, является вектор, указывающий в направлении, откуда свет падает на точку, которую вы хотите затенить.То есть вектор, указывающий от точки затенения к источнику света.Тем не менее, my_point_lights[temp].location - ray.origin может показаться вектором, указывающим от источника луча на источник света.

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

n = normalize(n);
…
L = normalize(L);

Кроме того, вы накапливаете значения в color и diff, но никогда не инициализируете эти векторы.Вы, вероятно, хотели инициализировать их нулями ... 101

...