Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 半球的光线追踪_C_Geometry_Raytracing - Fatal编程技术网

C 半球的光线追踪

C 半球的光线追踪,c,geometry,raytracing,C,Geometry,Raytracing,我目前正在使用C编写一个基本的光线跟踪程序,我已经成功地创建了一些简单的形状ex,sphere/box/plane/cone/…,我还使用phong照明对它们进行了一些着色处理。 但我的问题是,我可以掌握光线跟踪半球的方法,比如是否有一个定义半球的集合方程,如果有,请启发我,因为我找不到任何,或者是否有一个集合方法来做这件事,我想不出来 我也试着用一个平面切割球体,只显示上半部分,但没有效果(我对这一切还是新手,所以我的理解可能是错误的) 编辑:好的,我很抱歉,因为我对这一切都很陌生,但以下是我

我目前正在使用C编写一个基本的光线跟踪程序,我已经成功地创建了一些简单的形状ex,sphere/box/plane/cone/…,我还使用phong照明对它们进行了一些着色处理。
但我的问题是,我可以掌握光线跟踪半球的方法,比如是否有一个定义半球的集合方程,如果有,请启发我,因为我找不到任何,或者是否有一个集合方法来做这件事,我想不出来

我也试着用一个平面切割球体,只显示上半部分,但没有效果(我对这一切还是新手,所以我的理解可能是错误的)

编辑:好的,我很抱歉,因为我对这一切都很陌生,但以下是我尝试过的

#include "raytacing.h"

t_env  *init_sphere(t_env *e)
{
//sphere position and radius
    e->sph.posi.x = 0;
    e->sph.posi.y = 0;
    e->sph.posi.z = -1;
    e->sph.rad = 0;
    e->sph.color = (t_color){255, 255, 128);
    return (e);
}

t_env  *init_plane(t_env *e)
{
//plane position
    e->plane.posi.x = 0;
    e->olane.posi.y = -0.5;
    e->plane.posi.z = 0;
//plane normal
    e->plane.norm.x = 0;
    e->olane.norm.y = 1;
    e->plane.norm.z = 0;

    e->plane.color = (t_color){0, 255, 0);
    return (e);
}

double         inter_plane(t_env *e, double *t) //calculating plane intersection
{
    t_vect  dist;
    double  norm;

    norm = dot(e->plane.normal, e->r.direction);
    if (fabs(norm) > 1e-6)
    {
        dist = vect_sub(e->plane.posi, e->r.start);
        e->t0 = dot(dist, e->plane.normal) / norm;
        if (e->t0 < *t && e->t0 > 1e-6)
        {
            *t = e->t0;
            return (1);
        }
        else
            return (0);
    } 
    return (0);
}

double      inter_sph(t_env *e, double *t) //calculating sphere intersection
{
    double  delta;
    double  sqrtd;
    t_vect  dist;

    e->a = dot(e->r.direction, e->r.direction);
    dist = vect_sub(e->r.start, e->sph.posi);
    e->b = 2 * dot(dist, e->r.direction);
    e->c = dot(dist, dist) - e->sph.rad * e->sph.rad;
    delta = e->b * e->b - 4 * e->a * e->c;
    if (delta < 0)
        return (0);
    sqrtd = sqrt(delta);
    e->t0 = (-e->b + sqrtd) / (2 * e->a);
    e->t1 = (-e->b - sqrtd) / (2 * e->a);
    if (e->t0 > e->t1)
        e->t0 = e->t1;
    if ((e->t0 > 1e-6) && (e->t0 < *t))
    {
        *t = e->t0;
        return (1);
    }
    else
        return (0);
}

double      inter_hemisphere(t_env *e) //calculating hemisphere intersection
{
    t_vect  hit_normal;

    if (inter_sph(e, &e->t) == 1)
    {

        hit_normal = vect_add(e->r.start, vect_scalaire(e->t, e->r.direction));
        hit_normal = vect_normalize(hit_normal);

        if (inter_plane(e, &(e->t)) == 1)
        {
            if (dot(e->plane.normal, hit_normal) < 0)
                return (1);
            return (0);
        }
    }
    return (0);
}
结果如下:


最简单的方法是将球体切割成一个平面

如果平面法线大于任何方向(球体上的点-球体中心),则与法线方向相同的平面将被切断。仅凭此条件:

dot(point on sphere - sphere center , plane normal ) > 0.0
但别忘了测试光线和球体的交点,因为最近的交点可能在平面的另一侧

