gpt4 book ai didi

c++ - 光线追踪程序中的全向光给出了错误的渲染 C++

转载 作者:行者123 更新时间:2023-11-30 03:42:39 27 4
gpt4 key购买 nike

我正在尝试在我的 C++ 光线追踪程序中实现全向光源(又名点光源)。我没有得到预期的结果,但我无法找出问题所在。也许有人可以看到我做错了什么。我已经包含了负责光线追踪和光线的两个函数。 ClosestIntersection 函数查找最近的交点和三角形。稍后将在 DirectLight 函数中使用。如果有任何帮助,我将不胜感激。

#include <iostream>
#include <glm/glm.hpp>
#include <SDL.h>
#include "SDLauxiliary.h"
#include "TestModel.h"
#include "math.h"

using namespace std;
using glm::vec3;
using glm::mat3;

// ----------------------------------------------------------------------------
// GLOBAL VARIABLES

const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;
SDL_Surface* screen;
int t;
vector<Triangle> triangles;
float focalLength = 900;
vec3 cameraPos(0, 0, -4.5);

vec3 lightPos(0.5, 0.5, 0);
vec3 lightColor = 14.f * vec3(1,1,1);

// Translate camera
float translation = 0.1; // use this to set translation increment

// Rotate camera
float yaw;
vec3 trueCameraPos;

const float PI = 3.1415927;

// ----------------------------------------------------------------------------
// CLASSES

class Intersection;

// ----------------------------------------------------------------------------
// FUNCTIONS
void Update();
void Draw();
bool ClosestIntersection(vec3 start, vec3 dir, const vector<Triangle>& triangles,
Intersection& closestIntersection);
vec3 DirectLight(const Intersection& i);
// ----------------------------------------------------------------------------
// STRUCTURES
struct Intersection
{
vec3 position;
float distance;
int triangleIndex;
};

float m = std::numeric_limits<float>::max();

int main(int argc, char* argv[])
{
LoadTestModel(triangles);

screen = InitializeSDL(SCREEN_WIDTH, SCREEN_HEIGHT);
t = SDL_GetTicks(); // Set start value for timer.

while (NoQuitMessageSDL())
{
Update();
Draw();
}

SDL_SaveBMP(screen, "screenshot.bmp");
return 0;
}

void Update()
{
// Compute frame time:
int t2 = SDL_GetTicks();
float dt = float(t2 - t);
t = t2;
cout << "Render time: " << dt << " ms." << endl;
}
}

void Draw()
{
if (SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);

for (int y = 0; y<SCREEN_HEIGHT; ++y)
{
for (int x = 0; x < SCREEN_WIDTH; ++x)
{
vec3 start = cameraPos;
vec3 dir(x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength);
Intersection intersection;
if (ClosestIntersection(start, dir, triangles, intersection))
{
//vec3 theColor = triangles[intersection.triangleIndex].color;
vec3 theColor = DirectLight(intersection);
PutPixelSDL(screen, x, y, theColor);
}
else
{
vec3 color(0, 0, 0);
PutPixelSDL(screen, x, y, color);
}
}
}

if (SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);

SDL_UpdateRect(screen, 0, 0, 0, 0);
}

bool ClosestIntersection(vec3 s, vec3 d,
const vector<Triangle>& triangles, Intersection& closestIntersection)
{
closestIntersection.distance = m;
for (size_t i = 0; i < triangles.size(); i++)
{
vec3 v0 = triangles[i].v0;
vec3 v1 = triangles[i].v1;
vec3 v2 = triangles[i].v2;
vec3 u = v1 - v0;
vec3 v = v2 - v0;
vec3 b = s - v0;
vec3 x;

// Determinant of A = [-d u v]
float det = -d.x * ((u.y * v.z) - (v.y * u.z)) -
u.x * ((-d.y * v.z) - (v.y * -d.z)) +
v.x * ((-d.y * u.z) - (u.y * -d.z));

// Cramer'r Rule for t = x.x
x.x = (b.x * ((u.y * v.z) - (v.y * u.z)) -
u.x * ((b.y * v.z) - (v.y * b.z)) +
v.x * ((b.y * u.z) - (u.y * b.z))) / det;

if (x.x >= 0)
{
// Cramer'r Rule for u = x.y
x.y = (-d.x * ((b.y * v.z) - (v.y * b.z)) -
b.x * ((-d.y * v.z) - (v.y * -d.z)) +
v.x * ((-d.y * b.z) - (b.y * -d.z))) / det;

// Cramer'r Rule for v = x.z
x.z = (-d.x * ((u.y * b.z) - (b.y * u.z)) -
u.x * ((-d.y * b.z) - (b.y * -d.z)) +
b.x * ((-d.y * u.z) - (u.y * -d.z))) / det;

if (x.y >= 0 && x.z >= 0 && x.y + x.z <= 1 && x.x < closestIntersection.distance)
{
closestIntersection.position = x;
closestIntersection.distance = x.x;
closestIntersection.triangleIndex = i;
}
}

}
//end of for loop

if (closestIntersection.distance != m)
{
return true;
}
else
{
return false;
}

}

vec3 DirectLight(const Intersection& i)
{
vec3 n = triangles[i.triangleIndex].normal;
vec3 r = lightPos - i.position;
float R2 = r.x * r.x + r.y * r.y + r.z * r.z;
vec3 D = (lightColor * fmaxf((glm::dot(glm::normalize(r), n)), 0)) / (4 * PI * R2);
return D;
}

最佳答案

如果我正确理解 ClosestIntersection 中的代码,下面是它对每个三角形所做的事情:

  • 令 u,v 为从三角形的一个顶点到另外两个顶点的 vector 。设 d 是我们正在考虑的光线的(相反)方向。
  • 设 b 为从三角形顶点到相机的 vector 。
  • 找到 p,q,r 使得 b = pd+qu+rv(p,q,r 是您的代码调用的 x.x、x.y、x.z)。
  • 现在如果 p>0, q>=0, r>=0, q+r<=1 则射线与三角形相交并且到交点的距离为 p。

所以,关于 q,r 的条件是有意义的;这个想法是 b-qu-rv 是从相机到三角形中相关点的 vector ,它的方向是 d。你的距离并不是真正的距离,但沿着一条射线它们是实际距离的相同倍数,这意味着这可以很好地确定你击中了哪个三角形,这就是你的全部使用它们。到目前为止,还不错。

但是你说 closestIntersection.position = x; 肯定是错的,因为这个 x 与你的相机位置不在同一个坐标系中,三角形顶点等。在这个有趣的“d 的多少,u 的多少,v 的多少”坐标系中,从一个三角形到下一个三角形甚至都不相同。 (我认为,这就是为什么即使在一个面内,三角形边界也会出现不连续的原因。)

尝试将其设置为 v0+x.y*(v1-v0)+x.z*(v2-v0)(我认为这是正确的;它意味着光线穿过三角形的实际点,在相同的坐标中和你所有的其他观点一样),看看它做了什么。

关于c++ - 光线追踪程序中的全向光给出了错误的渲染 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36708800/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com