Files
renderdoc/renderdoc/data/glsl/mesh.comp
T
2017-01-06 12:13:31 +00:00

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