void TexturedGlossyPaint::indirectBrdf(
            std::vector<Raycast>& raycasts,
            const RayHitReport& report,
            const std::shared_ptr<Material>& leavedMaterial,
            const std::shared_ptr<Material>& enteredMaterial,
            unsigned int outRayCountHint) const
    {
        size_t preSize, postSize;

        double mirrorRatio = computeReflexionRatio(
            leavedMaterial->refractiveIndex(),
            _varnishRefractiveIndex,
            report.incidentRay.direction,
            report.normal);


        // Varnish glossy reflection
        double glossiness = _defaultGlossiness;
        if(report.isTextured)
        {
            const glm::dvec3& texCoord = report.texCoord;
            glossiness = _sampler.sample(
                _glossMap, texCoord.s, texCoord.t).r;
            mirrorRatio *= glossiness;
        }

        preSize = raycasts.size();
        indirectGlossyReflection(raycasts, report, leavedMaterial, glossiness, outRayCountHint);
        postSize = raycasts.size();

        for(size_t i=preSize; i<postSize; ++i)
        {
            raycasts[i].color *= mirrorRatio;
        }


        // Pigment diffuse reflection
        preSize = raycasts.size();
        indirectDiffuseReflection(raycasts, report, leavedMaterial, outRayCountHint);
        postSize = raycasts.size();

        glm::dvec3 color = _defaultColor;
        if(report.isTextured)
        {
            const glm::dvec3& texCoord = report.texCoord;
            color = glm::dvec3(_sampler.sample(
                _texture, texCoord.x, texCoord.y));
        }

        color *= (1.0 - mirrorRatio);
        for(size_t i=preSize; i<postSize; ++i)
        {
            raycasts[i].color *= color;
        }
    }
    glm::dvec3 TexturedGlossyPaint::directBrdf(
            const RayHitReport& report,
            const glm::dvec3& outDirection,
            const std::shared_ptr<Material>& leavedMaterial,
            const std::shared_ptr<Material>& enteredMaterial) const
    {
        double mirrorRatio = computeReflexionRatio(
            leavedMaterial->refractiveIndex(),
            _varnishRefractiveIndex,
            report.incidentRay.direction,
            report.normal);

        double glossiness = _defaultGlossiness;
        if(report.isTextured)
        {
            const glm::dvec3& texCoord = report.texCoord;
            int i = texCoord.s * _glossMap.width();
            int j = texCoord.t * _glossMap.height();
            unsigned char* pixel = _glossMap.pixel(
                glm::clamp(i, 0,  _glossMap.width()-1),
                glm::clamp(j, 0, _glossMap.height()-1));

            // Not blended with default color
            glossiness = pixel[0] / 255.0;
            mirrorRatio *= glossiness;
        }

        glm::dvec3 color = _defaultColor;
        if(report.isTextured)
        {
            const glm::dvec3& texCoord = report.texCoord;
            color = glm::dvec3(_sampler.sample(
                _texture, texCoord.x, texCoord.y));
        }


        return glm::mix(
            color * directDiffuseReflection(report, outDirection),
            directGlossyReflection(report, outDirection, glossiness),
            mirrorRatio);
    }
