在片段着色器中实现RayPicking

时间:2019-01-29 01:43:52

标签: glsl webgl fragment-shader

我在Fragment-Shader中实现RayPicking时遇到了麻烦,我知道我必须从鼠标坐标开始,但是我不确定用什么乘以原点。

我尝试创建一个3分量矢量,用x和y作为鼠标坐标除以我的分辨率,在z中,我尝试使用p(对于空间中的点,计算为rayOrigin + rayDirection * t),不使用运气。 这是https://ktor.io/,它会尝试我要寻找的内容。

float ray( vec3 ro, vec3 rd, out float d )
{

   float t = 0.0; d = 0.0;

   for( int i = 0; i < STEPS; ++i )
   {

       vec3 p = ro + rd * t;
       d = map( p );

       if( d < EPS || t > FAR ) break;

       t += d;

    }

    return t;

}

vec3 shad( vec3 ro, vec3 rd, vec2 uv )
{

    float t = 0.0, d = 0.0;
    t = ray( ro, rd, d );

    float x = ( 2.0 * iMouse.x ) / iResolution.x - 1.0;
    float y = 1.0 - ( 2.0 * iMouse.y ) / iResolution.y;
    float z = 1.0;

    vec3 p = ro + rd * t;
    vec3 n = nor( p );
    vec3 lig = ( vec3( x, -y, z ) );
    lig += ro + rd;
    lig = normalize( lig );
    vec3 ref = reflect( rd, n );

    float amb = 0.5 + 0.5 * n.y;
    float dif = max( 0.0, dot( n, lig ) );
    float spe = pow( clamp( dot( ref, lig ), 0.0, 1.0 ), 16.0 );

    vec3 col = vec3( 0 );

    col += 0.1 * amb;
    col += 0.2 * dif;
    col += spe;

    return col;

}

我希望获得移动的光,就像我正在从鼠标坐标向SDF发射光线一样。

1 个答案:

答案 0 :(得分:0)

这是正确的代码:

// Our sphere-tracing algorithm.
float ray( vec3 ro, vec3 rd, out float d )
{

    float t = 0.0; d = 0.0;

    for( int i = 0; i < STEPS; ++i )
    {

        vec3 p = ro + rd * t;
        d = map( p );

        if( d < EPS || t > FAR ) break;

        t += d;

    }

    return t;

}

// Here we compute all our lighting calculations.
vec3 shad( vec3 ro, vec3 rd, vec2 uv )
{

    float t = 0.0, d = 0.0;
    t = ray( ro, rd, d );

    vec3 p = ro + rd * t;
    vec3 n = nor( p );
    // The values of the variable lig are not random they are in the same position as our rayOrigin for our sphere tracing algo, that goes in main's body.
    vec3 lig = ( vec3( 0, 0, 2 ) );
    // Here is where we "shoot" our ray from the mouse position. Our ray's origin.
    vec2 uvl = ( -iResolution.xy + 2.0 * iMouse.xy ) / iResolution.y;
    // This is our ray's direction.
    vec3 lir = normalize( vec3( uvl, -1 ) );
    // Here we get our SDF(dO) and our incrementing value(tO).
    float dO = 0.0, tO = ray( lig, lir, dO );
    // Now we update our vector with the direction and incrementing steps.
    lig += lir * tO;
    // We must normalize lights as they are just a direction, the magnitude screws the lighting calculations.
    lig = normalize( lig );

    vec3 ref = reflect( rd, n );

    float amb = 0.5 + 0.5 * n.y;
    float dif = max( 0.0, dot( n, lig ) );
    float spe = pow( clamp( dot( ref, lig ), 0.0, 1.0 ), 16.0 );

    vec3 col = vec3( 0 );

    col += 0.1 * amb;
    col += 0.2 * dif;
    col += spe;

    return col;

}

// Last step, here we create the origin and direction of our rays that we shoot against the SDF.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{

    //Normalize the coordinates.
    vec2 uv = ( -iResolution.xy + 2.0 * fragCoord.xy ) / iResolution.y;

    // This is our ray's origin. We must use the same values for our lig's origin.
    vec3 ro = vec3( 0, 0, 2 );
    // This is our ray's direction.
    vec3 rd = normalize( vec3( uv, -1 ) );

    // Our SDF(d) and our incrementing steps(t), we only need our SDF(d) to bail the shading calculations according to our epsilon(EPS).
    float t = 0.0, d = 0.0;
    t = ray( ro, rd, d );

    vec3 col = d < EPS ? shad( ro, rd, uv ) : vec3( 0 );

    fragColor = vec4( col, 1 );

}