Example #1
0
std::string
SplatTerrainEffect::generateSamplingFunction()
{
    std::stringstream buf;
    buf <<
        "#version " GLSL_VERSION_STR "\n"
        "#extension GL_EXT_texture_array : enable\n"
        GLSL_DEFAULT_PRECISION_FLOAT "\n"
        "uniform sampler2DArray " << SPLAT_SAMPLER << ";\n"
        "float " NOISE_FUNC "(in vec2);\n"
        "vec4 " SPLAT_FUNC "(in float v, in vec2 splat_tc) \n"
        "{\n"
        "    float i = -1.0;\n";

    unsigned count = 0;
    const SplatCoverageLegend::Predicates& preds = _legend->getPredicates();
    for(SplatCoverageLegend::Predicates::const_iterator p = preds.begin(); p != preds.end(); ++p, ++count)
    {
        if ( p->get()->_exactValue.isSet() )
        {
            if ( count > 0 )
                buf << "    else ";
            else
                buf << "    ";

            //buf << "if (v <= float(" << p->get()->_exactValue.get() << ")) i="
            buf << "if (abs(v-float(" << p->get()->_exactValue.get() << "))<0.01) i = "
                << "float(" << _splatTexIndex[p->get()->_mappedClassName.get()] << ");\n";
        }
    }

    buf << "    vec4 texel = texture2DArray(" SPLAT_SAMPLER ", vec3(splat_tc, max(i,0.0)));\n"
        << "    if ( i < 0.0 ) texel.a = 0.0; \n" //texel = vec4(1,0,0,1); \n"
        << "    return texel; \n"
        << "}\n";

    return buf.str();
}
Example #2
0
bool
SplatTerrainEffect::createSplattingSamplingFunction(const Coverage*  coverage,
                                                    SplatTextureDef& textureDef) const
{
    if ( !coverage || !coverage->getLegend() )
    {
        OE_WARN << LC << "Sampling function: illegal state (no coverage or legend); \n";
        return false;
    }

    if ( !textureDef._texture.valid() )
    {
        OE_WARN << LC << "Internal: texture is not set; cannot create a sampling function\n";
        return false;
    }

    std::stringstream
        weightBuf,
        primaryBuf,
        detailBuf,
        brightnessBuf,
        contrastBuf,
        thresholdBuf,
        slopeBuf;

    unsigned
        primaryCount    = 0,
        detailCount     = 0,
        brightnessCount = 0,
        contrastCount   = 0,
        thresholdCount  = 0,
        slopeCount      = 0;

    const SplatCoverageLegend::Predicates& preds = coverage->getLegend()->getPredicates();
    for(SplatCoverageLegend::Predicates::const_iterator p = preds.begin(); p != preds.end(); ++p)
    {
        const CoverageValuePredicate* pred = p->get();

        if ( pred->_exactValue.isSet() )
        {
            // Look up by class name:
            const std::string& className = pred->_mappedClassName.get();
            const SplatLUT::const_iterator i = textureDef._splatLUT.find(className);
            if ( i != textureDef._splatLUT.end() )
            {
                // found it; loop over the range selectors:
                int selectorCount = 0;
                const SplatSelectorVector& selectors = i->second;

                OE_DEBUG << LC << "Class " << className << " has " << selectors.size() << " selectors.\n";

                for(SplatSelectorVector::const_iterator selector = selectors.begin();
                    selector != selectors.end();
                    ++selector)
                {
                    const std::string&    expression = selector->first;
                    const SplatRangeData& rangeData  = selector->second;

                    std::string val = pred->_exactValue.get();

                    weightBuf
                        << IND "float w" << val
                        << " = (1.0-clamp(abs(value-" << val << ".0),0.0,1.0));\n";

                    // Primary texture index:
                    if ( primaryCount == 0 )
                        primaryBuf << IND "primary += ";
                    else
                        primaryBuf << " + ";

                    // the "+1" is because "primary" starts out at -1.
                    primaryBuf << "w"<<val << "*" << (rangeData._textureIndex + 1) << ".0";
                    primaryCount++;

                    // Detail texture index:
                    if ( rangeData._detail.isSet() )
                    {
                        if ( detailCount == 0 )
                            detailBuf << IND "detail += ";
                        else
                            detailBuf << " + ";
                        // the "+1" is because "detail" starts out at -1.
                        detailBuf << "w"<<val << "*" << (rangeData._detail->_textureIndex + 1) << ".0";
                        detailCount++;

                        if ( rangeData._detail->_brightness.isSet() )
                        {
                            if ( brightnessCount == 0 )
                                brightnessBuf << IND "brightness += ";
                            else
                                brightnessBuf << " + ";
                            brightnessBuf << "w"<<val << "*" << rangeData._detail->_brightness.get();
                            brightnessCount++;
                        }

                        if ( rangeData._detail->_contrast.isSet() )
                        {
                            if ( contrastCount == 0 )
                                contrastBuf << IND "contrast += ";
                            else
                                contrastBuf << " + ";
                            contrastBuf << "w"<<val << "*" << rangeData._detail->_contrast.get();
                            contrastCount++;
                        }

                        if ( rangeData._detail->_threshold.isSet() )
                        {
                            if ( thresholdCount == 0 )
                                thresholdBuf << IND "threshold += ";
                            else
                                thresholdBuf << " + ";
                            thresholdBuf << "w"<<val << "*" << rangeData._detail->_threshold.get();
                            thresholdCount++;
                        }

                        if ( rangeData._detail->_slope.isSet() )
                        {
                            if ( slopeCount == 0 )
                                slopeBuf << IND "slope += ";
                            else
                                slopeBuf << " + ";
                            slopeBuf << "w"<<val << "*" << rangeData._detail->_slope.get();
                            slopeCount++;
                        }
                    }                    
                }
            }
        }
    }

    if ( primaryCount > 0 )
        primaryBuf << ";\n";

    if ( detailCount > 0 )
        detailBuf << ";\n";

    if ( brightnessCount > 0 )
        brightnessBuf << ";\n";

    if ( contrastCount > 0 )
        contrastBuf << ";\n";

    if ( thresholdCount > 0 )
        thresholdBuf << ";\n";

    if ( slopeCount > 0 )
        slopeBuf << ";\n";

    SplattingShaders splatting;
    std::string code = ShaderLoader::load(
        splatting.FragGetRenderInfo,
        splatting);

    std::string codeToInject = Stringify()
        << IND
        << weightBuf.str()
        << primaryBuf.str()
        << detailBuf.str()
        << brightnessBuf.str()
        << contrastBuf.str()
        << thresholdBuf.str()
        << slopeBuf.str();

    osgEarth::replaceIn(code, "$COVERAGE_SAMPLING_FUNCTION", codeToInject);

    textureDef._samplingFunction = code;

    OE_DEBUG << LC << "Sampling function = \n" << code << "\n\n";

    return true;
}
Example #3
0
osg::Texture*
Surface::createLUTBuffer(const Coverage* coverage) const
{
    typedef LOD CoverageClass[NUM_LODS];

    typedef CoverageClass LUT[NUM_CLASSES];

    LUT lut;

    // Build the LUT!
    const SplatCoverageLegend::Predicates& preds = coverage->getLegend()->getPredicates();
    for (SplatCoverageLegend::Predicates::const_iterator p = preds.begin(); p != preds.end(); ++p)
    {
        const CoverageValuePredicate* pred = p->get();

        if (pred->_exactValue.isSet())
        {
            int coverageIndex = (int)(::atoi(pred->_exactValue.get().c_str()));
            if (coverageIndex >= 0 && coverageIndex < NUM_CLASSES)
            {
                CoverageClass& coverageClass = lut[coverageIndex];
            
                // Look up by class name:
                const std::string& className = pred->_mappedClassName.get();
                const SplatLUT::const_iterator i = _textureDef._splatLUT.find(className);
                if (i != _textureDef._splatLUT.end())
                {
                    const SplatRangeDataVector& ranges = i->second;
                    unsigned r = 0;
                    for (unsigned lod = 0; lod < NUM_LODS; ++lod)
                    {
                        const SplatRangeData& range = ranges[r];
                        write(coverageClass[lod], range);
                        if (range._maxLOD.isSet() && lod == range._maxLOD.get() && (r + 1) < ranges.size())
                            ++r;
                    }
                }
            }
        }
    }

    // Encode the LUT into a texture buffer.
    osg::Image* image = new osg::Image();
    image->allocateImage(NUM_CLASSES * NUM_LODS, 1, 1, GL_RGBA32F_ARB, GL_FLOAT);

    // Populate the LUT image. Each LOD fits into a single RGBA GL_FLOAT vec4
    // by packing 6 floats into 4. See below for packing approach
    GLfloat* ptr = reinterpret_cast<GLfloat*>( image->data() );
    for (unsigned c=0; c<NUM_CLASSES; ++c)
    {
        for (unsigned lod=0; lod<NUM_LODS; ++lod)
        {
            LOD& record = lut[c][lod];

            *ptr++ = record.primary;
            *ptr++ = record.detail;

            // Pack two values into one float. First each value is truncated to a maximum
            // of 2 decimal places; then the first value goes left of the decimal, and the
            // second value goes to the right. The shader will unpack after reading.
            // We do this so that a single texelFetch call will retrieve the entire record.

            float b = (int)(record.brightness*100.0);
            float c = (int)(record.contrast*100.0);
            *ptr++ = b + (c/1000.0f);

            float t = (int)(record.threshold*100.0);
            float s = (int)(record.slope*100.0);
            *ptr++ = t + (s/1000.0f);
        }
    }

    // create a buffer object
    osg::TextureBuffer* buf = new osg::TextureBuffer();
    buf->setImage(image);
    buf->setInternalFormat(GL_RGBA32F_ARB);
    buf->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
    buf->setUnRefImageDataAfterApply(true);

    // Tell the shader generator to skip the positioning texture.
    ShaderGenerator::setIgnoreHint(buf, true);

    return buf;
}