在过去的几天里,我第一次一直在攻击光线跟踪器.然而,有一些困扰我的怪癖,我真的不知道如何解决.从一开始就存在的是场景中球体的形状 - 渲染时,它们实际上看起来像椭圆形.当然,场景中有透视,但最终的形状看起来仍然很奇怪.我附上了一个样本渲染,我所遇到的问题在图像左下角的反射球上特别明显.

我真的不知道是什么原因引起的.它可能是光线球体交叉代码,如下所示:
bool Sphere::intersect(Ray ray, glm::vec3& hitPoint) {
//Compute A, B and C coefficients
float a = glm::dot(ray.dir, ray.dir);
float b = 2.0 * glm::dot(ray.dir, ray.org-pos);
float c = glm::dot(ray.org-pos, ray.org-pos) - (rad * rad);
// Find discriminant
float disc = b * b - 4 * a * c;
// if discriminant is negative there are no real roots, so return
// false as ray misses sphere
if (disc < 0)
return false;
// compute q
float …Run Code Online (Sandbox Code Playgroud) 我正在使用 vulkan 计算着色器开发路径跟踪器。我实现了一个表示边界卷层次结构的树。BVH 的想法是最小化需要执行光线交叉测试的对象数量。
#1 幼稚的实现
我的第一个实现非常快,它将树向下遍历到BVH 树的单个叶子。但是,射线可能会与多个叶子相交。这段代码会导致一些三角形没有被渲染(尽管它们应该)。
int box_index = -1;
for (int i = 0; i < boxes_count; i++) {
// the first box has no parent, boxes[0].parent is set to -1
if (boxes[i].parent == box_index) {
if (intersect_box(boxes[i], ray)) {
box_index = i;
}
}
}
if (box_index > -1) {
uint a = boxes[box_index].ids_offset;
uint b = a + boxes[box_index].ids_count;
for (uint j = a; j < b; j++) { …Run Code Online (Sandbox Code Playgroud) 我注意到一些顶尖大学正在开设课程,向学生们讲授CS专业的计算机图形学相关科目.可悲的是,这是我的大学不提供的东西,我希望在接下来的几年中进入某个时间.
我从一些大学找到的几个项目很棒,虽然我最感兴趣的是两件事:
很抱歉发布这样模糊,让我们说实话,愚蠢的问题.这只是我一段时间想要做的事情,而且对于我来说,在我自己的时间里发展这个项目会很好.
我希望通过观察平面从相机产生光线.为了做到这一点,我需要我的相机位置("眼睛"),向上,向右和向向量(其中朝向是相机在相机所看到的物体方向上的向量)和P,观察平面上的点.一旦我有这些,产生的光线是:
ray = camera_eye + t*(P-camera_eye);
Run Code Online (Sandbox Code Playgroud)
其中t是沿光线的距离(假设现在t = 1).
我的问题是,如果它位于观察平面上的位置(i,j),我如何获得点P的3D坐标?假设给出了观察平面的左上角和右下角.
注意:观察平面实际上并不是一个平面,因为它不会在所有方向上无限延伸.相反,人们可能会将此平面视为宽度x高度图像.在x方向上,范围是0 - >宽度,在y方向上,范围是0 - >高度.我希望找到第(i,j)个元素的3D坐标,0
问候,
我正在开发一个使用六角形瓷砖地图的3D变体的游戏项目.瓷砖实际上是立方体,而不是六角形,但是像六边形一样布局(因为正方形可以转换为立方体从2D到3D外推,但没有十六进制的3D版本).这里有一个4x4x4地图的例子,而不是冗长的描述:

(我已经突出显示了一个任意的瓷砖(绿色)及其相邻的瓷砖(黄色),以帮助描述整个事物应该如何工作;但邻接功能不是问题,已经解决了.)
我有一个结构类型来表示图块,而地图则表示为一个3D图块的图块(包含在一个Map类中以添加一些实用工具方法,但这并不是很相关).每个瓷砖应该代表一个完美的立方体空间,它们的大小完全相同.而且,相邻"行"之间的偏移恰好是图块大小的一半.
这是足够的背景; 我的问题是:
考虑到两个点的坐标A和B,我怎么能生成砖(或者说,它们的坐标),其之间的直线的名单A和B会生气吗?
这将在以后用于各种目的,例如确定视线,充电路径合法性等.
顺便说一下,这可能很有用:我的地图使用(0,0,0)作为参考位置.地图的"锯齿状"可以定义为将每个瓷砖((y+z) mod 2) * tileSize/2.0从它在"理智"笛卡尔系统上的位置向右偏移.对于非锯齿状的行,产生0; 对于行为(y+z) mod 21,它产生0.5个tile.
我正在研究面向.Net Framework 4.0的C#4; 但我真的不需要特定的代码,只需要算法来解决奇怪的几何/数学问题.我一直在努力解决这个问题几天无济于事; 并试图在纸上绘制整个东西以"可视化"它也没有帮助:(.
提前感谢您的回答
language-agnostic algorithm geometry raytracing hexagonal-tiles
我正在实现一个光线跟踪器,我正在实现采样器.采样器是方形x = 0:1,y = 0:1上的随机点的生成器.每个采样器保存多组"随机"样本,每组包含给定数量的样本.
现在,其中一个采样器是NRooks.它以n x n块为单位划分表面,沿对角线选择块,在每个对角线块中提取一个随机点,最后先将x它们自身混洗,然后再对其进行随机抽样y.

这一切都很干净.然而,当提取点数时,我正在遵循的书提出了这些额外的要求,以打破后续像素和采样之间的相关性.第一个要求是每次设置耗尽时,随机选取一个新的样本集.为实现此目的而实现的代码如下:
Point2D Sampler::sample_unit_square(void) {
if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples;
return (samples[jump + count++ % num_samples]
}
Run Code Online (Sandbox Code Playgroud)
其中samples是Point2D的矢量大小num_samples*num_sets(它是线性化的).每次完成一个像素(计数可被num_samples整除)时,将提取新的跳转并用于指示线性阵列以开始新的集合.
由于我使用python,我的策略使用迭代器:
def __iter__(self):
while True:
for sample_set in random.choice(self._samples_sets):
for sample in sample_set:
yield sample
Run Code Online (Sandbox Code Playgroud)
这是微不足道的,并且工作正常.
第二个需要是改变指数,这就是我的问题所在.该书修改了如下代码
Point2D Sampler::sample_unit_square(void) {
if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples;
return (samples[jump + shuffled_indices[ …Run Code Online (Sandbox Code Playgroud) 我需要进行有限形式的光线追踪.我不需要反思.我只需要改变一个像素的颜色,这取决于它如何通过一个物体和折射.我也只需要测试光线和球体和磁盘之间的交叉点,没有别的.
这是我的着色器中的主要功能:
void main(void)
{
Ray ray;
ray.origin=vec3(0.5,0.5,.75);
ray.direction=vec3(gl_FragCoord.x/width,gl_FragCoord.y/height,-gl_FragCoord.z)-ray.origin;
ray.direction=normalize(ray.direction);
gl_FragColor=trace(ray);
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是关于射线的起源.我如何获得它的位置?现在,我只是摆弄它直到看起来正确,但如果我改变屏幕的宽度或高度,我必须四处玩,直到它看起来正确.
我的第二个问题是关于光线和光盘之间的交叉.我这样做是首先检查光线是否与平面相交,然后检查交叉点是否在光盘的半径范围内.我的代码看起来像这样
float intersectPlane(Ray ray,vec3 point,vec3 normal)
{
return dot(point-ray.origin,normal)/dot(ray.direction,normal);
}
...
det=intersectPlane(ray,bodies[count].position,vec3(0,0,1));
if(det>0)
{
if(distance(det*ray.direction,bodies[count].position)<=bodies[count].radius)
{
return vec4(1.0,0.0,0.0,1.0);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是如果body [count] .radius小于或等于光线原点的z位置,则不显示任何内容.所以
if(det>0)
{
if(distance(det*ray.direction,bodies[count].position)<=.76)
{
return vec4(1.0,0.0,0.0,1.0);
}
}
Run Code Online (Sandbox Code Playgroud)
导致可见磁盘,而使用实际半径导致什么都没有.
我有一个与光线追踪相关的宠物项目.我需要生成光线跟踪图像,但实际的光线跟踪不是这里的重点.因此,我希望能够自由地使用库来为我做这件事.
我知道POVray但有点害怕它有两个原因:
我已经谷歌搜索了几天,除了POV之外没有找到任何合适的东西.
问题是...
我是否应该克服它并使用POVray,或者是否有简单(但不简单),更小,隐藏的光线跟踪库可以免费提供,如在言论自由中?
我想知道计算几种不同光源和环境光产生的阴影的最准确方法.环境光是存在于整个"世界"中的光,具有相同的强度而没有特定的方向,并且漫射光是由点光源的直接照明而发生的照明.
鉴于Ka是表面环境反射率的系数,Ia是环境光的强度,Kd是表面漫反射率,Ip1是第一(相应)点光源的强度,N是表面法线,L1是光(相应的第一个来源)方向.
根据我的参考资料,现场颜色的强度应为:
I=Ka.Ia+Kd(Ip1(N.L1)+Ip2(N.L2))
其中' .'是点积.
但根据我的理解,真实的光强度应该在光源之间进行某种平均,而不仅仅是将它们加起来,这样如果只有两个光源,则公式应如下所示:
I=Ka.Ia+Kd(Ip1(N.L1)+Ip2(N.L2))/2
如果有3个光源,但是第三个被阻挡并且不直接照亮表面,那么:
I=Ka.Ia+Kd(Ip1(N.L1)+Ip2(N.L2))/3
(如果有一个所有3个灯都有贡献的地方,它会变得更亮.
我的假设是对的吗?
raytracing ×10
geometry ×3
algorithm ×2
c++ ×2
glsl ×2
graphics ×2
3d ×1
bounding-box ×1
intersection ×1
opengl ×1
shader ×1
trigonometry ×1
vulkan ×1