mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-12 10:37:08 +00:00
227 lines
5.5 KiB
Plaintext
227 lines
5.5 KiB
Plaintext
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2016-2017 Baldur Karlsson
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
layout(binding = 1, std140) readonly buffer vertex_data
|
|
{
|
|
vec4 data[];
|
|
} vb;
|
|
|
|
layout(binding = 2, std430) readonly buffer index_data
|
|
{
|
|
uint data[];
|
|
} ib;
|
|
|
|
layout(binding = 3, std140) buffer pickresult_buffer
|
|
{
|
|
uvec4 counter;
|
|
uvec4 results[];
|
|
} pickresult;
|
|
|
|
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
|
|
|
|
bool TriangleRayIntersect(vec3 A, vec3 B, vec3 C,
|
|
vec3 RayPosition, vec3 RayDirection, out vec3 HitPosition)
|
|
{
|
|
bool Result = false;
|
|
|
|
vec3 v0v1 = B - A;
|
|
vec3 v0v2 = C - A;
|
|
vec3 pvec = cross(RayDirection, v0v2);
|
|
float det = dot(v0v1, pvec);
|
|
|
|
// if the determinant is negative the triangle is backfacing, but we still take those!
|
|
// if the determinant is close to 0, the ray misses the triangle
|
|
if (abs(det) > 0)
|
|
{
|
|
float invDet = 1 / det;
|
|
|
|
vec3 tvec = RayPosition - A;
|
|
vec3 qvec = cross(tvec, v0v1);
|
|
float u = dot(tvec, pvec) * invDet;
|
|
float v = dot(RayDirection, qvec) * invDet;
|
|
|
|
if (u >= 0 && u <= 1 &&
|
|
v >= 0 && u + v <= 1)
|
|
{
|
|
float t = dot(v0v2, qvec) * invDet;
|
|
if (t > 0)
|
|
{
|
|
HitPosition = RayPosition + (RayDirection * t);
|
|
Result = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
void trianglePath(uint threadID)
|
|
{
|
|
uint vertid = uint(mod(float(threadID), float(meshpick.numVerts)));
|
|
|
|
uint vertid0 = 0;
|
|
uint vertid1 = 0;
|
|
uint vertid2 = 0;
|
|
switch (meshpick.meshMode)
|
|
{
|
|
case MESH_TRIANGLE_LIST:
|
|
{
|
|
vertid *= 3;
|
|
vertid0 = vertid;
|
|
vertid1 = vertid+1;
|
|
vertid2 = vertid+2;
|
|
break;
|
|
}
|
|
case MESH_TRIANGLE_STRIP:
|
|
{
|
|
vertid0 = vertid;
|
|
vertid1 = vertid+1;
|
|
vertid2 = vertid+2;
|
|
break;
|
|
}
|
|
case MESH_TRIANGLE_FAN:
|
|
{
|
|
vertid0 = 0;
|
|
vertid1 = vertid+1;
|
|
vertid2 = vertid+2;
|
|
break;
|
|
}
|
|
case MESH_TRIANGLE_LIST_ADJ:
|
|
{
|
|
vertid *= 6;
|
|
vertid0 = vertid;
|
|
vertid1 = vertid+2;
|
|
vertid2 = vertid+4;
|
|
break;
|
|
}
|
|
case MESH_TRIANGLE_STRIP_ADJ:
|
|
{
|
|
vertid *= 2;
|
|
vertid0 = vertid;
|
|
vertid1 = vertid+2;
|
|
vertid2 = vertid+4;
|
|
break;
|
|
}
|
|
}
|
|
|
|
vec4 pos0 = meshpick.use_indices != 0u ? vb.data[ib.data[vertid0]] : vb.data[vertid0];
|
|
vec4 pos1 = meshpick.use_indices != 0u ? vb.data[ib.data[vertid1]] : vb.data[vertid1];
|
|
vec4 pos2 = meshpick.use_indices != 0u ? vb.data[ib.data[vertid2]] : vb.data[vertid2];
|
|
|
|
#ifdef VULKAN
|
|
if(meshpick.unproject == 1u)
|
|
{
|
|
pos0 = vec4(pos0.x, -pos0.y, pos0.z, pos0.w);
|
|
pos1 = vec4(pos1.x, -pos1.y, pos1.z, pos1.w);
|
|
pos2 = vec4(pos2.x, -pos2.y, pos2.z, pos2.w);
|
|
}
|
|
#endif
|
|
|
|
vec3 hitPosition;
|
|
bool hit;
|
|
if (meshpick.unproject == 1u)
|
|
{
|
|
hit = TriangleRayIntersect(pos0.xyz / pos0.w, pos1.xyz / pos1.w, pos2.xyz / pos2.w,
|
|
meshpick.rayPos, meshpick.rayDir,
|
|
/*out*/ hitPosition);
|
|
}
|
|
else
|
|
{
|
|
hit = TriangleRayIntersect(pos0.xyz, pos1.xyz, pos2.xyz,
|
|
meshpick.rayPos, meshpick.rayDir,
|
|
/*out*/ hitPosition);
|
|
}
|
|
|
|
// ray hit a triangle, so return the vertex that was closest
|
|
// to the triangle/ray intersection point
|
|
if (hit)
|
|
{
|
|
float dist0 = distance(pos0.xyz/pos0.w, hitPosition);
|
|
float dist1 = distance(pos1.xyz/pos1.w, hitPosition);
|
|
float dist2 = distance(pos2.xyz/pos2.w, hitPosition);
|
|
|
|
uint result_idx = atomicAdd(pickresult.counter.x, 1u);
|
|
|
|
uint meshVert = vertid0;
|
|
if (dist1 < dist0 && dist1 < dist2)
|
|
{
|
|
meshVert = vertid1;
|
|
}
|
|
else if (dist2 < dist0 && dist2 < dist1)
|
|
{
|
|
meshVert = vertid2;
|
|
}
|
|
pickresult.results[result_idx] = uvec4(meshVert,
|
|
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;
|
|
|
|
if(meshpick.unproject == 1u)
|
|
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_OTHER)
|
|
{
|
|
defaultPath(gl_GlobalInvocationID.x);
|
|
}
|
|
else
|
|
{
|
|
trianglePath(gl_GlobalInvocationID.x);
|
|
}
|
|
}
|