为什么在相机旋转期间拉伸模型,以及如何解决纹理化问题?

问题描述 投票:1回答:1

我正在研究一个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中创建)。我可以看到它,但是当旋转相机时,立方体会拉伸。我不知道为什么这是立方体的图片。如果我过度旋转凸轮,它将成为第二张图片中的一个。

enter image description here

enter image description here

我的第二个问题与纹理有关。我是否可以通过这种应用程序结构添加obj(来自mtl)的纹理?我可以用assimp加载纹理。我正在考虑编写texture(texture_diffuse1, TexCoords);并将其乘以负责射线追踪的fs方法计算出的颜色。但是,如果除了散开的表面之外还包含更多的纹理,则实现起来可能是个问题。

我的第三个问题:我是否选择了正确的方向来在opengl中实现光线跟踪器?

无论如何,这是我到源的github链接:https://github.com/fox-1942/rayTracerBoros/tree/testforRayTracing(当前使用的着色器是名称中带有“ quad”结尾的着色器。)

感谢您的帮助。谢谢!

opengl glsl shader raytracing
1个回答
0
投票

您必须遵守视口的宽高比。

[计算射线方向的点时,wRightwUp考虑纵横比:

p = wLookAt + wRight * cCamWindowVertex.x + cCamWindowVertex.y * wUp;

用两个长度相同的wRight矢量定义wUpperpendicular。例如:

wRight = (0, -1, 0)
wUp = (1, 0, 0)

最后按纵横比缩放向量的x分量:

aspect = width/height
wRight.x = wRight.x * aspect
wRight.y = wRight.y * aspect
© www.soinside.com 2019 - 2024. All rights reserved.