Форвард + - расчет усеченного конуса - PullRequest
0 голосов
/ 04 апреля 2019

Я начал реализацию forward + и застрял в расчете усеченности для конкретной группы в вычислительном шейдере. Код для расчета, связанного с плоскостью, преобразования точки из проекции в область просмотра и освещения контрольной точки с плоскостями:

//From AMD DX11 sample.
//this creates the standard Hessian-normal-form plane equation from three points, 
//except it is simplified for the case where the first point is the origin
vec3 createPlaneEqn(vec3 tmp_b, vec3 tmp_c) 
{
  //normalize(cross( b-a, c-a )), except we know "a" is the origin
  //also, typically there would be a fourth term of the plane equation, 
  //-(n dot a), except we know "a" is the origin
  return normalize(cross(tmp_b, tmp_c));
}

//Convert a point from post-projection space into view space
vec4 convertProjToView(vec4 tmp_p, mat4 tmp_invProjMatrix) 
{
    tmp_p = tmp_invProjMatrix * tmp_p;
    tmp_p /= tmp_p.w;
    return tmp_p;
}

//Point-plane distance, simplified for the case where 
//the plane passes through the origin
float getSignedDistanceFromPlane(vec3 p, vec3 eqn) 
{
  // dot(eqn.xyz,p) + eqn.w, , except we know eqn.w is zero 
  // (see CreatePlaneEquation above)
  return dot(eqn, p);
}

//Where c is center of point light in view space, r is point light radius
    bool testFrustumSides(vec3 c, float r, vec3 plane0, vec3 plane1, vec3 plane2, vec3 plane3) 
    {
        bool intersecting = getSignedDistanceFromPlane(c, plane0) < r;
        bool intersecting1 = getSignedDistanceFromPlane(c, plane1) < r;
        bool intersecting2 = getSignedDistanceFromPlane(c, plane2) < r;
        bool intersecting3 = getSignedDistanceFromPlane(c, plane3) < r;

        return (intersecting && intersecting1 && 
                intersecting2 && intersecting3);
    }

А вот мой код, в котором я вычисляю усеченную фигуру для конкретной группы:

if(gl_LocalInvocationIndex == 0) 
    {
        o_lightCount = 0;
        s_groupStartIndex = (gl_WorkGroupID.x + gl_WorkGroupID.y * workingGroups.x) * MAX_VIS_LIGHTSX;

        vec2 tmp_screenSpace[4];
        //Top left
        tmp_screenSpace[0] = vec2(TILE_SIZE * gl_WorkGroupID.x, TILE_SIZE * gl_WorkGroupID.y);
        //Bottom left
        tmp_screenSpace[1] = vec2(TILE_SIZE * gl_WorkGroupID.x, TILE_SIZE * (gl_WorkGroupID.y + 1));
        //Bottom right
        tmp_screenSpace[2] = vec2(TILE_SIZE * (gl_WorkGroupID.x + 1), TILE_SIZE * (gl_WorkGroupID.y + 1));
        //Top right
        tmp_screenSpace[3] = vec2(TILE_SIZE * (gl_WorkGroupID.x + 1), TILE_SIZE * gl_WorkGroupID.y);

        //Clip space frustum
        vec2 tmp_clipSpace[4];
        for(int i = 0; i < 4; i++)
        {
            tmp_clipSpace[i] = vec2((tmp_screenSpace[i].x / u_screenSize.x) * 2.0f - 1.0f,
                                    ((tmp_screenSpace[i].y) / u_screenSize.y) * 2.0f - 1.0f);
        }

        //View space frustum
        vec4 tmp_viewSpace[4];
        for(int i = 0; i < 4; i++)
        {
            tmp_viewSpace[i] = convertProjToView(vec4(tmp_clipSpace[i], 1.0, 1.0), u_invProjMatrix);
        }

        s_groupFrustum[0] = createPlaneEqn(tmp_viewSpace[3].xyz, tmp_viewSpace[0].xyz);
        s_groupFrustum[1] = createPlaneEqn(tmp_viewSpace[0].xyz, tmp_viewSpace[1].xyz);
        s_groupFrustum[2] = createPlaneEqn(tmp_viewSpace[1].xyz, tmp_viewSpace[2].xyz);
        s_groupFrustum[3] = createPlaneEqn(tmp_viewSpace[2].xyz, tmp_viewSpace[3].xyz);
    }

Я проверил все самолеты, и, кажется, только первый из них работает. Остальные самолеты покрывают только половину экрана. Любая помощь будет оценена :) 1007 *

...