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