Opengl 为什么网格对象后面没有阴影?

Opengl 为什么网格对象后面没有阴影?,opengl,glsl,shadow,raytracing,Opengl,Glsl,Shadow,Raytracing,我正在为多边形模型创建一个基于OpenGL的光线跟踪器。基本结构将从片段着色器将结果渲染到四元体。为了加速应用,使用了BVH树 问题是,该方法测试阴影光线是否与某个对象相交,如果该对象不应返回true,则返回true,这意味着根本没有阴影。立方体只有两个面是黑色的,它们不面对光源 这是一个屏幕截图,你可以在平面上看到一个立方体。还有一个光源。 以下是片段着色器的有用部分:trace和shadowIntersect方法: bool shadowIntersect(Ray ray1){ // fo

我正在为多边形模型创建一个基于OpenGL的光线跟踪器。基本结构将从片段着色器将结果渲染到四元体。为了加速应用,使用了BVH树

问题是,该方法测试阴影光线是否与某个对象相交,如果该对象不应返回true,则返回true,这意味着根本没有阴影。立方体只有两个面是黑色的,它们不面对光源

这是一个屏幕截图,你可以在平面上看到一个立方体。还有一个光源。

以下是片段着色器的有用部分:
trace
shadowIntersect
方法:

bool shadowIntersect(Ray ray1){ // for testing if the shadowray intersects something
    for (int i;i<nodes.length();i++){
        for (int j=0;j<nodes[i].indices.length();j++){
            if (mod(nodes[i].indices[j].x,1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
                vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
                vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
                vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
                Hit hit=rayTriangleIntersect(ray1, TrianglePointA, TrianglePointB, TrianglePointC);
                if (hit.t>0){
                    return true;
                }
            }
        }
    }
    return false;
}
vec3 trace(Ray ray){
    const float epsilon = 0.0001f;
    vec3 outRadiance = vec3(0, 0, 0);
    vec3 gold_ka = vec3(0.24725f, 0.1995f, 0.0745f);
    vec3 gold_kd = vec3 (40.75164f, 0.60648f, 0.22648f);
    vec3 gold_ks = vec3 (0.628281f, 0.555802f, 0.366065f);
    float goldshininess= 0.4f;

    // Traversing the bounding volume hierachies tree
    Hit hit=traverseBvhTree(ray);

    if (hit.t<0){ return lights[0].La;}

    outRadiance+= gold_ka * lights[0].La;

    Ray shadowRay;
    shadowRay.orig = normalize(hit.orig) + normalize(hit.normal) * epsilon;
    shadowRay.dir  = normalize(lights[0].direction);

    float cosTheta = dot(normalize(hit.normal), normalize(lights[0].direction));

    // if the shadow ray intersects nothing, we add the emission coefficient of the light.
    if (cosTheta>0 && shadowIntersect(shadowRay)==false) {
        outRadiance +=lights[0].Le * gold_kd * cosTheta;

    }
    return outRadiance;
}
上面的变化给了我一个只有环境光的立方体

我还测试了以下行:

 if(shadowIntersect(shadowRay)==false){
        return vec3(1,1,1);
    }
    return vec3(0,0,0);
这一次,整个对象变为黑色,所以问题也应该出在阴影相交方法上

以下是完整片段着色器:

#version 460 core

layout(std140, binding=0) buffer primitives{
    vec4 primitiveCoordinates[];
};


struct FlatBvhNode
{
// base aligment                aligned offset
    vec4 min;// 16 byte              0
    vec4 max;// 16 byte             16
    int  order;// 4 byte            32
    int  isLeaf;// 4 byte           36
    int  createdEmpty;// 4 byte     40
    int  leftOrRight;
    vec4 indices[100];// 32 byte     48
};

layout(std430, binding=1) buffer TNodes
{
    FlatBvhNode nodes[];
};

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;
    hit.t=-1;
    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.0001){
        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;
}

vec4 getCoordinatefromIndices(float index){
    return primitiveCoordinates[int(index)];
}


FlatBvhNode leftChild(FlatBvhNode node){
    return nodes[2*node.order+1];
}

FlatBvhNode rightChild(FlatBvhNode node){
    return nodes[2*node.order+2];
}

bool rayIntersectWithBox(vec4 boxMin, vec4 boxMax, Ray r) {
    vec3 invdir = 1.0 / r.dir.xyz;
    vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
    vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;

    vec3 tmax = f * sign(invdir);
    vec3 tmin = n * sign(invdir);

    return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
}


Hit traverseBvhNode(Ray ray, FlatBvhNode node){
    Hit besthit;
    besthit.t=-1;
    bool hit;
    Hit hitreal;
    int i=0;

    while (i<=nodes.length()) {


        if (nodes[i].isLeaf==1){
            for (int j=0;j<nodes[i].indices.length();j++){
                if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
                    vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
                    vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
                    vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;

                    hitreal=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);

                    if (hitreal.t==-1){ continue; }

                    if (hitreal.t>0 && (besthit.t>hitreal.t || besthit.t<0)){
                        besthit=hitreal;
                    }
                    if(dot(ray.dir, besthit.normal)>0) besthit.normal = besthit.normal * (-1);
                }
            }

            if (nodes[i].leftOrRight==0){
                i=i+1;
                continue;
            }


            else if (nodes[i].leftOrRight==1){

                int id=int(ceil(i-2)/2);
                FlatBvhNode parent=nodes[id];

                while (parent.leftOrRight==1){
                    parent=nodes[int(ceil(parent.order-2)/2)];
                    if (parent.order==0){
                        return besthit;
                    }
                }
                i = parent.order+1;
                continue;
            }
        }


        hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);

        if (hit) {
            if (nodes[i].isLeaf==0){
                i=2*i+1;
                continue;
            }
        }

        else {

            if (nodes[i].order==0){
                break;
            }


            if (nodes[i].leftOrRight==0) {
                i=i+1;
                continue;
            }

            else if (nodes[i].leftOrRight==1){
                FlatBvhNode parent=nodes[int(ceil(i-2)/2)];

                while (parent.leftOrRight==1){
                    parent=nodes[int(ceil(parent.order-2)/2)];
                    if (parent.order==0){
                        if (parent.order==0){
                            return besthit;
                        }
                    }
                }
                i = parent.order+1;
                continue;
            }
        }
    }
    return besthit;
}


