【问题标题】:Why is my ray-traced image entirely black?为什么我的光线追踪图像全黑?
【发布时间】:2013-05-17 12:45:43
【问题描述】:

我必须生成一个黑色圆圈的图像,黑色是 (0, 0 , 0),白色是 (1, 1, 1),但我一直得到一个完全黑色的图像。这是我所有的代码:

#include "cast.h"
#include "collisions.h"
#include <stdio.h>
#include "math.h"

int cast_ray(struct ray r, struct sphere spheres[], int num_spheres)
{
   int isFound;
   struct maybe_point mp;
   isFound = 0;

   for (int i = 0; i < num_spheres; i++)
   {
      mp = sphere_intersection_point(r, spheres[i]);

      if (mp.isPoint == 1)
      {
         isFound = 1;
      }
      else
      {
         isFound = 0;
      }
   }
   return isFound;
}

void print_pixel(double a, double b, double c)
{
   int i, j, k;

   i = a * 255;
   j = b * 255;
   k = c * 255;

   printf("%d %d %d ", i, j, k);
}

void cast_all_rays(double min_x, double max_x, double min_y, double max_y,
                  int width, int height, struct point eye,
                  struct sphere spheres[], int num_spheres)
{
   double width_interval, height_interval, y, x;
   int intersect;

   width_interval = (max_x - min_x)/width;
   height_interval = (max_y - min_y)/height;

   for (y = max_y; y > min_y; y = y - height_interval)
   {
      for (x = min_x; x < max_x; x = x + width_interval)
      {
         struct ray r;
         r.p = eye;
         r.dir.x = x;
         r.dir.y = y;
         r.dir.z = 0.0;

         intersect = cast_ray(r, spheres, num_spheres);

            if (intersect != 0)
            {
               print_pixel (0, 0, 0);
            }
            else
            {
               print_pixel (1, 1, 1);
            }
      }

我已经有一些我知道是正确的函数来判断光线是否与球体相交。我用来查找交点的函数在函数 cast_ray 中。

    sphere_intersection_point(r, spheres[i]);

print_pixel 函数通过将整数值乘以最大颜色值(即 255)来转换整数值。

cast_all_rays 函数将光线从我们的眼睛投射到整个场景中(在更改 y 之前经过所有 x 坐标)。如果光线与球体相交,则像素为黑色,最终形成一个黑色圆圈。

这里是 x、y 和半径的限制(注意:我使用的是 PPM 格式):

Eye at <0.0, 0.0, -14.0>.
A sphere at <1.0, 1.0, 0.0> with radius 2.0.
A sphere at <0.5, 1.5, -3.0> with radius 0.5.
min_x at -10, max_x at 10, min_y of -7.5, max_y at 7.5, width=1024, and height=768.

我需要生成一个黑色圆圈的图像,但我不断得到一个完全黑色的图像。我有一种感觉,问题出在 cast_all_rays 函数中,但我似乎无法找到它是什么。帮助表示赞赏!谢谢。

以防万一我的测试出现问题,这是我的 cast_all_rays 的 test.c 文件:

#include "collisions.h"
#include "data.h"
#include "cast.h"
#include <stdio.h>

void cast_all_rays_tests(void)
{
   printf("P3\n");
   printf("%d %d\n", 1024, 768);
   printf("255\n");

   double min_x, max_x, min_y, max_y;
   int width, height;
   struct point eye;
   struct sphere spheres[2];

   eye.x = 0.0;
   eye.y = 0.0;
   eye.z = -14.0;
   spheres[0].center.x = 1.0;
   spheres[0].center.y = 1.0;
   spheres[0].center.z = 0.0;
   spheres[0].radius = 2.0;
   spheres[1].center.x = 0.5;
   spheres[1].center.y = 1.5;
   spheres[1].center.z = -3.0;
   spheres[1].radius = 0.5;
   min_x = -10;
   max_x = 10;
   min_y = -7.5;
   max_y = 7.5;

   cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye, spheres, num_spheres);
}

int main()

{
   cast_all_rays_tests();

   return 0;
}

【问题讨论】:

    标签: c raytracing


    【解决方案1】:

    不确定这是否是您遇到的问题,但您应该只在与球体相交时设置isFound。不相交就不要设置。否则,您的图像将仅由列表中的最后一个球体控制。

      if (mp.isPoint == 1)
      {
         isFound = 1;
      }
      //else
      //{
      //   isFound = 0;
      //}
    

    由于您的图像完全是黑色的,您的交叉路口代码似乎是错误的,或者您的视野太窄了。如果您对上述更改不满意,也许您应该发布有关 x 和 y 限制、眼睛位置以及球体的位置和半径的详细信息。

    我注意到的另一件事是r.dir.z = 0.0。你是从这个减去眼睛的位置来得到一个方向,还是你的真实光线方向?当然,您需要提供非零 z 方向。通常,您根据您的视图平面设置xy,并提供一个常量z,例如1-1

    [编辑]

    为了从下面的 cmets 中更清楚,我相信你没有正确设置你的光线方向。相反,您只需将方向设置为视图平面的像素位置,而忽略眼睛位置。以下会更常见:

         struct ray r;
         r.p = eye;
         r.dir.x = x - eye.x;
         r.dir.y = y - eye.y;
         r.dir.z = 0.0 - eye.z;
    

    【讨论】:

    • 是的,图像仍然是黑色的。 :( 我会在上面发布限制。
    • 嗯...哦!它表示视图矩形的边界是 min_x、max_x、min_y 和 max_y(z 坐标为 0)。等一下,他们所指的 z 坐标实际上不是射线方向的 z 坐标?
    • 没有看到你的球体交叉代码很难说。在我看来,如果视平面以z=0 为中心,您应该做的是创建一条射线,其方向是您的视平面像素位置减去眼睛位置。所以这会给你一个 14 的 z 方向。如果你从我在你的代码中看到的逐字使用光线方向,那将是一条从眼睛位置射出的光线,在眼睛周围的 2D 圆圈中,而不是比 3D 平截头体。正确设置你的光线方向,一切都会好起来的。
    • 谢谢!快速提问,我应该在 test.c 的代码中调用 cast_all_rays 函数吗?我不断收到一条错误消息:未定义对“cast_all_rays”的引用。但是如果我尝试编译而不调用该函数,则不会出现错误。
    • 大概是您的一个标题 (cast.h?) 声明了 cast_all_rays 函数。您应该在标题中使用extern void cast_all_rays(...);。这里我使用了...,但您实际上想要包含所有类型的参数列表。或者这可能是链接器错误,这意味着您需要将所有编译的目标代码链接到一个可执行文件中。也许这更好地解释了您的图像全黑 - 如果您无法构建源代码,则必须运行旧版本。
    猜你喜欢
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多