Beispiel #1
0
static inline void drawLight(vec2 * pos, float size){
	glPushMatrix();
	glTranslatef(pos->x,pos->y,0);
	backTransform();
	glTranslatef(0,0.2,0);
		Begin(GL_TRIANGLE_FAN);
			TexCoord2f (0.0f, 0.0f);
			Vertex2f(-size,-size);
			TexCoord2f (0.0f, 1.0f);
			Vertex2f(-size,size);
			TexCoord2f (1.0f, 1.0f);
			Vertex2f(size,size);
			TexCoord2f (1.0f, 0.0f);
			Vertex2f(size,-size);
		End();
	glPopMatrix();
}
Beispiel #2
0
/*virtual*/
void
DeepTransform::sample (int outX,
                       int outY,
                       const DeepTile& deep_in_tile,
                       Dcx::DeepPixel& out_pixel)
{
    out_pixel.clear();

    // No filtering, find nearest input pixel and copy it:
    if (m_filter_mode == FILTER_NEAREST)
    {
        // Back project center of pixel:
        float finX, finY;
        backTransform(float(outX)+0.5f,  float(outY)+0.5f, finX, finY, 0/*clamp_to*/);
        const int inX = int(floorf(finX)+0.01f);
        const int inY = int(floorf(finY)+0.01f);

        if (inX < deep_in_tile.x() || inX > deep_in_tile.r() || 
            inY < deep_in_tile.y() || inY > deep_in_tile.t())
            return; // Skip if projected outside input bbox

        deep_in_tile.getDeepPixel(inX, inY, out_pixel);

        return;
    }

    // Back-project output pixel corners into input tile.
    // backTransform expects an inclusive bbox, so we don't add one to r/t here:
    const IMATH_NAMESPACE::Box2i in = backTransform(IMATH_NAMESPACE::Box2i(IMATH_NAMESPACE::V2i(outX, outY),
                                                                           IMATH_NAMESPACE::V2i(outX, outY)), 0/*clamp_to*/);

#ifdef DCX_DEBUG_TRANSFORM
    if (debug) {
        std::cout << "----------------------------------------------------------------------------------" << std::endl;
        std::cout << "DeepTransform::sample(" << outX << ", " << outY << ") yUp=" << deep_in_tile.tileYup();
//        std::cout << ", dataWindow" << deep_in_tile.dataWindow() << std::endl;
        //std::cout << "  transform:" << std::endl << std::fixed << imatrix();
//        std::cout << "  sample input rectangle=" << in;
        std::cout << " [" << (in.max.x - in.min.x + 1) << " " << (in.max.y - in.min.y + 1) << "]";
    }
#endif

    // Bail if it transformed outside input bbox:
    if (in.min.x < deep_in_tile.x() || in.max.x > deep_in_tile.r() || 
        in.min.y < deep_in_tile.y() || in.max.y > deep_in_tile.t())
#ifdef DCX_DEBUG_TRANSFORM
    {
        if (debug) std::cout << "...sample rectangle outside input tile bbox, bail." << std::endl;
        return;
    }
#else
        return;
#endif

    Dcx::DeepPixel in_pixel(deep_in_tile.channels());

    //=============================================================
    // Partial-transparency filtering
    //=============================================================

    const int   ss_factor = std::min(std::max(m_ss_factor, 1), SSAMPLING_MAX);
    const int   ss_factor_sqr = ss_factor*ss_factor;
    const int   superW = (int)SpMask8::width*ss_factor; // 32
    const float ifsuperW = 1.0f/float(superW);
    const float ss_factor_center = 0.5f/float(superW);
    const float fmaskW = float(SpMask8::width);
    const float foutX = float(outX);
    const float foutY = float(outY);
    float finX, finY;
#ifdef DCX_DEBUG_TRANSFORM
    if (debug) std::cout << ", ss_factor=" << ss_factor << ", ss_factor_sqr=" << ss_factor_sqr << std::endl;
#endif

    char    bin_hits[SpMask8::numBits];
    std::vector<char> ss_weight_counts(ss_factor_sqr);   //char    ss_weight_counts[ss_factor_sqr];
    std::vector<SpMask8> ss_weight_masks(ss_factor_sqr); //SpMask8 ss_weight_masks[ss_factor_sqr];
    SpMask8 out_mask, out_opaque_mask, out_transp_mask;

    // Iterate through input pixel range, finding segments that contribute to the output pixel,
    // and resampling the masks:
    for (int tY=in.min.y; tY <= in.max.y; ++tY)
    {
        for (int tX=in.min.x; tX <= in.max.x; ++tX)
        {
            // Get the deep pixel from the deep tile:
            deep_in_tile.getDeepPixel(tX, tY, in_pixel);
            const size_t nSegments = in_pixel.size();
#ifdef DCX_DEBUG_TRANSFORM
            if (debug) {
                std::cout << "  --------------------------------------------------------------------" << std::endl;
                std::cout << "  in[" << tX << " " << tY << "] segments=" << nSegments << std::endl;
            }
#endif

            if (nSegments == 0)
                continue;
            assert(nSegments < 10000); // just in case...

            // There's input subpixel masks, so resample them:
            for (size_t segment=0; segment < nSegments; ++segment)
            {
                // Get input segment:
                const DeepSegment& in_segment = in_pixel.getSegment(segment);
                const SpMask8 in_mask = (!in_segment.zeroCoverage())?in_segment.spMask():SpMask8::fullCoverage;

#ifdef DCX_DEBUG_TRANSFORM
                if (debug) {
                    std::cout << "   -----------------------------" << std::endl;
                    std::cout << "   " << segment << " Zf=" << in_segment.Zf << ", Zb=" << in_segment.Zb << std::endl;
                    std::cout << "   mask:" << std::endl;
                    in_mask.printPattern(std::cout, "   ");
                }
#endif
                out_mask = out_opaque_mask = SpMask8::zeroCoverage;
                memset(bin_hits, 0, SpMask8::numBits);

                // Sample subpixel locations at a potentially higher rate and stochastically(TODO)
                // than 8x8, building up the bin-hit counts and accumulated masks:
                for (int spSupOutY=(superW-1); spSupOutY >= 0; --spSupOutY)
                {
#ifdef DCX_DEBUG_TRANSFORM
                    if (debug) std::cout << "  ";
#endif
                    const int spOutY = spSupOutY / ss_factor;
                    for (int spSupOutX=0; spSupOutX < superW; ++spSupOutX)
                    {
                        const int spOutX = spSupOutX / ss_factor;
                        // Back-project input subpixel coordinate into output space:
                        // (TODO: can this be a dPdx/dpDy interpolation routine instead?)
                        // (TODO: jitter this stochastically too!)
                        backTransform(foutX + ss_factor_center + float(spSupOutX)*ifsuperW,
                                      foutY + ss_factor_center + float(spSupOutY)*ifsuperW,
                                      finX, finY);
                        const float flr_inX = floorf(finX);
                        const float flr_inY = floorf(finY);
                        const int inX = int(flr_inX);
                        const int inY = int(flr_inY);
                        // Skip if it projects outside the current output pixel:
                        if (inX != tX || inY != tY)
#ifdef DCX_DEBUG_TRANSFORM
                        {
                            if (debug) std::cout << " [   ]  ";
                            continue;
                        }
#else
                            continue;
#endif

                        // Sample location in input spmask:
                        const int spInX = int(floorf((finX - flr_inX)*fmaskW));
                        const int spInY = int(floorf((finY - flr_inY)*fmaskW));
#ifdef DCX_DEBUG_TRANSFORM
                        if (debug) std::cout << " [" << spInX << " " << spInY << "]";
#endif

                        // Get input spmask bit:
                        const SpMask8 in_sp = SpMask8(1ull) << (spInY*SpMask8::width + spInX);
                        if (in_mask & in_sp)
                        {
                            // Increment hit-count for this output bin:
                            const int out_bin = spOutY*SpMask8::width + spOutX;
                            assert(out_bin < (int)SpMask8::numBits);
                            const SpMask8 out_sp = SpMask8(1ull) << out_bin;
                            out_mask |= out_sp;
                            ++bin_hits[out_bin];
                            if (bin_hits[out_bin] >= ss_factor_sqr)
                                out_opaque_mask |= out_sp;
#ifdef DCX_DEBUG_TRANSFORM
                            if (debug) std::cout << "=" << std::dec << (int)bin_hits[out_bin];
#endif
                        }
#ifdef DCX_DEBUG_TRANSFORM
                        else
                        {
                            if (debug) std::cout << "  ";
                        }
#endif

                    } // spInX loop
#ifdef DCX_DEBUG_TRANSFORM
                    if (debug) std::cout << std::endl;
#endif

                } // spInY loop

                // Skip this segment if it doesn't overlap any output bins:
                if (out_mask == SpMask8::zeroCoverage)
#ifdef DCX_DEBUG_TRANSFORM
                {
                    if (debug) std::cout << "     no output overlap, skip segment " << segment << std::endl;
                    continue;
                }
#else
                    continue;
#endif

                // Write the opaque sample if the mask is non-zero:
                if (out_opaque_mask != SpMask8::zeroCoverage) {
                    DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment));
                    // Update output metadata:
                    out_segment.metadata.spmask = out_opaque_mask;
                    out_segment.metadata.flags &= ~DEEP_PARTIAL_BIN_COVERAGE;
                }

                // Write partially-transparent segment if segment is included in accumulated transp mask:
                // The transparent mask is the bins that are on but not opaque:
                out_transp_mask = (out_mask & ~out_opaque_mask);
#if 0//def DCX_DEBUG_TRANSFORM
                if (debug) {
                    std::cout << "   out_mask" << std::endl;
                    out_mask.printPattern(std::cout, "   ");
                    std::cout << "   out_opaque_mask" << std::endl;
                    out_opaque_mask.printPattern(std::cout, "   ");
                    std::cout << "   out_transp_mask" << std::endl;
                    out_transp_mask.printPattern(std::cout, "   ");
                }
#endif
                if (out_transp_mask != SpMask8::zeroCoverage)
                {
                    // Determine weights for each bin, then output the dominant weight, or
                    // separate segments with the separate weights separated by subpixel bits:
                    memset(&ss_weight_counts[0], 0, ss_factor_sqr);
                    memset(&ss_weight_masks[0], 0, ss_factor_sqr*sizeof(SpMask8));

                    float average_weight = 0.0f;
                    int transp_hits = 0;
                    SpMask8 count_mask(1ull);
                    for (int sp_bin=0; sp_bin < SpMask8::numBits; ++sp_bin, count_mask <<= 1)
                    {
                        const int nHits = bin_hits[sp_bin];
                        if (nHits == 0 || nHits >= ss_factor_sqr)
                             continue;
                        // Increment weight count for ss bin:
                        ++ss_weight_counts[nHits];
                        ss_weight_masks[nHits] |= (SpMask8(1ull) << sp_bin);
                        //
                        const float bin_weight = float(nHits) / float(ss_factor_sqr);
                        average_weight += bin_weight;
                        ++transp_hits;
                    }
                    //
                    if (1)
                    {
                        // Output separate segments for each weight bin, building a unique
                        // subpixel mask for each:
                        for (int i=1; i < ss_factor_sqr; ++i)
                        {
                            const int weight_count = ss_weight_counts[i];
                            if (weight_count == 0)
                                continue;
                            DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment));
                            // Weight output channels:
                            out_pixel.getSegmentPixel(out_segment) *= float(i) / float(ss_factor_sqr);
                            // Update output metadata:
                            out_segment.metadata.spmask = ss_weight_masks[i];
                            out_segment.metadata.flags |= DEEP_PARTIAL_BIN_COVERAGE;
                        }
                    }
                    else
                    {
                        // Output only the dominant (just the average for now...) weight:
                        // TODO: change this to some other weighting...?
                        DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment));
                        // Weight output channels:
                        out_pixel.getSegmentPixel(out_segment) *= (average_weight / float(transp_hits));
                        // Update output metadata:
                        out_segment.metadata.spmask = out_transp_mask;
                        out_segment.metadata.flags |= DEEP_PARTIAL_BIN_COVERAGE;
                    }

                }

            } // segments loop

        } // tX loop

    } // tY loop

}