Hit traverseBvhTree(Ray ray){
    return traverseBvhNode(ray, nodes[0]);
}

bool shadowIntersect(Ray ray1){ // for testing if the shadowray intersects something
    for (int i;i<nodes.length();i++){
        for (int j=0;j<nodes[i].indices.length();j++){
            if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
                vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
                vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
                vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
                if (rayTriangleIntersect(ray1, TrianglePointA, TrianglePointB, TrianglePointC).t>0){
                    return true;

                }
            }
        }
    }
    return false;
}

vec3 trace(Ray ray){
    const float epsilon = 0.0001f;
    vec3 outRadiance = vec3(0, 0, 0);
    vec3 gold_ka = vec3(0.44725f, 0.3995f, 0.2745f);
    vec3 gold_kd = vec3 (40.75164f, 0.60648f, 0.22648f);
    vec3 gold_ks = vec3 (0.628281f, 0.555802f, 0.366065f);
    float goldshininess= 0.4f;

    // Traversing the bounding volume hierachies tree
    Hit hit=traverseBvhTree(ray);

    if (hit.t<0){ return lights[0].La; }

    outRadiance+= gold_ka * lights[0].La;

    Ray shadowRay;

    /*shadowRay.orig = hit.orig + normalize(hit.normal) * epsilon;
    shadowRay.dir  = normalize(lights[0].direction);*/

    shadowRay.dir = normalize(lights[0].direction);
    shadowRay.orig = hit.orig + shadowRay.dir * epsilon;

    float cosTheta = dot(normalize(hit.normal), normalize(lights[0].direction));

    // if the shadow ray intersects nothing, we add the emission coefficient of the light.
    if (cosTheta>0 && shadowIntersect(shadowRay)==false) {
        outRadiance +=lights[0].Le * gold_kd * cosTheta;
        vec3 halfway = normalize(-normalize(ray.dir) + normalize(lights[0].direction));
        float cosDelta = dot(normalize(hit.normal), halfway);
        if (cosDelta > 0) outRadiance += lights[0].Le * gold_ks * pow(cosDelta, goldshininess);

    }
    return outRadiance;
}


