C++ Raytracer - 只有一个对象出现在场景中
C++ Raytracer - Only one object appearing in scene
我正在使用光线追踪器来渲染 Sphereflake,但我在尝试让多个对象出现在场景中时遇到了问题。在下面的场景中,我只是想测试一个场景中有两个球体,但由于某种原因,场景中只出现一个球体,而且通常是半径最大的球体。
另一个奇怪的事情是,即使场景中设置了摄像机,输出 window 似乎总是显示中心的主要对象 ((0,0),屏幕坐标在[-1,-1]->[1,1]) 而不是与相机坐标相关 space.
我不确定这是父层次结构问题还是我渲染对象的方式,但如果能深入了解问题持续存在的原因,我们将不胜感激。
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 & s2.radius = 0.33f
scene 1
另一个具有两个球体的场景示例 s1.radius = 0.33f & s2.radius = 1.0f
scene 2
如你所见,相机作为视角似乎是无效的,因为无论球体的位置如何,唯一的区别就是它的光照,但它永远在中心显示 window
由于 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 后面。
事实证明这不是我的场景构建器的问题,而是 child/parent 继承在另一个 class SceneObject*
中的工作方式。无论如何,我修复了 AddChild 函数,现在代码现在适用于相机透视和场景中的多个项目
我正在使用光线追踪器来渲染 Sphereflake,但我在尝试让多个对象出现在场景中时遇到了问题。在下面的场景中,我只是想测试一个场景中有两个球体,但由于某种原因,场景中只出现一个球体,而且通常是半径最大的球体。
另一个奇怪的事情是,即使场景中设置了摄像机,输出 window 似乎总是显示中心的主要对象 ((0,0),屏幕坐标在[-1,-1]->[1,1]) 而不是与相机坐标相关 space.
我不确定这是父层次结构问题还是我渲染对象的方式,但如果能深入了解问题持续存在的原因,我们将不胜感激。
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 & s2.radius = 0.33f
scene 1
另一个具有两个球体的场景示例 s1.radius = 0.33f & s2.radius = 1.0f
scene 2
如你所见,相机作为视角似乎是无效的,因为无论球体的位置如何,唯一的区别就是它的光照,但它永远在中心显示 window
由于 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 后面。
事实证明这不是我的场景构建器的问题,而是 child/parent 继承在另一个 class SceneObject*
中的工作方式。无论如何,我修复了 AddChild 函数,现在代码现在适用于相机透视和场景中的多个项目