我已经开始实现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);
}
我检查了所有飞机,似乎只有第一个飞机在工作。其余飞机仅覆盖屏幕的一半。任何帮助将不胜感激:)