Ready to plug multiple selections javascript side

This commit is contained in:
Olivier Prat 2017-10-16 17:02:13 +02:00
parent 1b67223e0e
commit 70f892e67d
4 changed files with 112 additions and 71 deletions

View file

@ -16,23 +16,85 @@
<@include Outline_shared.slh@>
uniform outlineParamsBuffer {
OutlineParameters params;
OutlineParameters groups[GROUP_COUNT];
};
uniform sampler2D sceneDepthMap;
uniform sampler2D outlinedDepthMap;
uniform sampler2D outlinedIdMap;
uniform int enabledGroupsMask;
in vec2 varTexCoord0;
out vec4 outFragColor;
const float FAR_Z = 1.0;
const float ID_THRESHOLD = 1.f/64.f;
const float LINEAR_DEPTH_BIAS = 5e-3;
const float OPACITY_EPSILON = 5e-3;
<@func main(IS_FILLED)@>
int getGroupIndexFromColor(vec4 color) {
ivec4 id = ivec4(color * GROUP_ID_COLOR_COMPONENT_MAX) << ivec4(0, GROUP_ID_COLOR_COMPONENT_BITS, GROUP_ID_COLOR_COMPONENT_BITS*2, GROUP_ID_COLOR_COMPONENT_BITS*3);
return (id.r | id.g | id.b | id.a) - 1;
}
vec4 computeGroupOutline(int centerGroupId, float centerDepth, int groupId, vec2 texCoord) {
float intensity = 0.0;
if (centerGroupId==groupId && centerDepth < FAR_Z) {
// We're on the outlined object, thus no outline to do!
<@if IS_FILLED@>
OutlineParameters groupParams = groups[groupId];
// But we need to fill the interior
float sceneDepth = texture(sceneDepthMap, texCoord).x;
// Transform to linear depth for better precision
centerDepth = -evalZeyeFromZdb(centerDepth);
sceneDepth = -evalZeyeFromZdb(sceneDepth);
// Are we occluded?
intensity = (sceneDepth < (centerDepth-LINEAR_DEPTH_BIAS)) ? groupParams._fillOpacityOccluded : groupParams._fillOpacityUnoccluded;
return vec4(groupParams._color.rgb, intensity);
<@else@>
return vec4(0,0,0,0);
<@endif@>
} else {
OutlineParameters groupParams = groups[groupId];
float weight = 0.0;
vec2 deltaUv = groupParams._size / groupParams._blurKernelSize;
vec2 lineStartUv = texCoord - groupParams._size / 2.0;
vec2 uv;
int x;
int y;
for (y=0 ; y<groupParams._blurKernelSize ; y++) {
uv = lineStartUv;
lineStartUv.y += deltaUv.y;
if (uv.y>=0.0 && uv.y<=1.0) {
for (x=0 ; x<groupParams._blurKernelSize ; x++) {
if (uv.x>=0.0 && uv.x<=1.0)
{
vec4 outlinedIdColor = texture(outlinedIdMap, uv);
float outlinedDepth = texture(outlinedDepthMap, uv).x;
int outlinedId = getGroupIndexFromColor(outlinedIdColor);
intensity += (outlinedDepth<FAR_Z /*&& outlinedId!=groupId*/) ? 1.0 : 0.0;
weight += 1.f;
}
uv.x += deltaUv.x;
}
}
}
intensity /= weight;
if (intensity < OPACITY_EPSILON) {
return vec4(0,0,0,0);
}
intensity = min(1.0, intensity / groupParams._threshold) * groupParams._intensity;
return vec4(groupParams._color.rgb, intensity);
}
}
void main(void) {
// We offset by half a texel to be centered on the depth sample. If we don't do this
// the blur will have a different width between the left / right sides and top / bottom
@ -42,60 +104,25 @@ void main(void) {
vec4 outlinedIdColor = texture(outlinedIdMap, texCoord0);
float outlinedDepth = texture(outlinedDepthMap, texCoord0).x;
float intensity = 0.0;
int groupId = getGroupIndexFromColor(outlinedIdColor);
if (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) {
// We're not on the far plane so we are on the outlined object, thus no outline to do!
<@if IS_FILLED@>
// But we need to fill the interior
float sceneDepth = texture(sceneDepthMap, texCoord0).x;
// Transform to linear depth for better precision
outlinedDepth = -evalZeyeFromZdb(outlinedDepth);
sceneDepth = -evalZeyeFromZdb(sceneDepth);
// Are we occluded?
if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) {
intensity = params._fillOpacityOccluded;
} else {
intensity = params._fillOpacityUnoccluded;
vec4 finalColor = vec4(0,0,0,0);
int groupMask = 1;
for (int i=0 ; i<GROUP_COUNT ; i++) {
if ((enabledGroupsMask & groupMask)!=0) {
vec4 groupColor = computeGroupOutline(groupId, outlinedDepth, i, texCoord0);
finalColor.rgb = mix(finalColor.rgb, groupColor.rgb, groupColor.a);
// If first group we encounter then don't mix the color
finalColor.rgb = finalColor.a==0 ? groupColor.rgb : finalColor.rgb;
finalColor.a = min(1, finalColor.a+groupColor.a*(1-finalColor.a));
}
<@else@>
discard;
<@endif@>
} else {
float weight = 0.0;
vec2 deltaUv = params._size / params._blurKernelSize;
vec2 lineStartUv = texCoord0 - params._size / 2.0;
vec2 uv;
int x;
int y;
for (y=0 ; y<params._blurKernelSize ; y++) {
uv = lineStartUv;
lineStartUv.y += deltaUv.y;
if (uv.y>=0.0 && uv.y<=1.0) {
for (x=0 ; x<params._blurKernelSize ; x++) {
if (uv.x>=0.0 && uv.x<=1.0)
{
outlinedDepth = texture(outlinedDepthMap, uv).x;
outlinedIdColor = texture(outlinedIdMap, uv);
intensity += (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) ? 1.0 : 0.0;
weight += 1.f;
}
uv.x += deltaUv.x;
}
}
}
intensity /= weight;
if (intensity < OPACITY_EPSILON) {
discard;
}
intensity = min(1.0, intensity / params._threshold) * params._intensity;
groupMask <<= 1;
}
outFragColor = vec4(params._color.rgb, intensity);
if (finalColor.a < OPACITY_EPSILON) {
discard;
}
outFragColor = finalColor;
}
<@endfunc@>

View file

@ -94,6 +94,8 @@ glm::vec4 encodeIdToColor(unsigned int id) {
unsigned char id;
} groupId;
static_assert(GROUP_ID_COLOR_COMPONENT_BITS == 2, "Assuming two bits per component contrary to GLSL shader code. See Outline_shared.slh");
assert(id < 254);
groupId.id = id+1;
@ -101,7 +103,7 @@ glm::vec4 encodeIdToColor(unsigned int id) {
// Normalize. Since we put 2 bits into each color component, each component has a maximum
// value of 3.
idColor /= 3.f;
idColor /= GROUP_ID_COLOR_COMPONENT_MAX;
return idColor;
}
@ -250,15 +252,19 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
if (_hasConfigurationChanged)
{
auto& configuration = _configuration.edit();
configuration._color = _color;
configuration._intensity = _intensity;
configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded;
configuration._fillOpacityOccluded = _fillOpacityOccluded;
configuration._threshold = _threshold;
configuration._blurKernelSize = _blurKernelSize;
configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x;
configuration._size.y = _size;
configuration._idColor = encodeIdToColor(0);
for (auto groupId = 0; groupId < MAX_GROUP_COUNT; groupId++) {
auto& groupConfig = configuration._groups[groupId];
groupConfig._color = _color;
groupConfig._intensity = _intensity;
groupConfig._fillOpacityUnoccluded = _fillOpacityUnoccluded;
groupConfig._fillOpacityOccluded = _fillOpacityOccluded;
groupConfig._threshold = _threshold;
groupConfig._blurKernelSize = _blurKernelSize;
groupConfig._size.x = (_size * framebufferSize.y) / framebufferSize.x;
groupConfig._size.y = _size;
}
_hasConfigurationChanged = false;
}
@ -272,15 +278,15 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport));
batch.setPipeline(pipeline);
auto enabledGroupsLoc = pipeline->getProgram()->getUniforms().findLocation("enabledGroupsMask");
batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration);
batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer());
batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture);
batch.setResourceTexture(OUTLINED_ID_SLOT, outlinedIdTexture);
batch._glUniform1i(enabledGroupsLoc, 1);
batch.draw(gpu::TRIANGLE_STRIP, 4);
// Restore previous frame buffer
batch.setFramebuffer(destinationFrameBuffer);
});
}
}