我试图在我的GLSL光线跟踪器中实现这一点:

并提供更新的片段着色器:

顶点(无更改):

//------------------------------------------------------------------
#版本420核心
//------------------------------------------------------------------
均匀浮动方面;
均匀浮动焦距;
均匀的mat4x4 tm_眼;
vec2位置中的布局(位置=0);
输出平滑vec2 txt_pos;//屏幕上用于调试打印的frag位置
输出平滑vec3射线_pos;//射线起始位置
输出平滑vec3光线方向;//射线起始方向
//------------------------------------------------------------------
真空总管(真空)
{
vec4p;
txt_pos=pos;
//透视投影
p=tm_eye*vec4(位置x/纵横比,位置y,0.0,1.0);
射线位置=p.xyz;
p-=tm_眼睛*vec4(0.0,0.0,-焦距,1.0);
ray_dir=规格化(p.xyz);
gl_位置=vec4(位置,0.0,1.0);
}
//------------------------------------------------------------------
片段(添加的半球):

//------------------------------------------------------------------
#版本420核心
//------------------------------------------------------------------
//射线跟踪器版本:1.000
//------------------------------------------------------------------
在平滑vec3光线中_pos;//射线起始位置
在平滑的vec3光线_dir;//射线起始方向
均匀浮动n0;//摄像机原点折射率
统一整数fac_siz;//方形纹理x、y分辨率大小
统一整数fac_num;//纹理中的有效浮动数
均匀取样器2D fac_txr;//场景网格数据纹理
输出布局(位置=0)矢量4框架;
//---------------------------------------------------------------------------
#定义-反映
#定义折射
//---------------------------------------------------------------------------
真空总管(真空)
{
常量vec3 light_dir=规格化(vec3(0.1,0.1,1.0));
常量浮点数\u iamb=0.1;//点偏移
恒浮光_idir=0.5;//平行光振幅
常量vec3 back_col=vec3(0.2,0.2,0.2);//背景色
const float _zero=1e-6;//避免光线起点的干涉
const int_fac_triangles=0;//r,g,b,a,n,三角形计数,{x0,y0,z0,x1,y1,z1,x2,y2,z2}
const int_fac_spheres=1;//r,g,b,a,n,sphere count,{x,y,z,r}
const int_fac_半球=2;//r,g,b,a,n,半球计数,{x,y,z,r,nx,ny,nz}
//光线场景相交
结构射线
{
dvec3位置、方向或非;
vec3-col;
float refl,refr;//反射,折射强度系数
浮点n0,n1;//重构索引(开始,结束)
双l;//射线长度
int lvl,i0,i1;//递归级别,反射,折射
};
常数int _lvls=4;
常数int_射线=(10.0)l1=-1.0;
//***这只是使用更近的有效命中

如果(l0“它不起作用”不是一个有用的描述。请在这里显示您的尝试。然后解释它不起作用的方式。通过平面切割是一种简单地检查点符号的方式(平面正常,点击正常)
另一个选项是将光线转换为对象局部坐标系,只需检查命中位置坐标之一的符号……没有代码,没有MCVE没有有效的问题描述,因此无法回答此问题+Close@Spektre我尝试了你说的,我得到了实际显示,但它仍然不正确,我似乎不知道我在哪里我错了。我确实添加了我试图用截图做的事情。@HeartStabQQ您只测试球体的第一次命中。在某些情况下,您需要使用第二次命中(如果第一次命中在飞机的错误一侧)这就是为什么第一个图像缺少半球的另一侧。旋转结果提示您旋转不正确…顺便说一句,渲染对象的线框(使用矢量图形而不是光线跟踪)可以帮助您进行调试(查看光线跟踪是否适合,如果不适合,请查看具体位置…)@HeartStabQQ我为平面切割方法添加了可用代码的答案。但是它基于我的GLSL光线跟踪器,所以你需要将它移植到你的(太懒了,无法从你的代码创建可用的光线跟踪器,因为编码太多)很抱歉,我花了一段时间才回复,但它工作正常,即使在第一次我试着做你的交集时,我有一些NUL变量,但当我把它转换为我做交集的方式时,它工作正常,第一次尝试。关于旋转,它工作正常,甚至没有改变它,只是我做的有一个交叉点计算可能是错误的。非常感谢您的时间。我将更新函数的代码
dot(point on sphere - sphere center , plane normal ) > 0.0