Esempio n. 1
0
    // steps convolution like a coroutine
    // returns true if more pixels are to be processed on IN, false if last pixel was processed
    private void stepConvo()
    {
        ps.blockMetric.begin();

        ulong isize         = ps.lightCount;
        ulong osize         = ps.lightCount;
        float invLightCount = 1f / (float)ps.lightCount;

        ulong passSize  = isize * osize;
        ulong endOfPass = passSize - 1;

        //re-initialize iterator state
        ulong expPass = ps.curr / passSize;
        ulong ixyoxy  = ps.curr % passSize;
        ulong ixy     = ixyoxy / osize;
        ulong oxy     = ixyoxy % osize;

        expPass = ps.exponentCount - expPass - 1;

        /*
         * ulong passItr = ps.curr / passSize;					//iterates over every exponent pass
         * ulong inoutItr = ps.curr % passSize;                 //iterates over every in-out pairing
         * ulong inItr =  inoutItr / osize;					//iterates over every input pixel
         * ulong outItr = inoutItr % osize;					//iterates over every output pixel
         * passItr = (ulong)outExponentCount - passItr - 1;	//flip pass iterators to do high exponents last
         */
        // iterate over all 5 nested for loops of expPass { iy { ix { oy { ox } } } } linearly and extract pixel coordinates from i
        for ( ; ps.curr < ps.total;)
        {
            ixyoxy = ps.curr % passSize;             // needed every frame to check for end of pass
            oxy    = ps.curr % osize;

            if (oxy == 0)                // next input pixel
            {
                ixy = ixyoxy / osize;
                if (ixyoxy == 0)                        //start an exponent pass
                {
                    expPass = ps.curr / passSize;
                    expPass = ps.exponentCount - expPass - 1;

                    //if we're putting the reflection into the highest mip level, skip the first exponent pass and do this instead
                    if (expPass == 0 && ps.reflectionInSIM)
                    {
                        uploadReflection(0, outMipSizes[0]);
                        ps.skip(ps.lightCount * ps.lightCount);
                        if (ps.needsRepaint())
                        {
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    ps.exponent     = outExponents[expPass];
                    ps.exponentFunc = QPow.closestPowFunc(ps.exponent);
                    ps.exposure     = specNormalizer(ps.exponent) * invLightCount;

                    Util.clearTo(ref ps.CONVO.pixels, Color.black);
                }
                ps.inLookup = ps.lightDirs[ixy];
                ps.LColor   = ps.lights[ixy];
            }
            //NOTE: this assumes input and output dimensions match!
            ps.outLookup = ps.lightDirs[oxy];
            float dp = ps.inLookup.x * ps.outLookup.x +
                       ps.inLookup.y * ps.outLookup.y +
                       ps.inLookup.z * ps.outLookup.z;

            if (dp > 0f)
            {
                dp = ps.exponentFunc(dp);
                //compute two pixels with the same dot product
                //NOTE: this only works if input dimensions match output dimensions!
                ps.CONVO.pixels[oxy] += ps.exposure * dp * ps.LColor;
                if (oxy != ixy)
                {
                    ps.CONVO.pixels[ixy] += ps.exposure * dp * ps.lights[oxy];
                }
            }

            if (ixyoxy == endOfPass)                //end of exponent pass
            {
                ps.passWriteMetric.begin();
                if (uiShowPreview)
                {
                    uiConvoPreview.SetPixels(ps.CONVO.pixels);
                    uiConvoPreview.Apply();
                }
                if (ps.exponent == 1)
                {
                    // DIM
                    finishDIM();
                }
                else
                {
                    // SIM
                    if (ps.buildMipChain)
                    {
                        int mipSize = outMipSizes[expPass];
                        uploadMipLevel((int)expPass, mipSize);
                    }
                    else
                    {
                        finishSIM();
                    }
                }
                ps.passWriteMetric.end();
            }
            // modified j=i for loop. Since we compute two pixels with the same dot product above,
            // we can skip any repeating permutations of input/output pixels.
            if (oxy >= ixy)
            {
                ps.skip(osize - oxy);
            }
            else
            {
                ps.next();
            }

            if (ps.needsRepaint())
            {
                break;
            }
        }
        ps.blockMetric.end();
    }