134 lines
3.4 KiB
C++
134 lines
3.4 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#ifndef K4APOINTCLOUDSHADERS_H
|
|
#define K4APOINTCLOUDSHADERS_H
|
|
|
|
// clang-format off
|
|
|
|
constexpr char const PointCloudFragmentShader[] =
|
|
R"(
|
|
#version 430
|
|
|
|
in vec4 vertexColor;
|
|
out vec4 fragmentColor;
|
|
|
|
uniform bool enableShading;
|
|
|
|
void main()
|
|
{
|
|
if (vertexColor.a == 0.0f)
|
|
{
|
|
discard;
|
|
}
|
|
|
|
fragmentColor = vertexColor;
|
|
}
|
|
)";
|
|
|
|
constexpr char const PointCloudVertexShader[] =
|
|
R"(
|
|
#version 430
|
|
layout(location = 0) in vec4 inColor;
|
|
|
|
out vec4 vertexColor;
|
|
|
|
uniform mat4 view;
|
|
uniform mat4 projection;
|
|
layout(rgba32f) readonly uniform image2D pointCloudTexture;
|
|
uniform bool enableShading;
|
|
|
|
bool GetPoint3d(in vec2 pointCloudSize, in ivec2 point2d, out vec3 point3d)
|
|
{
|
|
if (point2d.x < 0 || point2d.x >= pointCloudSize.x ||
|
|
point2d.y < 0 || point3d.y >= pointCloudSize.y)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
point3d = imageLoad(pointCloudTexture, point2d).xyz;
|
|
if (point3d.z <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
ivec2 pointCloudSize = imageSize(pointCloudTexture);
|
|
ivec2 currentDepthPixelCoordinates = ivec2(gl_VertexID % pointCloudSize.x, gl_VertexID / pointCloudSize.x);
|
|
vec3 vertexPosition = imageLoad(pointCloudTexture, currentDepthPixelCoordinates).xyz;
|
|
|
|
gl_Position = projection * view * vec4(vertexPosition, 1);
|
|
|
|
vertexColor = inColor;
|
|
|
|
// Pass along the 'invalid pixel' flag as the alpha channel
|
|
//
|
|
if (vertexPosition.z == 0.0f)
|
|
{
|
|
vertexColor.a = 0.0f;
|
|
}
|
|
|
|
if (enableShading)
|
|
{
|
|
// Compute the location of the closest neighbor pixel to compute lighting
|
|
//
|
|
vec3 closestNeighbor = vertexPosition;
|
|
|
|
// If no neighbors have data, default to 1 meter behind point.
|
|
//
|
|
closestNeighbor.z += 1.0f;
|
|
|
|
vec3 outPoint;
|
|
if (GetPoint3d(pointCloudSize, currentDepthPixelCoordinates - ivec2(1, 0), outPoint))
|
|
{
|
|
if (closestNeighbor.z > outPoint.z)
|
|
{
|
|
closestNeighbor = outPoint;
|
|
}
|
|
}
|
|
if (GetPoint3d(pointCloudSize, currentDepthPixelCoordinates + ivec2(1, 0), outPoint))
|
|
{
|
|
if (closestNeighbor.z > outPoint.z)
|
|
{
|
|
closestNeighbor = outPoint;
|
|
}
|
|
}
|
|
if (GetPoint3d(pointCloudSize, currentDepthPixelCoordinates - ivec2(0, 1), outPoint))
|
|
{
|
|
if (closestNeighbor.z > outPoint.z)
|
|
{
|
|
closestNeighbor = outPoint;
|
|
}
|
|
}
|
|
if (GetPoint3d(pointCloudSize, currentDepthPixelCoordinates + ivec2(0, 1), outPoint))
|
|
{
|
|
if (closestNeighbor.z > outPoint.z)
|
|
{
|
|
closestNeighbor = outPoint;
|
|
}
|
|
}
|
|
|
|
vec3 lightPosition = vec3(0, 0, 0);
|
|
float occlusion = length(vertexPosition - closestNeighbor) * 20.0f;
|
|
float diffuse = 1.0f - clamp(occlusion, 0.0f, 0.6f);
|
|
|
|
float distance = length(lightPosition - vertexPosition);
|
|
|
|
// Attenuation term for light source that covers distance up to 50 meters
|
|
// http://wiki.ogre3d.org/tiki-index.php?page=-Point+Light+Attenuation
|
|
//
|
|
float attenuation = 1.0 / (1.0 + 0.09 * distance + 0.032 * distance * distance);
|
|
|
|
vertexColor = vec4(attenuation * diffuse * vertexColor.rgb, vertexColor.a);
|
|
}
|
|
}
|
|
)";
|
|
|
|
// clang-format on
|
|
|
|
#endif
|