- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
注意:此问题已从其原始形式进行了彻底编辑
我正在尝试通过实现与体素化相结合的八叉树数据结构来创建对数光线追踪器,以实现快速光线追踪。
目前我在光线碰撞检测方面遇到问题。
预期的输出应该是带有法线贴图的体素化斯坦福龙。
目前的问题是有些区域是透明的:
完整的龙:
透明区域:
从这些图像中可以清楚地看出几何是正确的,但碰撞检查是错误的。
此过程涉及 2 个片段着色器:
#version 430
in vec3 f_pos;
in vec3 f_norm;
in vec2 f_uv;
out vec4 f_color;
struct Voxel
{
vec4 position;
vec4 normal;
vec4 color;
};
struct Node
{
int children[8];
};
layout(std430, binding = 0) buffer voxel_buffer
{
Voxel voxels[];
};
layout(std430, binding = 1) buffer buffer_index
{
uint index;
};
layout(std430, binding = 2) buffer tree_buffer
{
Node tree[];
};
layout(std430, binding = 3) buffer tree_index
{
uint t_index;
};
out vec4 fragment_color;
uniform int voxel_resolution;
uniform int cube_dim;
int getVIndex(vec3 position, int level)
{
float size = cube_dim / pow(2,level);
int bit2 = int(position.x > size);
int bit1 = int(position.y > size);
int bit0 = int(position.z > size);
return 4*bit2 + 2*bit1 + bit0;
}
void main()
{
uint m_index = atomicAdd(index, 1);
voxels[m_index].position = vec4(f_pos*cube_dim,1);
voxels[m_index].normal = vec4(f_norm,1);
voxels[m_index].color = vec4(f_norm,1);
int max_level = int(log2(voxel_resolution));
int node = 0;
vec3 corner = vec3(-cube_dim);
int child;
for(int level=0; level<max_level-1; level++)
{
float size = cube_dim / pow(2,level);
vec3 corners[] =
{corner, corner+vec3(0,0,size),
corner+vec3(0,size,0), corner+vec3(0,size,size),
corner+vec3(size,0,0), corner+vec3(size,0,size),
corner+vec3(size,size,0), corner+vec3(size,size,size)};
vec3 offsetPos = (vec3(voxels[m_index].position));
child = getVIndex(offsetPos-corner, level);
int mrun = 500;
while ((tree[node].children[child] <= 0) && (mrun > 0)){
mrun--;
if( (atomicCompSwap( tree[node].children[child] , 0 , -1) == 0 ))
{
tree[node].children[child] = int(atomicAdd(t_index, 1));
}
}
if(mrun < 1)
discard;
if(level==max_level-2)
break;
node = tree[node].children[child];
corner = corners[child];
}
tree[node].children[child] = int(m_index);
}
我理解逻辑可能不太清楚,所以让我解释一下:
我们从一个 3D psoition voxels[m_index].position = vec4(f_pos*cube_dim,1);
我们知道有一个维度为 (-cube_dim,-cube_dim,-cube_dim ) 到 (cube_dim,cube_dim,cube_dim)所以一个立方体,其对角线在原点相交,边长为 2*cube_dim。它被分成多个边长为 2*cube_dim/voxel_resolution 的小立方体。基本上这只是一个立方体 segmentation n 次以形成笛卡尔网格。
我们使用这个坐标从大立方体开始,将其 segmentation 为 8 个大小相等的子空间,并检测这些子空间中的哪个子空间包含该坐标。
我们这样做直到找到包含该位置的最小框。
#version 430
in vec2 f_coord;
out vec4 fragment_color;
struct Voxel
{
vec4 position;
vec4 normal;
vec4 color;
};
struct Node
{
int children[8];
};
layout(std430, binding = 0) buffer voxel_buffer
{
Voxel voxels[];
};
layout(std430, binding = 1) buffer buffer_index
{
uint index;
};
layout(std430, binding = 2) buffer tree_buffer
{
Node tree[];
};
layout(std430, binding = 3) buffer tree_index
{
uint t_index;
};
uniform vec3 camera_pos;
uniform float aspect_ratio;
uniform float cube_dim;
uniform int voxel_resolution;
float planeIntersection(vec3 origin, vec3 ray, vec3 pNormal, vec3 pPoint)
{
pNormal = normalize(pNormal);
return (dot(pPoint,pNormal)-dot(pNormal,origin))/dot(ray,pNormal);
}
#define EPSILON 0.001
bool inBoxBounds(vec3 corner, float size, vec3 position)
{
bool inside = true;
position-=corner;
for(int i=0; i<3; i++)
{
inside = inside && (position[i] > -EPSILON);
inside = inside && (position[i] < size+EPSILON);
}
return inside;
}
float boxIntersection(vec3 origin, vec3 dir, vec3 corner0, float size)
{
dir = normalize(dir);
vec3 corner1 = corner0 + vec3(size,size,size);
vec3 normals[6] =
{ vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1), vec3(1,0,0), vec3(0,1,0), vec3(0,0,1) };
float coeffs[6];
for(uint i=0; i<3; i++)
coeffs[i] = planeIntersection(origin, dir, normals[i], corner0);
for(uint i=3; i<6; i++)
coeffs[i] = planeIntersection(origin, dir, normals[i], corner1);
float t = 1.f/0.f;
for(uint i=0; i<6; i++){
coeffs[i] = coeffs[i] < 0 ? 1.f/0.f : coeffs[i];
t = inBoxBounds(corner0,size,origin+dir*coeffs[i]) ? min(coeffs[i],t) : t;
}
return t;
}
void sort(float elements[8], int indices[8], vec3 vectors[8])
{
for(uint i=0; i<8; i++)
{
for(uint j=i; j<8; j++)
{
if(elements[j] < elements[i])
{
float swap = elements[i];
elements[i] = elements[j];
elements[j] = swap;
int iSwap = indices[i];
indices[i] = indices[j];
indices[j] = iSwap;
vec3 vSwap = vectors[i];
vectors[i] = vectors[j];
vectors[j] = vSwap;
}
}
}
}
int getVIndex(vec3 position, int level)
{
float size = cube_dim / pow(2,level);
int bit2 = int(position.x > size);
int bit1 = int(position.y > size);
int bit0 = int(position.z > size);
return 4*bit2 + 2*bit1 + bit0;
}
#define MAX_TREE_HEIGHT 11
int nodes[8*MAX_TREE_HEIGHT];
int levels[8*MAX_TREE_HEIGHT];
vec3 positions[8*MAX_TREE_HEIGHT];
int sp=0;
void push(int node, int level, vec3 corner)
{
nodes[sp] = node;
levels[sp] = level;
positions[sp] = corner;
sp++;
}
void main()
{
vec3 r = vec3(f_coord.x, f_coord.y, 1.f/tan(radians(40)));
r.y/=aspect_ratio;
vec3 dir = r;
r += vec3(0,0,-1.f/tan(radians(40))) + camera_pos;
fragment_color = vec4(0);
//int level = 0;
int max_level = int(log2(voxel_resolution));
push(0,0,vec3(-cube_dim));
float tc = 1.f;
int level=0;
int node=0;
do
{
sp--;
node = nodes[sp];
level = levels[sp];
vec3 corner = positions[sp];
float size = cube_dim / pow(2,level);
vec3 corners[] =
{corner, corner+vec3(0,0,size),
corner+vec3(0, size,0), corner+vec3(0,size,size),
corner+vec3(size,0,0), corner+vec3(size,0,size),
corner+vec3(size,size,0), corner+vec3(size,size,size)};
float t = boxIntersection(r, dir, corner, size*2);
if(!isinf(t))
tc *= 0.9f;
float coeffs[8];
for(int child=0; child<8; child++)
{
if(tree[node].children[child]>0)
coeffs[child] = boxIntersection(r, dir, corners[child], size);
else
coeffs[child] = 1.f/0.f;
}
int indices[8] = {0,1,2,3,4,5,6,7};
sort(coeffs, indices, corners);
for(uint i=7; i>=0; i--)
{
if(!isinf(coeffs[i]))
{
push(tree[node].children[indices[i]],
level+1, corners[i]);
}
}
}while(level < (max_level-1) && sp>0);
if(level==max_level-1)
{
fragment_color = abs(voxels[node].normal);
}
else
{
fragment_color=vec4(tc);
}
}
}
在这里,我们从最大的立方体开始,测试与每组 8 个子级( segmentation 立方体得到的 8 个立方体)的交集。每次我们成功检测到碰撞时,我们都会沿着树向下移动,直到我们到达描述实际几何形状的最低级别,然后我们根据该级别为场景着色。
重要的是有2个buffer,一个用来存放除叶子之外的树,一个用来存放叶子。
所以在体素化和光线追踪中,最后一层需要区别对待。
我注意到的关于透明度的问题如下:
它只发生在与笛卡尔网格对齐的平面上
这似乎发生在光线向负方向移动时(向下或向左)。 (至少这是我的印象,但不是100%
一定)
我不确定我做错了什么。
编辑:
最初的问题似乎已经解决,但光线追踪器仍然存在问题。我已经编辑了问题以反射(reflect)问题的当前状态。
最佳答案
错误来自于评论中提到的某人的排序功能,尽管出于相同的原因。
发生的事情是,我认为排序函数会修改传递给它的数组,但它似乎在复制数据,所以它没有返回任何东西。
换句话说:
void sort(float elements[8], int indices[8], vec3 vectors[8])
{
for(uint i=0; i<8; i++)
{
for(uint j=i; j<8; j++)
{
if((elements[j] < elements[i]))
{
float swap = elements[i];
elements[i] = elements[j];
elements[j] = swap;
int iSwap = indices[i];
indices[i] = indices[j];
indices[j] = iSwap;
vec3 vSwap = vectors[i];
vectors[i] = vectors[j];
vectors[j] = vSwap;
}
}
}
}
不返回元素、索引和 vector 内部的正确值,因此调用此函数只会浪费计算周期。
关于c++ - Oct 树生成在最后一步出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50767629/
我正在使用 node.js 和 mocha 单元测试,并且希望能够通过 npm 运行测试命令。当我在测试文件夹中运行 Mocha 测试时,测试运行成功。但是,当我运行 npm test 时,测试给出了
我的文本区域中有这些标签 ..... 我正在尝试使用 replaceAll() String 方法替换它们 text.replaceAll("", ""); text.replaceAll("", "
早上好,我是 ZXing 的新手,当我运行我的应用程序时出现以下错误: 异常Ljava/lang/NoClassDefFoundError;初始化 ICOM/google/zxing/client/a
我正在制作一些哈希函数。 它的源代码是... #include #include #include int m_hash(char *input, size_t in_length, char
我正在尝试使用 Spritekit 在 Swift 中编写游戏。目的是带着他的角色迎面而来的矩形逃跑。现在我在 SKPhysicsContactDelegate (didBegin ()) 方法中犯了
我正在尝试创建一个用于导入 CSV 文件的按钮,但出现此错误: actionPerformed(java.awt.event.ActionEvent) in cannot implement
请看下面的代码 public List getNames() { List names = new ArrayList(); try { createConnection(); Sta
我正在尝试添加一个事件以在“dealsArchive”表中创建一个条目,然后从“deals”表中删除该条目。它需要在特定时间执行。 这是我正在尝试使用的: DELIMITER $$ CREATE EV
我试图将两个存储过程的表结果存储到 phpmyadmin 例程窗口中的单个表中,这给了我 mariadb 语法错误。单独调用存储过程给出了结果。 存储过程代码 BEGIN CREATE TABLE t
我想在 videoview 中加载视频之前有一个进度条。但是我收到以下错误。我还添加了所有必要的导入。 我在 ANDROID 中使用 AIDE 这是我的代码 public class MainActi
我已经使用了 AsyncTask,但我不明白为什么在我的设备 (OS 4.0) 上测试时仍然出现错误。我的 apk 构建于 2.3.3 中。我想我把代码弄错了,但我不知道我的错误在哪里。任何人都请帮助
我在测试 friend 网站的安全性时,通过在 URL 末尾添加 ' 发现了 SQL 注入(inject)漏洞该网站是用zend框架构建的我遇到的问题是 MySQL -- 中的注释语法不起作用,因此页
我正在尝试使用堆栈溢出答案之一的交互式信息窗口。 链接如下: interactive infowindow 但是我在代码中使用 getMap() 时遇到错误。虽然我尝试使用 getMapAsync 但
当我编译以下代码时出现错误: The method addMouseListener(Player) is undefined for the type Player 代码: import java.
我是 Android 开发的初学者。我正在开发一个接收 MySql 数据然后将其保存在 SQLite 中的应用程序。 我将 Json 用于同步状态,以便我可以将未同步数据的数量显示为要同步的待处理数据
(这里是Hello world级别的自动化测试人员) 我正在尝试下载一个文件并将其重命名以便于查找。我收到一个错误....这是代码 @Test public void allDownload(
我只是在写另一个程序。并使用: while (cin) words.push_back(s); words是string的vector,s是string。 我的 RAM 使用量在 4 或 5
我是 AngularJS 的新手,我遇到了一个问题。我有一个带有提交按钮的页面,当我单击提交模式时必须打开并且来自 URL 的数据必须存在于模式中。现在,模式打开但它是空的并且没有从 URL 获取数据
我正在尝试读取一个文件(它可以包含任意数量的随机数字,但不会超过 500 个)并将其放入一个数组中。 稍后我将需要使用数组来做很多事情。 但到目前为止,这一小段代码给了我 no match for o
有些人在使用 make 命令进行编译时遇到了问题,所以我想我应该在这里尝试一下,我已经在以下操作系统的 ubuntu 32 位和挤压 64 位上尝试过 我克隆了 git 项目 https://gith
我是一名优秀的程序员,十分优秀!