c++ - OpenGL 中的非随机半球样​​本

标签 c++ opengl

我目前正在使用一种采样方法来追踪光线,我使用这段代码对半球上的一个随机点进行采样并输出一个 vector :

vec3 CosWeightedRandomHemisphereDirection( vec3 n, float rand1, float rand2 )
{
    float Xi1 = rand1;
    float Xi2 = rand2;

    float  theta = acos(sqrt(1.0-Xi1));
    float  phi = 2.0 * 3.1415926535897932384626433832795 * Xi2;

    float xs = sin(theta) * cos(phi);
    float ys = cos(theta);
    float zs = sin(theta) * sin(phi);

    vec3 y = n;
    vec3 h = y;
    if (abs(h.x)<=abs(h.y) && abs(h.x)<=abs(h.z))
        h.x= 1.0;
    else if (abs(h.y)<=abs(h.x) &&abs(h.y)<=abs(h.z))
        h.y= 1.0;
    else
        h.z= 1.0;

    vec3 x = normalize(cross(h,y));
    vec3 z = normalize(cross(x,y));

    vec3 direction = xs * x + ys * y + zs * z;
    return normalize(direction);
}

现在,如果我希望样本相对于半球始终具有固定位置,例如 those vectors每个半球都以 60° 的角度采样,我该如何调整代码?我将 vector 保存在一个数组中。 所以我的函数会有一个像

这样的标题
vec3 FixedHemisphereDirection( vec3 n, vec3 sampleDir)

其中 sampleDir 是 6 个固定方向之一 还有,位置要固定了,代码能不能优化一下?

编辑:

我注意到方向只对指向上方或下方的法线有效,而对其余法线无效(我花了一段时间才注意到,因为我一直在使用随机方向)。这是我现在使用的代码。

    vec3 FixedHemisphereDirection( vec3 n, vec3 sampleDir)
{
    vec3 x;
    vec3 z;

    if(abs(n.x) < abs(n.y)){
        if(abs(n.x) < abs(n.z)){
            x = vec3(1.0f,0.0f,0.0f);
        }else{
            x = vec3(0.0f,0.0f,1.0f);
        }
    }else{
        if(abs(n.y) < abs(n.z)){
            x = vec3(0.0f,1.0f,0.0f);
        }else{
            x = vec3(0.0f,0.0f,1.0f);
        }
    }

    z = normalize(cross(x,n));
    x = cross(n,z);

    mat3 M = mat3(  x.x, n.x, z.x,
                    x.y, n.y, z.y,
                    x.z, n.z, z.z);
    return M*sampleDir;
}

最佳答案

单个法线不足以唯一标识半球的局部坐标系。它可以围绕该法线沿任何方向旋转。

我们首先需要构建局部坐标系。因此,我们需要局部 x 和 z 轴。 y 轴已经由法线给出。所有轴都应相互正交。所以我们可以这样做:

x := (1, 0, 0)
z := normalize(cross(x, n))
x := cross(n, z)

如果法线平行于(1, 0, 0),您应该选择另一个x轴,因为叉积将为零。

从这些轴,我们可以构造一个变换矩阵:

     / x.x  n.x  z.x \
M := | x.y  n.y  z.y |
     \ x.z  n.z  z.z /

这是将六个给定方向转换为 n 指定的半球方向的矩阵。

dir := randomly pick on of the six directions
return M * dir

关于c++ - OpenGL 中的非随机半球样​​本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24758507/

相关文章:

C++(E0158 表达式必须是左值或函数指示符)和(错误 C2102 '&' 需要左值)

android - 强制停止自动旋转(Android、C++、SDL2)

c++ - 将共享内存指针类型转换为整数指针

c++ - 使用 openGL、C++ 绘制/渲染的替代方法

opengl - 初始化 vao 时出错(glCreateVertexArrays())

c++ - 调用 glDrawElements 时出现段错误

指向类的 C++ 指针,释放类实例的调用函数,这是好的做法吗?

c++ - 使用 cgal 二次规划求解超定系统

c++ - openGL 中带有/对象的静态背景。 "bake"的最佳方式?

c++ - 学习现代 OpenGL