Реализация RayPicking во фрагментном шейдере - PullRequest
0 голосов
/ 29 января 2019

У меня проблемы с реализацией RayPicking во Fragment-Shader, я понимаю, что должен начинать с координат мыши, но я не уверен, на что умножить исходную точку.

Я попытался создать 3 компонентаvector, с x и y в качестве координат моей мыши, разделенных на мое разрешение, а в z я попытался использовать p (для точки в пространстве, рассчитанной как rayOrigin + rayDirection * t), но безуспешно.Вот Shadertoy , который пробует то, что я ищу.

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 голосов
/ 29 января 2019

Это правильный код:

// 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 );

}
...