예제 #3
0
glm::dvec4 StdCoating::indirectBrdf(
    std::vector<Raycast>& raycasts,
    const RayHitReport& report,
    const Raycast& incidentRay) const
{
    // Emission
    glm::dvec4 emission = glm::dvec4(0.0);

    // Report's shorthands
    const glm::dvec3& pos = report.position;
    const glm::dvec3& tex = report.texCoord;
    const glm::dvec3& wallNormal = report.normal;
    const glm::dvec3& reflectOrig = report.reflectionOrigin;
    const glm::dvec3& refractOrig = report.refractionOrigin;
    const Material& currMaterial = *report.currMaterial;
    const Material& nextMaterial = *report.nextMaterial;
    const glm::dvec3& incident = incidentRay.direction;

    // StdCoating properties
    double rough = roughness(tex);
    double pRIdx = paintRefractiveIndex(tex);
    double entropy = Raycast::getEntropy(rough);
    glm::dvec4 paintFrag = paintColor(tex);
    glm::dvec3 pColor = glm::dvec3(paintFrag);
    double pOpa = paintFrag.a;

    // Leaved material properties
    double lRIdx = currMaterial.refractiveIndex(pos);

    // Entered material properties
    double eOpa = nextMaterial.opacity(pos);
    double eCond = nextMaterial.conductivity(pos);
    double eRIdx = nextMaterial.refractiveIndex(pos);
    glm::dvec3 eColor = nextMaterial.color(pos);


    // Reflection
    glm::dvec3 reflectNormal = getMicrofacetNormal(
                                   wallNormal, incident, rough);

    // Fresnel reflection
    double paintReflectRatio = computeReflexionRatio(
                                   lRIdx, pRIdx, incident, reflectNormal);


    glm::dvec4 reflectSample(0.0);
    glm::dvec4 diffuseSample(0.0);
    glm::dvec4 refractSample(0.0);


    // Paint
    if(pOpa > 0.0)
    {
        double paintReflectWeight = pOpa * paintReflectRatio;
        reflectSample += glm::dvec4(paintReflectWeight);

        double paintDiffWeight = pOpa * (1 - paintReflectRatio);
        diffuseSample += glm::dvec4(pColor * paintDiffWeight, paintDiffWeight);
    }

    if(pOpa < 1.0)
    {
        // Metal reflection
        double metalWeight = (1 - pOpa) * eCond;
        if(metalWeight > 0.0)
        {
            reflectSample += glm::dvec4(eColor * metalWeight, metalWeight);
        }

        if(eCond < 1.0)
        {
            // Insulator reflection
            double insulProb = (1 - pOpa) * (1 - eCond);
            double matReflectRatio = computeReflexionRatio(
                                         lRIdx, eRIdx, incident, reflectNormal);

            double insulReflectWeight = insulProb * matReflectRatio;
            reflectSample += glm::dvec4(insulReflectWeight);

            // Fully opaque insulator
            if(eOpa >= 1.0)
            {
                double matDiffWeight = insulProb * (1 - matReflectRatio);
                diffuseSample += glm::dvec4(eColor * matDiffWeight, matDiffWeight);
            }
            // Refraction
            else
            {
                double paintRefract = pOpa * (1 - paintReflectRatio);
                double insulRefract = insulProb * (1 - matReflectRatio);
                double refractWeight = paintRefract + insulRefract;
                glm::dvec3 refractColor = glm::mix(color::white, pColor, pOpa);
                refractSample += glm::dvec4(refractColor * refractWeight, refractWeight);
            }
        }
    }


    // Refraction
    if(refractSample.w > 0.0)
    {
        glm::dvec3 refractDir = computeRefraction(
                                    lRIdx, eRIdx, incident, reflectNormal);
        if(glm::dot(refractDir, wallNormal) < 0.0)
        {
            raycasts.push_back(Raycast(
                                   entropy,
                                   refractSample,
                                   refractOrig,
                                   refractDir));
        }
        else
        {
            reflectSample += refractSample;
        }
    }

    // Diffuse
    if(diffuseSample.w > 0.0)
    {
        if(rough < 1.0)
        {
            glm::dvec3 diffuseNormal = getMicrofacetNormal(
                                           wallNormal, incident, 1.0); // Fully diffusive

            glm::dvec3 diffuseDir = glm::reflect(
                                        incident, diffuseNormal);

            raycasts.push_back(Raycast(
                                   Raycast::FULLY_DIFFUSE,
                                   diffuseSample,
                                   reflectOrig,
                                   diffuseDir));
        }
        else
        {
            reflectSample += diffuseSample;
        }
    }

    // Reflection
    if(reflectSample.w > 0.0)
    {
        glm::dvec3 reflectDir = glm::reflect(
                                    incident, reflectNormal);

        raycasts.push_back(Raycast(
                               entropy,
                               reflectSample,
                               reflectOrig,
                               reflectDir));
    }

    // No emission
    return emission;
}
예제 #4
0
glm::dvec4 StdCoating::directBrdf(
    const LightCast& lightCast,
    const RayHitReport& report,
    const Raycast& eyeRay) const
{
    glm::dvec4 sampleSum = glm::dvec4(0.0);

    // Report's shorthands
    const glm::dvec3& pos = report.position;
    const glm::dvec3& tex = report.texCoord;
    const glm::dvec3& incident = lightCast.raycast.direction;

    // StdCoating properties
    double rough = roughness(tex);
    double entropy = Raycast::getEntropy(rough);
    double pRIdx = paintRefractiveIndex(tex);
    glm::dvec4 paintFrag = paintColor(tex);
    double pOpa = paintFrag.a;

    // Material properties
    double lRIdx = report.currMaterial->refractiveIndex(pos);
    double eRIdx = report.nextMaterial->refractiveIndex(pos);
    double eCond = report.nextMaterial->conductivity(pos);
    double eOpa = report.nextMaterial->opacity(pos);

    // Geometry
    glm::dvec3 wallNormal = report.normal;
    glm::dvec3 outDir = -eyeRay.direction;
    double inDotNorm = -glm::dot(incident, wallNormal);
    double outDotNorm = glm::dot(outDir, wallNormal);
    bool isTransmission = outDotNorm < 0.0;

    // Microfacet
    glm::dvec3 halfVec = glm::normalize(outDir - incident);
    wallNormal = glm::normalize(glm::mix(wallNormal, halfVec, rough));

    // Fresnel reflection
    double paintReflectRatio = computeReflexionRatio(
                                   lRIdx, pRIdx, incident, wallNormal);
    double matReflectRatio = computeReflexionRatio(
                                 lRIdx, eRIdx, incident, wallNormal);


    if(!isTransmission)
    {
        glm::dvec3 eColor = report.nextMaterial->color(pos);
        double diffuseLightSize = lightCast.diffuseSize(
                                      lightCast, eyeRay, Raycast::FULLY_DIFFUSE);

        double totalDiffScatt = (eOpa >= 1.0 ? 1.0 : 0.0);

        double metalProb = (1 - pOpa) * eCond;
        double insulProb = (1 - pOpa) * (1 - eCond);
        double matDiffProb = insulProb * totalDiffScatt * (1 - matReflectRatio);
        double diffuseProb = pOpa * (1 - paintReflectRatio) + matDiffProb;
        double fresnelProb = pOpa * paintReflectRatio + insulProb * matReflectRatio;
        double reflectProb = fresnelProb + metalProb;

        double diffuseIntens = inDotNorm * diffuseLightSize;

        if(diffuseProb > 0.0)
        {
            double diffuseWeight = diffuseProb * diffuseIntens;

            glm::dvec3 pColor = glm::dvec3(paintFrag);
            glm::dvec3 diffuseColor = glm::mix(pColor, eColor, matDiffProb / diffuseProb);
            glm::dvec4 diffSample(diffuseColor * diffuseWeight, diffuseWeight);
            sampleSum += diffSample;
        }

        if(reflectProb > 0.0 && rough > 0.0)
        {
            double reflectLightSize = lightCast.diffuseSize(
                                          lightCast, eyeRay, entropy);

            glm::dvec3 reflection = glm::reflect(incident, wallNormal);
            double outDotReflect = glm::max(glm::dot(outDir, reflection), 0.0);
            double reflectPower = cellar::fast_pow(outDotReflect, 1 / rough);
            double reflectIntens = reflectPower * reflectLightSize;
            reflectIntens = glm::mix(reflectIntens, diffuseIntens, rough);
            double reflectWeight = reflectProb * reflectIntens;

            glm::dvec3 reflectColor = glm::mix(color::white, eColor, metalProb / reflectProb);
            glm::dvec4 reflectSample(reflectColor * reflectWeight, reflectWeight);
            sampleSum += reflectSample;
        }
    }
    else if(rough > 0.0 && eOpa < 1.0)
    {
        double insulProb = (1 - pOpa) * (1 - eCond);

        if(insulProb > 0.0)
        {
            double reflectLightSize = lightCast.diffuseSize(
                                          lightCast, eyeRay, entropy);

            glm::dvec3 refraction = computeRefraction(lRIdx, eRIdx, incident, wallNormal);
            double refractDotOut = glm::max(glm::dot(refraction, outDir), 0.0);
            double refractPower = cellar::fast_pow(refractDotOut, 1 / rough);
            refractPower = glm::mix(refractPower, inDotNorm, rough);

            double paintRefract = pOpa * (1 - paintReflectRatio);
            double insulRefract = insulProb * (1 - matReflectRatio);
            double refractProb = (paintRefract + insulRefract) * refractPower * reflectLightSize;

            glm::dvec4 refractSample(refractProb);
            sampleSum += refractSample;
        }
    }

    return sampleSum;
}