View file

@ -94,9 +94,13 @@ signals:
};
class DrawOutline {
private:
#include "Outline_shared.slh"
public:
enum {
MAX_GROUP_COUNT = 7
MAX_GROUP_COUNT = GROUP_COUNT
};
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineRessourcesPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
@ -116,12 +120,14 @@ private:
OUTLINED_ID_SLOT,
OUTLINE_PARAMS_SLOT = 0,
FRAME_TRANSFORM_SLOT
FRAME_TRANSFORM_SLOT,
};
#include "Outline_shared.slh"
struct OutlineConfiguration {
OutlineParameters _groups[MAX_GROUP_COUNT];
};
using OutlineConfigurationBuffer = gpu::StructBuffer<OutlineParameters>;
using OutlineConfigurationBuffer = gpu::StructBuffer<OutlineConfiguration>;
static const gpu::PipelinePointer& getPipeline(bool isFilled);

View file

@ -9,6 +9,10 @@
# define VEC4 vec4
#endif
#define GROUP_COUNT 7
#define GROUP_ID_COLOR_COMPONENT_BITS 2
#define GROUP_ID_COLOR_COMPONENT_MAX 3
struct OutlineParameters
{
VEC3 _color;
@ -18,8 +22,6 @@ struct OutlineParameters
float _fillOpacityUnoccluded;
float _fillOpacityOccluded;
VEC4 _idColor;
float _threshold;
int _blurKernelSize;
float padding2;