我正在研究光线追踪器,并开始向场景中添加圆柱体。我遇到的问题是找到光线击中点的表面法向量。我需要这个才能进行漫射照明。此时我所拥有的是相机光线撞击圆柱体的 3d 点,以及由中心轴上的点定义的实际圆柱体,向量代表轴的方向和半径。所以总结一下我的问题,如何找到具有圆柱体撞击点、半径、其轴上的点和轴的方向向量的点的法线向量?
我正在尝试对立方体内的球体进行光线追踪。立方体由 12 个具有法线的三角形简单构成。
立方体具有单位坐标和单位法线。因此,在其局部空间内(-1 和 1 之间),应该有一个半径为 0.5 的球体。
所以我想我应该在顶点着色器中计算光线:光线原点是插值顶点位置,光线方向是顶点法线(或其相反方向,但我认为这并不重要)。剩下的应该由插值完成。
然后在片段着色器中,我应该计算光线球体交点,如果有的话,更改片段的颜色。
在立方体的正面和背面,结果似乎是正确的,但在左侧、右侧、顶部和底部,结果似乎来自错误的角度。我应该始终看到中间的球体,而那些侧面的情况并非如此。
有人可以告诉我我做错了什么吗?
这是着色器代码:
顶点着色器:
#version 400
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNor;
uniform mat4 uProj;
uniform mat4 uView;
uniform mat4 uModel;
out vec3 vRayPos;
out vec3 vRayDir;
void main(void)
{
gl_Position = uProj * uView * uModel * vec4(aPos, 1);
vRayPos = aPos;
vRayDir = inverse(mat3(uModel)) * aNor;
}
Run Code Online (Sandbox Code Playgroud)
片段着色器:
#version 400
in vec3 vRayPos;
in vec3 vRayDir;
out vec4 oFrag;
void main(void) …Run Code Online (Sandbox Code Playgroud) 我试图在片段着色器中编写一个简单的光线追踪器。我有这个函数应该创建一个漫射球体,如下所示:
这是功能:
vec3 GetRayColor(Ray ray)
{
Ray new_ray = ray;
vec3 FinalColor = vec3(1.0f);
bool IntersectionFound = false;
int hit_times = 0;
for (int i = 0; i < RAY_BOUNCE_LIMIT; i++)
{
RayHitRecord ClosestSphere = IntersectSceneSpheres(new_ray, 0.001f, MAX_RAY_HIT_DISTANCE);
if (ClosestSphere.Hit == true)
{
// Get the final ray direction
vec3 R;
R.x = nextFloat(RNG_SEED, -1.0f, 1.0f);
R.y = nextFloat(RNG_SEED, -1.0f, 1.0f);
R.z = nextFloat(RNG_SEED, -1.0f, 1.0f);
vec3 S = normalize(ClosestSphere.Normal) + normalize(R);
S = normalize(S);
new_ray.Origin = ClosestSphere.Point;
new_ray.Direction = …Run Code Online (Sandbox Code Playgroud) 从我收集到的,他使用稀疏的体素八叉树和光线投射.似乎他没有使用opengl或direct3d,当我看到游戏Voxelstein时,看起来微型立方体实际上是被绘制而不是仅仅是一堆2d方形.这让我措手不及我不知道他如何在没有opengl或direct3d的情况下做到这一点.
我试着阅读源代码,但我很难理解发生了什么.我想实现类似的东西,并希望算法这样做.
我对他如何进行渲染,剔除,遮挡和照明感兴趣.任何帮助表示赞赏.
我正在为教育目的构建一个简单的光线跟踪器,并希望为对象添加折射.使用Snells Law,我能够在交叉点处递归地创建新的光线.光线跟踪器目前仅支持球体,我使用的场景中我有多个球体嵌套在彼此内部,具有不同的折射率.
如果我从球体外部开始射线,一切看起来都很简单.从场景的折射率开始,一旦击中第一个球体,使用前面的折射率和球体材质的折射率折射光线,直到你击中下一个球体,依此类推.使用交点的法线我可以确定我是进入还是离开球体.
但是,我不明白我应该如何处理球体叶子以及如果光线不在场景的外部开始该怎么办.
例
你有三个球体,从外到内的折射率分别为0.9,1.1和0.8.空气指数为1.0
您的相机位于球体外部并指向球体的中心:
现在问题,当相机在球体内时.您不知道必须切换的折射率.
我正在重写我的光线追踪器,并试图更好地理解它的某些方面.
我似乎已经解决了关于法线的问题,以及你应该如何将它们乘以变换矩阵的转置的倒数.
我感到困惑的是,我应该将我的方向向量归一化吗?
我正在关注某本书,有时候它会明确说明我的矢量和其他情况的归一化,我发现我需要.
归一化向量的方向相同,单位长度为1?所以我不清楚何时有必要?
谢谢
我正在编写一个3D光线跟踪器作为个人学习项目(Enlight),并遇到了一个有趣的问题,涉及在光线和物体场景之间进行交叉测试.
情况是:
Transform对象中来对具有任意仿射变换的场景对象进行渲染(重要的是,这将使得相同图元的多个实例能够在场景中的不同位置使用,因为图元是不可变的)Ray用于表示部分光线段的对象(起始矢量,标准化方向矢量,起始距离,结束距离)问题是当光线撞击Transform对象的边界框时,看起来与包含在其中的变换图元进行交叉测试的唯一方法是将变换Ray为坐标变换的坐标空间.这很容易,但是如果光线没有碰到任何变形的物体,我需要回到原始状态Ray继续跟踪.由于Transforms可以嵌套,这意味着我必须Ray为每个完成的交集跟踪维护一整堆s.
这当然是整个应用程序的内部循环和主要性能瓶颈.它将被称为每秒数百万次,所以我渴望最小化复杂性/避免不必要的内存分配.
有一种聪明的方法可以避免分配新Ray的/保持Ray堆栈吗?
或者有一种更聪明的方式完全这样做?
计算固定大小的体素数据的梯度的最有效方法是什么,例如下面的源代码.请注意,我需要在空间的任何位置使用渐变.渐变将用于估计行进立方体实现中的法线.
#import <array>
struct VoxelData {
VoxelData(float* data, unsigned int xDim, unsigned int yDim, unsigned int zDim)
:data(data), xDim(xDim), yDim(yDim), zDim(zDim)
{}
std::array<float,3> get_gradient(float x, float y, float z){
std::array<float,3> res;
// compute gradient efficiently
return res;
}
float get_density(int x, int y, int z){
if (x<0 || y<0 || z<0 || x >= xDim || y >= yDim || z >= zDim){
return 0;
}
return data[get_element_index(x, y, z)];
}
int get_element_index(int x, int y, int z){
return x …Run Code Online (Sandbox Code Playgroud) 我正在测试光线是否与三角形相交,所以暂时使用下面的代码来测试指定光线之间是否有交点,此时此方向的方向为随机三角形的中点:
Ray<float> *ray = new Ray<float>(Vec3<float>(0), chosenTriangle->GetTriangleMidpoint());
Run Code Online (Sandbox Code Playgroud)
旁边是Vec3对象,它用于存储向量操作:
template<typename T>
class Vec3
{
public:
T x, y, z;
Vec3() : x(T(0)), y(T(0)), z(T(0)) { }
Vec3(T xx) : x(xx), y(xx), z(xx) { }
Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {}
Vec3& normalize()
{
T nor2 = length2();
if (nor2 > 0) {
T invNor = 1 / sqrt(nor2);
x *= invNor, y *= invNor, z *= invNor;
}
return *this;
}
Vec3<T> operator * (const T …Run Code Online (Sandbox Code Playgroud) 我有一个小的路径跟踪器,我试图弄清楚如何实现一些基本的BRDF。这是我使用的管道的简要说明(无递归):
1) For each pixel:
1.1) For each sample:
1.1.1) I construct a path.
1.1.2) I calculate the contribution of this path.
1.1.3) I calculate the "probability" of this path.
1.1.4) Finally, I calculate the overall color value(taking into account number of samples, "probability" and contribution of the path).
1.2) Take the sum of all samples' values and write it to the pixel.
Run Code Online (Sandbox Code Playgroud)
因此,我在步骤中计算反射光线的方向1.1.1) I construct a path。
目前,我已经实现了漫反射,镜面反射,光泽反射和折射。现在,我想实现一个复杂的BRDF,比方说Cook-Torrance BRDF。我看到它包含几个成分(漫反射和镜面反射)。我应该如何追踪这些光线以获得组合?我应该像往常一样在diffuse_ray / specular_ray之间进行选择,然后像往常一样累加值(乘以一些系数)吗?(例如,如果随机值大于0.5,那么我将跟踪漫射射线,否则为-镜面反射)还是应该跟踪多条射线从每个路口?
通常在基于物理的渲染器中如何实现?
PS:如果有人知道关于该主题的一些好文章,我将很高兴看到他们。我尝试阅读pbrt,但对我来说似乎非常复杂且庞大。某些地方的实现方式有所不同,例如相机模型和其他东西。