我正在研究一个Opengl射线跟踪器,它能够加载obj文件并对其进行射线跟踪。我的应用程序使用assimp加载obj文件,然后使用着色器存储对象将所有三角形面(顶点和索引)发送到片段着色器。基本结构即将把结果从片段着色器渲染到四边形。
这是我的顶点着色器。它的制服负责将像素定位在四边形上。
#version 460 core
layout(location = 0) in vec2 cCamWindowVertex;
uniform vec3 wLookAt, wRight, wUp;
out vec3 p;
out vec2 pos;
void main()
{
pos=cCamWindowVertex.xy;
gl_Position = vec4(cCamWindowVertex, 0, 1);
p = wLookAt + wRight * cCamWindowVertex.x + cCamWindowVertex.y * wUp;
}
这是片段着色器,其方法与射线追踪有关。有一种方法可以检查射线与三角形面之间的相交(一个面是由primitveCoordinates []中的三个元素构成的)。 WEye制服是相机的位置。
#version 460 core
layout(std140, binding=2) buffer primitives{
vec3 primitiveCoordinates[];
};
layout(std140, binding=3) buffer indices{
vec3 indicesC[];
};
out vec4 FragColor;
in vec3 p;
uniform vec3 wEye;
struct Light{
vec3 Le, La;
vec3 direction;
vec3 position;
};
uniform Light lights[];
struct Ray{
vec3 orig, dir;
};
struct Hit{
vec3 orig, dir, normal;
float t;
};
Hit rayTriangleIntersect(Ray ray, vec3 v0, vec3 v1, vec3 v2){
Hit hit;
float t; float u; float v;
vec3 v0v1 = v1 - v0;
vec3 v0v2 = v2 - v0;
vec3 pvec = cross(ray.dir, v0v2);
float det = dot(v0v1, pvec);
if (abs(det) < 0.008){
hit.t=-1;
return hit;// Culling is off
}
float invDet = 1 / det;
vec3 tvec = ray.orig - v0;
u = dot(tvec, pvec) * invDet;
if (u < 0 || u > 1){
hit.t=-1;
return hit;
}
vec3 qvec = cross(tvec, v0v1);
v = dot(ray.dir, qvec) * invDet;
if (v < 0 || u + v > 1) {
hit.t=-1;
return hit;
}
hit.t = dot(v0v2, qvec) * invDet;
hit.normal= cross(v0v1, v0v2);
return hit;
}
vec3 getCoordinatefromIndices(float index){
vec3 back;
for (int i=0; i < primitiveCoordinates.length();i++){
if (i==index){
back=primitiveCoordinates[i];
break;
}
}
return back;
}
Hit firstIntersect(Ray ray){
Hit besthit;
besthit.t=-1;
for (int i=0;i<indicesC.length();i++){
vec3 TrianglePointA=getCoordinatefromIndices(indicesC[i].x);
vec3 TrianglePointB=getCoordinatefromIndices(indicesC[i].y);
vec3 TrianglePointC=getCoordinatefromIndices(indicesC[i].z);
Hit hit=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hit.t>0 && (besthit.t>hit.t || besthit.t<0)){
besthit=hit;
}
}
return besthit;
}
vec3 trace(Ray ray){
vec3 color;
vec3 ka=vec3(0.5215, 0.1745, 0.0215);
Hit hit;
hit=firstIntersect(ray);
if (hit.t==-1){
return lights[0].La;
}
color=lights[0].La*ka;
for (int i=0;i<lights.length();i++){
Ray shadowRay;
shadowRay.orig=hit.orig;
shadowRay.dir=lights[0].direction;
Hit shadowHit=firstIntersect(shadowRay);
if (shadowHit.t<0 || shadowHit.t > length(shadowRay.orig-hit.orig))
color= color+lights[0].Le;
}
}
return color;
}
void main()
{
Ray ray;
ray.orig = wEye;
ray.dir = normalize(p - wEye);
FragColor = vec4(trace(ray), 1);
}
main.cpp中有一些统一变量:
float fov = 145;
glm::vec3 eye = glm::vec3(0, 0, 2);
glm::vec3 vup = glm::vec3(0, 1, 0);
glm::vec3 lookat = glm::vec3(0, 0, 0);
glm::vec3 w = eye - lookat;
float f = length(w);
glm::vec3 right1 = normalize(cross(vup, w)) ;
glm::vec3 up = normalize(cross(w, right1)) ;
我有三个与此有关的问题。
我目前正在使用一个简单的多维数据集模型(在Blender中创建)。我可以看到它,但是当旋转相机时,立方体会拉伸。我不知道为什么这是立方体的图片。如果我过度旋转凸轮,它将成为第二张图片中的一个。
我的第二个问题与纹理有关。我是否可以通过这种应用程序结构添加obj(来自mtl)的纹理?我可以用assimp加载纹理。我正在考虑编写texture(texture_diffuse1, TexCoords);
并将其乘以负责射线追踪的fs方法计算出的颜色。但是,如果除了散开的表面之外还包含更多的纹理,则实现起来可能是个问题。
我的第三个问题:我是否选择了正确的方向来在opengl中实现光线跟踪器?
无论如何,这是我到源的github链接:https://github.com/fox-1942/rayTracerBoros/tree/testforRayTracing(当前使用的着色器是名称中带有“ quad”结尾的着色器。)
感谢您的帮助。谢谢!
您必须遵守视口的宽高比。
[计算射线方向的点时,wRight
和wUp
考虑纵横比:
p = wLookAt + wRight * cCamWindowVertex.x + cCamWindowVertex.y * wUp;
用两个长度相同的wRight
矢量定义wUp
和perpendicular。例如:
wRight = (0, -1, 0)
wUp = (1, 0, 0)
最后按纵横比缩放向量的x分量:
aspect = width/height
wRight.x = wRight.x * aspect
wRight.y = wRight.y * aspect