Introduction To Raymarching

发布于:2025-04-13 ⋅ 阅读:(18) ⋅ 点赞:(0)

在二维上我们画一个圆实际上就是定义一个pos 然后 周围的uv判断是否在圆内

三维上我们画一个球,实际上就是三维的坐标到某个pos来判断是否在球内

看一下作者的做法

float3 rayOrigin = viewDir - worldPos;
float3 offset = viewDir * 1;

float result = 0.0f;
for(int i = 0; i < 256; i++)
{
    float dist = length(rayOrigin - sphereCenter) - sphereRadius;
    if (dist < 0.01f)
    {
        return float3(1.0f, 0.0f, 0.0f);
    }
    rayOrigin += offset;
}
return float3(0.0f, 0.0f, 0.0f);

我们需要知道的是,这个球实际上还是我们在物体的表面上形成的视觉欺骗的效果,我们设置为平面并且设置为rayOrigin的颜色

float3 rayOrigin = viewDir - worldPos;
float3 offset = viewDir * 1;

float result = 0.0f;
for(int i = 0; i < 256; i++)
{
    float dist = length(rayOrigin - sphereCenter) - sphereRadius;
    if (dist < 0.01f)
    {
        return rayOrigin;
    }
    rayOrigin += offset;
}
return float3(0.0f, 0.0f, 0.0f);

其实我还是不是很理解这个球怎么算的,我的感觉就是作者的做法是为了让它立体

problem

因为这里是相对于worldpossition来偏移的,当我们在世界中使用的时候无法显示

获取obj的中心坐标然后减去像素的世界坐标让它变成相对obj的局部坐标

然后就可以得到世界空间的效果

通过增加输出转换为不透明遮罩得到一个比较不错的三维球体

float3 rayOrigin = viewDir - worldPos;
float3 offset = viewDir * 1;

float result = 0.0f;
for(int i = 0; i < 256; i++)
{
    float dist = length(rayOrigin - sphereCenter) - sphereRadius;
    if (dist < 0.01f)
    {
        mask = 1.0;
        return rayOrigin;
    }
    rayOrigin += offset;
}
mask = 0.0;
return float3(0.0f, 0.0f, 0.0f);

加入diffuse light

float3 rayOrigin = worldPos - viewDir;
float3 offset = viewDir * -1;

float result = 0.0f;
for(int i = 0; i < 256; i++)
{
    float dist = length(rayOrigin - sphereCenter) - sphereRadius;
    if (dist < 0.01f)
    {
        mask = 1.0;
        float3 normal = normalize(rayOrigin - sphereCenter);
        float3 diffuse = max(dot(normal, lightPos), 0.0f);
        return float3(1.0f, 0.0f, 0.0f) * diffuse;
    }
    rayOrigin += offset;
}
mask = 0.0;
return float3(0.0f, 0.0f, 0.0f);

记得把原本的颜色去掉

Specular

float3 rayOrigin = worldPos - viewDir;
float3 offset = viewDir * -1;

float result = 0.0f;
for(int i = 0; i < 256; i++)
{
    float dist = length(rayOrigin - sphereCenter) - sphereRadius;
    if (dist < 0.01f)
    {
        mask = 1.0;
        float3 normal = normalize(rayOrigin - sphereCenter);
        float diffuse = max(dot(normal, lightPos), 0.0f);
        
        float3 h = normalize((viewDir + lightPos));
        float spec = pow(max(dot(normal, h), 0.0f), specRate);
        return float3(1.0f, 0.0f, 0.0f) * diffuse + float3(1.0f, 1.0f, 1.0f) * spec;
    }
    rayOrigin += offset;
}
mask = 0.0;
return float3(0.0f, 0.0f, 0.0f);