Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

Commit 8f7b61ab authored by Jakob Weiss's avatar Jakob Weiss

Fixed "Hard Shadows" Feature in simpleraycaster.cpp

Attempted colored shadows, but this does not give correct results yet.
parent f3fbef22
......@@ -67,6 +67,11 @@ uniform float _shadowIntensity;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
void blendUnder(inout vec4 result, in vec4 color) {
result.rgb = result.rgb + color.rgb * color.a * (1.0 - result.a);
result.a = result.a + (1.0 -result.a) * color.a;
}
/**
* Performs the raycasting and returns the final fragment color.
*/
......@@ -91,13 +96,43 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
#ifdef ENABLE_SHADOWING
float shadowSamplingStepSize = 2 * _samplingStepSize;
// simple and expensive implementation of hard shadows
if (color.a > 0.1) {
bool finished = false;
// compute direction from sample to light
vec3 L = normalize(_lightSource._position - textureToWorld(_volumeTextureParams, samplePosition)) * _samplingStepSize;
vec3 L = normalize(worldToTexture(_volumeTextureParams, _lightSource._position) - samplePosition) * shadowSamplingStepSize;
bool finished = false;
vec3 position = samplePosition + L;
jitterEntryPoint(position, L, _jitterStepSizeMultiplier);
int lightSamples = SHADOW_STEPS;
#ifdef ENABLE_COLORED_SHADOWING
// NOTE: This is probably still somehow wrong..
vec4 shadowFactor = vec4(0.0);
// traverse ray from sample to light
while (! finished) {
// grab intensity and TF opacity
intensity = texture(_volume, position).r;
vec4 shadowSample = lookupTF(_transferFunction, _transferFunctionParams, intensity);
//shadowSample.rgb = shadowSample.rgb;
shadowSample.a = 1.0 - pow(1.0 - shadowSample.a, shadowSamplingStepSize * SAMPLING_BASE_INTERVAL_RCP * _shadowIntensity * 10);
//shadowSample.a *= _shadowIntensity;
blendUnder(shadowFactor, shadowSample);
position += L;
finished = /*(shadowFactor.a > 0.95)
||*/ --lightSamples < 0
|| any(lessThan(position, vec3(0.0, 0.0, 0.0)))
|| any(greaterThan(position, vec3(1.0, 1.0, 1.0)));
}
blendUnder(shadowFactor, vec4(_lightSource._diffuseColor, 1.f));
//blendUnder(shadowFactor, vec4(1.f, 1.f, 1.f, 1.f));
// apply shadow to color
color.rgb *= shadowFactor.rgb;
#else
float shadowFactor = 0.0;
// traverse ray from sample to light
......@@ -107,14 +142,16 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
shadowFactor += lookupTF(_transferFunction, _transferFunctionParams, intensity).a;
position += L;
finished = (shadowFactor > 0.95)
finished = //(shadowFactor > 0.95)
--lightSamples < 0
|| any(lessThan(position, vec3(0.0, 0.0, 0.0)))
|| any(greaterThan(position, vec3(1.0, 1.0, 1.0)));
}
// apply shadow to color
color.rgb *= (1.0 - shadowFactor * _shadowIntensity);
color.rgb *= exp(- shadowFactor * shadowSamplingStepSize * _shadowIntensity * 1000.0);
#endif // ENABLE_COLORED_SHADOWING
}
#endif
#endif // ENABLE_SHADOWS
// perform compositing
if (color.a > 0.0) {
......@@ -122,13 +159,13 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
// compute gradient (needed for shading and normals)
vec3 gradient = computeGradient(_volume, _volumeTextureParams, samplePosition);
vec4 worldPos = _volumeTextureParams._textureToWorldMatrix * vec4(samplePosition, 1.0); // calling textureToWorld here crashes Intel HD driver and nVidia driver in debug mode, hence, let's calc it manually...
color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, _lightSource, _cameraPosition, gradient, color.rgb);
vec3 normal = -normalize(_volumeTextureParams._textureToWorldMatrixInvTransp * vec4(gradient, 0.0)).xyz; // negated because gradient is along increasing intensity but we want a surface normal
color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, _lightSource, _cameraPosition, normal, color.rgb);
#endif
// accomodate for variable sampling rates
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
result.rgb = result.rgb + color.rgb * color.a * (1.0 - result.a);
result.a = result.a + (1.0 -result.a) * color.a;
blendUnder(result, color);
}
// save first hit ray parameter for depth value calculation
......
......@@ -26,10 +26,13 @@
#include "core/tools/quadrenderer.h"
#include "core/datastructures/lightsourcedata.h"
#include "core/datastructures/cameradata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#include "core/datastructures/facegeometry.h"
#include "core/pipeline/processordecoratorgradient.h"
#include <tbb/tbb.h>
namespace campvis {
......@@ -38,16 +41,22 @@ namespace campvis {
SimpleRaycaster::SimpleRaycaster(IVec2Property* viewportSizeProp)
: RaycastingProcessor(viewportSizeProp, "modules/vis/glsl/simpleraycaster.frag", true)
, p_enableShading("EnableShading", "Enable Shading", true)
, p_shadowSteps("ShadowSteps", "Shadow Steps (0 to turn shadowing off)", 0, 0, 150)
, p_enableColoredShadowing("EnableColoredShadowing", "Enable Colored Shadows (broken)", false)
, p_shadowIntensity("ShadowIntensity", "Shadow Intensity", .15f, .0f, 1.f)
, p_lightId("LightId", "Input Light Source", "lightsource", DataNameProperty::READ)
, p_enableShadowing("EnableShadowing", "Enable Hard Shadows (Expensive!)", false)
, p_shadowIntensity("ShadowIntensity", "Shadow Intensity", .5f, .0f, 1.f)
, p_quadGeometry("QuadGeometry", "Quad Geometry", "", DataNameProperty::READ)
{
addDecorator(new ProcessorDecoratorGradient());
addProperty(p_enableShading, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_lightId);
addProperty(p_enableShadowing, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_shadowSteps, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_enableColoredShadowing, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_shadowIntensity);
addProperty(p_lightId);
addProperty(p_quadGeometry);
p_shadowIntensity.setVisible(false);
decoratePropertyCollection(this);
......@@ -67,6 +76,8 @@ namespace campvis {
void SimpleRaycaster::processImpl(DataContainer& data, ImageRepresentationGL::ScopedRepresentation& image) {
ScopedTypedData<LightSourceData> light(data, p_lightId.getValue());
ScopedTypedData<RenderData, true> outputImage(data, p_targetImageID.getValue());
ScopedTypedData<FaceGeometry> quadGeometry(data, p_quadGeometry.getValue(), true);
ScopedTypedData<CameraData> cam(data, p_camera.getValue());
if (p_enableShading.getValue() == false || light != nullptr) {
FramebufferActivationGuard fag(this);
......@@ -79,16 +90,24 @@ namespace campvis {
static const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, buffers);
if (p_enableShading.getValue() && light != nullptr) {
if ((p_enableShading.getValue() || p_shadowSteps.getValue() > 0) && light != nullptr) {
light->bind(_shader, "_lightSource");
}
if (p_enableShadowing.getValue()) {
if (p_shadowSteps.getValue() > 0) {
_shader->setUniform("_shadowIntensity", p_shadowIntensity.getValue());
}
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
if (quadGeometry && cam) {
_shader->setUniform("_viewMatrix", cam->getCamera().getViewMatrix());
_shader->setUniform("_projectionMatrix", cam->getCamera().getProjectionMatrix());
quadGeometry->render(GL_TRIANGLE_FAN);
}
else {
QuadRdr.renderQuad();
}
// restore state
glDrawBuffers(1, buffers);
......@@ -107,15 +126,20 @@ namespace campvis {
std::string toReturn = RaycastingProcessor::generateHeader();
if (p_enableShading.getValue())
toReturn += "#define ENABLE_SHADING\n";
if (p_enableShadowing.getValue())
if (p_shadowSteps.getValue() > 0) {
toReturn += "#define ENABLE_SHADOWING\n";
toReturn += "#define SHADOW_STEPS " + std::to_string(p_shadowSteps.getValue()) + "\n";
}
if (p_enableColoredShadowing.getValue())
toReturn += "#define ENABLE_COLORED_SHADOWING\n";
return toReturn;
}
void SimpleRaycaster::updateProperties(DataContainer& dataContainer) {
RaycastingProcessor::updateProperties(dataContainer);
p_lightId.setVisible(p_enableShading.getValue());
p_shadowIntensity.setVisible(p_enableShadowing.getValue());
p_lightId.setVisible(p_enableShading.getValue() || p_shadowSteps.getValue() > 0);
p_shadowIntensity.setVisible(p_shadowSteps.getValue() > 0);
p_enableColoredShadowing.setVisible(p_shadowSteps.getValue() > 0);
}
}
......@@ -73,10 +73,14 @@ namespace campvis {
virtual void deinit();
BoolProperty p_enableShading; ///< Flag whether to enable shading
DataNameProperty p_lightId; ///< Name/ID for the LightSource to use
IntProperty p_shadowSteps; ///< Number of shadow steps. Zero to turn shadows off
BoolProperty p_enableColoredShadowing; ///< Flag to indicate whether to compute colored shadows
BoolProperty p_enableShadowing; ///< Flag whether to enable shadowing
FloatProperty p_shadowIntensity; ///< Shadow intensity
DataNameProperty p_lightId; ///< Name/ID for the LightSource to use
DataNameProperty p_quadGeometry;
protected:
/// \see AbstractProcessor::updateProperties()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment