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

Fixed "Hard Shadows" Feature in simpleraycaster.cpp

Attempted colored shadows, but this does not give correct results yet.
parent f3fbef22
Loading
Loading
Loading
Loading
+45 −8
Original line number Diff line number Diff line
@@ -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
+34 −10
Original line number Diff line number Diff line
@@ -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);

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

}
+6 −2
Original line number Diff line number Diff line
@@ -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()