【问题标题】:C++ Raytracer - Only one object appearing in sceneC ++ Raytracer - 场景中只出现一个对象
【发布时间】:2017-05-17 21:58:31
【问题描述】:

我正在使用光线追踪器渲染 Sphereflake,但我无法尝试让场景中出现多个对象。在下面的场景中,我只是想测试一个场景中有两个球体,但由于某种原因,场景中只会出现一个球体,而且通常是半径最大的球体。

另一个奇怪的地方是,即使场景中设置了相机,输出窗口似乎总是在中心显示主要对象 ((0,0),屏幕坐标在 [-1,-1 ]->[1,1]) 而不是与相机坐标空间相关。

我不确定这是否是父层次结构问题或我如何渲染对象,但如果能深入了解问题为何持续存在,将不胜感激。

main.cpp(创建场景渲染对象)

#include <stdio.h>
#include <iostream>
#include <vector>
#include <math.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp> 

#include <Raytracer/Raytracer.h>

using namespace glm;
using namespace Raytracer;
using namespace Raytracer::Scenes;
using namespace Raytracer::Objects;

/**
 * Places a few spheres in the scene and adds some lights.
 *
 * @param scene The scene
 */
Scene *BuildScene(int depth, float aspect)
{
    const int materialCount = 6;

    vec3 colors[materialCount] =
    {
      vec3(1.0f, 0.0f, 0.0f),
      vec3(1.0f, 1.0f, 0.0f),
      vec3(0.0f, 1.0f, 0.0f),
      vec3(0.0f, 1.0f, 1.0f),
      vec3(0.0f, 0.0f, 1.0f),
      vec3(1.0f, 0.0f, 1.0f)
    };

    Material *materials[materialCount];

    for (int i = 0; i < materialCount; i++)
    {
        materials[i] = new Material();
        if (materials[i] == NULL)
            return NULL;

        vec3 ambient = colors[i] * 0.01f;
        materials[i]->SetAmbient(ambient);
        materials[i]->SetDiffuse(colors[i]);
        materials[i]->SetShininess(25.0f);
    }

    if (depth <= 0)
        return NULL;

    // Create the scene.
    Scene *scene = new Scene();
    if (scene == NULL)
        return NULL;

    Sphere * s1 = new Sphere(0.33f, materials[5]);
    s1->SetPosition(vec3(5.0f, 0.0f, -2.0f));
    Sphere * s2 = new Sphere(0.33f, materials[1]);
    s2->SetPosition(vec3((5.0f, 0.33f, -2.0f));

    s1->AddChild(s2);

  // Create a light.
  Light *light = new PointLight(vec3(10.0f));
  if (light == NULL)
  {
    delete scene;
    return NULL;
  }

  light->SetPosition(vec3(-5.0f, 3.0f, 2.0f));
  scene->AddChild(light);

  // Create a camera.
  Camera *camera = new Camera(vec3(-2.0f, 2.0f, 4.0f), vec3(0.0f, 0.0f, 0.0f), 
    vec3(0.0f, 1.0f, 0.0f), Camera::DefaultFov, aspect);

  scene->AddChild(s1);

  if (camera == NULL)
  {
    delete scene;
    return NULL;
  }
  scene->AddChild(camera);
  scene->SetActiveCamera(camera);

  return scene;
}

/**
 * Renders the scene and saves the result to a BMP file.
 *
 * @param fileName The name of the file
 * @param width The image width
 * @param height The image height
 */
void Render(const char *fileName, int width, int height)
{
  if (fileName == NULL || width <= 0 || height <= 0)
    return;

  SimpleRenderer renderer;

  renderer.SetAccelerator(new SimpleAccelerator());
  renderer.SetIntegrator(new PhongIntegrator());

  puts("Generiere Szene...");
  Scene *scene = BuildScene(3, (float)width / height);
  if (scene == NULL)
    return;

  puts("Rendere Bild...");
  Image *image = renderer.Render(*scene, width, height);
  if (image != NULL)
  {
    puts("Speichere Ergebnis...");
    image->SaveBMP(fileName, 2.2f);
    delete image;
  }

  delete scene;
}

/**
 * The main program
 */
int main()
{
  Render("image.bmp", 512, 512);
  return 0;
}

具有两个球体的场景示例,如上所述,s1.radius = 0.33f &amp; s2.radius = 0.33f

scene 1

另一个带有s1.radius = 0.33f &amp; s2.radius = 1.0f 的球体的场景示例

scene 2

如您所见,相机作为透视点似乎无效,因为无论球体的位置如何,唯一的区别是它的照明,但它始终位于显示窗口的中心

【问题讨论】:

  • vec4 pos = vec4(s2-&gt;GetPosition(), 1.0f) * s2-&gt;GetTransformation() * RotationY(30); 左乘真的是你想要的吗?通常,3d 变换是matrix * vec,而不是相反。
  • 抱歉,这只是测试代码,它真的不是想要的结果,我最初的位置是距离s1半径长度的位置,这样两个球体就会在场景中接触,然而似乎没有任何效果,因为场景中仍然只出现一个球体

标签: c++ object scene raytracing


【解决方案1】:

由于 s2 作为 s1 的子项附加,因此它在 X 轴下方比 s1 向下绘制 5 个单位:

s2->SetPosition(vec3((5.0f, 0.33f, -2.0f));
...
s1->AddChild(s2);

而且由于您的相机正在向下看正 x 轴:

Camera *camera = new Camera(vec3(-2.0f, 2.0f, 4.0f), 
    vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), Camera::DefaultFov, aspect);

s2 只是被画在 s1 后面。

【讨论】:

  • 感谢您的评论,我考虑了您所说的并将 s2 的位置设置为s2-&gt;SetPosition(vec3(0.0f, 0.33f, 0.0f)); 并且仍然只有一个对象出现,我希望它现在会出现在顶部s1,但还是什么都没有
  • 有一点,如果是这种情况,那么如果第二个对象以更大的半径绘制并放置在 x 轴下方,那么它应该仍然出现在第一个球体的后面,但没有无论我将位置设置为什么,场景中只会出现 1 个球体
  • 知道为什么只显示一个对象,我一遍又一遍地使用该功能,却无法找到问题所在
【解决方案2】:

事实证明这不是我的场景构建器的问题,而是子/父继承如何在另一个类 SceneObject* 中工作。无论如何,我修复了 AddChild 函数,现在代码现在适用于相机透视和场景中的多个项目

【讨论】:

    猜你喜欢
    • 2015-01-13
    • 2013-06-15
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    相关资源
    最近更新 更多