void main()
{
    Ray ray;
    ray.orig = wEye;
    ray.dir = normalize(p - wEye);
    FragColor = vec4(trace(ray), 1);

    // FragColor = vec4(nodes[4].isLeaf, 1, 1, 1);
}
#版本460核心
布局(std140,绑定=0)缓冲区原语{
vec4基元坐标[];
};
结构FlatBvhNode
{
//基线对齐偏移量
vec4 min;//16字节0
vec4 max;//16字节16
int顺序;//4字节32
int isLeaf;//4字节36
int createdEmpty;//4字节40
int左向右;
vec4索引[100];//32字节48
};
布局(std430,绑定=1)缓冲区TNodes
{
FlatBvhNode节点[];
};
out vec4 FragColor;
vec3p;
均匀vec3-wEye;
结构光{
维克勒,洛杉矶;
vec3方向;
vec3位置;
};
均匀光照[];
结构射线{
vec3 orig,dir;
};
结构命中{
向量3原点,方向,正常;
浮动t;
};
命中光线三角形相交(光线,vec3 v0,vec3 v1,vec3 v2){
击中击中;
hit.t=-1;
浮球t;浮球u;浮球v;
vec3 v0v1=v1-v0;
vec3 v0v2=v2-v0;
vec3 pvec=交叉(射线方向,v0v2);
浮点数=点(v0v1,pvec);
如果(绝对绝对值(det)<0.0001){
hit.t=-1;
返回命中;//剔除已关闭
}
浮动invDet=1/det;
vec3 tvec=射线源-v0;
u=点(tvec、pvec)*invDet;
如果(u<0 | | u>1){
hit.t=-1;
回击;
}
vec3 qvec=交叉(tvec,v0v1);
v=点(射线方向,qvec)*invDet;
如果(v<0 | | u+v>1){
hit.t=-1;
回击;
}
hit.t=点(v0v2,qvec)*invDet;
命中正常=交叉(v0v1,v0v2);
回击;
}
vec4 getCoordinatefromIndices(浮动索引){
返回原始坐标[int(索引)];
}
FlatBvhNode leftChild(FlatBvhNode节点){
返回节点[2*节点订单+1];
}
FlatBvhNode rightChild(FlatBvhNode节点){
返回节点[2*节点.订单+2];
}
布尔光线与长方体相交(vec4 boxMin,vec4 boxMax,光线r){
vec3 invdir=1.0/r.dir.xyz;
vec3 f=(boxMax.xyz-r.orig.xyz)*invdir;
vec3 n=(boxMin.xyz-r.orig.xyz)*invdir;
vec3 tmax=f*符号(invdir);
vec3 tmin=n*符号(invdir);
返回tmin.x
我认为您的shadowRay配置是问题所在

Ray shadowRay;
shadowRay.dir = normalize(lights[0].position - hit.orig);
shadowRay.orig = hit.orig + shadowRay.dir * epsilon

假定阴影光线从交点开始,方向朝向灯光

问题是,我没有在光线交点算法中计算交点的原点

添加此行解决了以下问题:

hit.orig=ray.orig+normalize(ray.dir)*hit.t;

现在,立方体仅使用环境照明进行可视化。我在问题的更新部分发布了结果。很好,你找到了问题。完全错过了。
hit.orig=ray.orig+normalize(ray.dir)*hit.t;