added original picking back in as a fallback.

This commit is contained in:
James Fulop
2016-09-30 10:51:57 +02:00
committed by baldurk
parent bdfd44ebc9
commit 8851da66af
3 changed files with 152 additions and 43 deletions
+11 -4
View File
@@ -130,8 +130,9 @@ BINDING(0) uniform FontUBOData
}
INST_NAME(general);
#define MESH_TRIANGLE_LIST 0
#define MESH_TRIANGLE_STRIP 1
#define MESH_OTHER 0 // this covers points and lines, logic is the same
#define MESH_TRIANGLE_LIST 1
#define MESH_TRIANGLE_STRIP 2
BINDING(0) uniform MeshPickUBOData
{
vec3 rayPos;
@@ -140,8 +141,14 @@ BINDING(0) uniform MeshPickUBOData
vec3 rayDir;
uint numVerts;
int meshMode;//triangles, triangle strip, fan, etc...
vec3 padding;
vec2 coords;
vec2 viewport;
uint meshMode; // triangles, triangle strip, fan, etc...
uint unproject;
vec2 padding;
mat4 mvp;
}
INST_NAME(meshpick);
+54 -6
View File
@@ -74,11 +74,9 @@ bool TriangleRayIntersect(vec3 A, vec3 B, vec3 C,
return Result;
}
void main()
void trianglePath(uint threadID)
{
uvec3 tid = gl_GlobalInvocationID;
uint vertid = tid.x;
uint vertid = threadID;
// NOTE(james): when I turn on following early out the shader doesn't do anything.
// so I end up with a lot of duplicated work on smaller meshes
@@ -92,14 +90,16 @@ void main()
uint idx2 = 0;
switch (meshpick.meshMode)
{
case MESH_TRIANGLE_LIST:{
case MESH_TRIANGLE_LIST:
{
vertid *= 3;
idx0 = meshpick.use_indices != 0u ? ib.data[vertid ] : vertid;
idx1 = meshpick.use_indices != 0u ? ib.data[vertid+1] : vertid+1;
idx2 = meshpick.use_indices != 0u ? ib.data[vertid+2] : vertid+2;
break;
}
case MESH_TRIANGLE_STRIP:{
case MESH_TRIANGLE_STRIP:
{
idx0 = meshpick.use_indices != 0u ? ib.data[vertid ] : vertid;
idx1 = meshpick.use_indices != 0u ? ib.data[vertid+1] : vertid+1;
idx2 = meshpick.use_indices != 0u ? ib.data[vertid+2] : vertid+2;
@@ -137,4 +137,52 @@ void main()
pickresult.results[result_idx] = uvec4(vertid,
floatBitsToUint(hitPosition.x), floatBitsToUint(hitPosition.y), floatBitsToUint(hitPosition.z));
}
}
void defaultPath(uint threadID)
{
uint vertid = threadID;
if(vertid >= meshpick.numVerts)
return;
uint idx = meshpick.use_indices != 0u ? ib.data[vertid] : vertid;
vec4 pos = vb.data[idx];
#ifdef VULKAN
if(meshpick.unproject == 1u)
pos = vec4(pos.x, -pos.y, pos.z, pos.w);
#endif
vec4 wpos = meshpick.mvp * pos;
wpos.xyz /= wpos.www;
wpos.xy *= vec2(1.0f, -1.0f);
vec2 scr = (wpos.xy + 1.0f) * 0.5f * meshpick.viewport;
// close to target co-ords? add to list
float len = length(scr - meshpick.coords);
if(len < 35.0f)
{
uint result_idx = atomicAdd(pickresult.counter.x, 1u);
pickresult.results[result_idx] = uvec4(vertid, idx, floatBitsToUint(len), floatBitsToUint(wpos.z));
}
}
void main()
{
if (meshpick.meshMode == MESH_TRIANGLE_LIST ||
meshpick.meshMode == MESH_TRIANGLE_STRIP)
{
trianglePath(gl_GlobalInvocationID.x);
}
else
{
defaultPath(gl_GlobalInvocationID.x);
}
}
+87 -33
View File
@@ -1076,25 +1076,35 @@ uint32_t GLReplay::PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t
cdata->rayDir = rayDir;
cdata->use_indices = cfg.position.idxByteWidth ? 1U : 0U;
cdata->numVerts = cfg.position.numVerts;
bool isTriangleMesh = false;
switch(cfg.position.topo)
{
case eTopology_TriangleList:
{
cdata->meshMode = MESH_TRIANGLE_LIST;
isTriangleMesh = true;
break;
};
case eTopology_TriangleStrip:
{
cdata->meshMode = MESH_TRIANGLE_STRIP;
isTriangleMesh = true;
break;
};
default:
{
cdata->meshMode = -1;
RDCWARN("Mesh type unsupported by picking");
cdata->meshMode = MESH_OTHER;
RDCWARN("Mesh type defaulting to screenspace point picking");
};
}
// line/point data
cdata->unproject = cfg.position.unproject;
cdata->mvp = PickMVP;
cdata->coords = Vec2f((float)x, (float)y);
cdata->viewport = Vec2f(DebugData.outWidth, DebugData.outHeight);
gl.glUnmapBuffer(eGL_UNIFORM_BUFFER);
GLuint ib = 0;
@@ -1213,44 +1223,88 @@ uint32_t GLReplay::PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t
if(numResults > 0)
{
struct PickResult
if(isTriangleMesh)
{
uint32_t vertid;
vec3 intersectionPoint;
};
byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY);
mapped += sizeof(uint32_t) * 4;
PickResult *pickResults = (PickResult *)mapped;
PickResult *closest = pickResults;
// distance from raycast hit to nearest worldspace position of the mouse
float closestPickDistance = (closest->intersectionPoint - rayPos).Length();
// min with size of results buffer to protect against overflows
for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++)
{
// We need to keep the picking order consistent in the face
// of random buffer appends, when multiple vertices have the
// identical position (e.g. if UVs or normals are different).
//
// We could do something to try and disambiguate, but it's
// never going to be intuitive, it's just going to flicker
// confusingly.
float pickDistance = (pickResults[i].intersectionPoint - rayPos).Length();
if(pickDistance < closestPickDistance)
struct PickResult
{
closest = pickResults + i;
uint32_t vertid;
vec3 intersectionPoint;
};
byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY);
mapped += sizeof(uint32_t) * 4;
PickResult *pickResults = (PickResult *)mapped;
PickResult *closest = pickResults;
// distance from raycast hit to nearest worldspace position of the mouse
float closestPickDistance = (closest->intersectionPoint - rayPos).Length();
// min with size of results buffer to protect against overflows
for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++)
{
// We need to keep the picking order consistent in the face
// of random buffer appends, when multiple vertices have the
// identical position (e.g. if UVs or normals are different).
//
// We could do something to try and disambiguate, but it's
// never going to be intuitive, it's just going to flicker
// confusingly.
float pickDistance = (pickResults[i].intersectionPoint - rayPos).Length();
if(pickDistance < closestPickDistance)
{
closest = pickResults + i;
}
}
uint32_t ret = closest->vertid;
gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf);
return ret;
}
else
{
struct PickResult
{
uint32_t vertid;
uint32_t idx;
float len;
float depth;
};
uint32_t ret = closest->vertid;
byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY);
gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf);
mapped += sizeof(uint32_t) * 4;
return ret;
PickResult *pickResults = (PickResult *)mapped;
PickResult *closest = pickResults;
// min with size of results buffer to protect against overflows
for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++)
{
// We need to keep the picking order consistent in the face
// of random buffer appends, when multiple vertices have the
// identical position (e.g. if UVs or normals are different).
//
// We could do something to try and disambiguate, but it's
// never going to be intuitive, it's just going to flicker
// confusingly.
if(pickResults[i].len < closest->len ||
(pickResults[i].len == closest->len && pickResults[i].depth < closest->depth) ||
(pickResults[i].len == closest->len && pickResults[i].depth == closest->depth &&
pickResults[i].vertid < closest->vertid))
closest = pickResults + i;
}
uint32_t ret = closest->vertid;
gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf);
return ret;
}
}
return ~0U;