Exemplo n.º 1
0
        /// <summary>
        /// Writes a pixel to the buffer according to depth-test for single pass rendering.
        /// </summary>
        /// <param name="x">x index</param>
        /// <param name="y">y index</param>
        /// <param name="z">Depth buffer value</param>
        /// <param name="premultColor">Premultiplied Frame buffer value</param>
        /// <param name="premultTolerance">Premultiplied Tolerance buffer value</param>
        public void SetPixel(int x, int y, float z, Color premultColor, Color premultTolerance)
        {
            if (x >= 0 && x < width && y >= 0 && y < height && z >= 0 && z <= 1.0f)
            {
                bool isZFightingPossible = IsPixelRendered(x, y);
                bool drawPixel           = DepthTest(z, zBuffer[x, y]);
                if (drawPixel)
                {
                    // Write to frame buffer according to alpha value of pixel
                    frameBuffer[x, y] = ColorOperations.PreMultipliedAlphaBlend(
                        premultColor,
                        frameBuffer[x, y]);

                    // We have a pre-multiplied tolerance value
                    toleranceBuffer[x, y] = ColorOperations.PreMultipliedToleranceBlend(
                        premultTolerance,
                        toleranceBuffer[x, y],
                        premultColor.A);
                }

                // See if we were within tolerance of another test result
                if (isZFightingPossible)
                {
                    if (DepthTestWithinTolerance(z, zBuffer[x, y], RenderTolerance.ZBufferTolerance))
                    {
                        // If so, ignore this pixel, since we can't be sure if it's right
                        toleranceBuffer[x, y] = Color.FromArgb(0, 255, 255, 255);
                    }
                }
                else if (z < RenderTolerance.NearPlaneTolerance || 1.0 - RenderTolerance.FarPlaneTolerance < z)
                {
                    // If we're right on the near/far clipping plane, we can't be sure if this pixel is right.

                    // Note that the tolerance at the near plane will be considerably more than that of the
                    //  far plane if we are using a perspective camera to view this scene.
                    toleranceBuffer[x, y] = Color.FromArgb(0, 255, 255, 255);
                }

                if (drawPixel && writeToZBuffer)
                {
                    zBuffer[x, y] = z;
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Blend the contents of the RenderBuffer with a background color
        /// </summary>
        public void AddBackground(Color opaqueBackgroundColor)
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // We keep our colors and tolerances premultiplied.
                    // Do the tolerance blend first so that we have the correct alpha value from the framebuffer
                    toleranceBuffer[x, y] = ColorOperations.PreMultipliedToleranceBlend(
                        toleranceBuffer[x, y],
                        toleranceBufferClearValue,
                        frameBuffer[x, y].A);

                    frameBuffer[x, y] = ColorOperations.PreMultipliedAlphaBlend(
                        frameBuffer[x, y],
                        opaqueBackgroundColor);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Lights this pixel using precomputed lighting information.
        /// </summary>
        /// <param name="v">Interpolated vertex for this pixel position.</param>
        protected override void ComputePixelProgram(Vertex v)
        {
            bool  rendered = false;
            Color totalTexturingTolerance = emptyColor;

            for (int pass = 0; pass < textures.Length; pass++)
            {
                // A Filter can be null if the Material or the Brush are null.
                // For those cases, we skip the material entirely.
                if (textures[pass] == null)
                {
                    continue;
                }
                TextureFilter currentTexture = textures[pass];
                rendered = true;

                // We need extra information for trilinear
                if (currentTexture is TrilinearTextureFilter)
                {
                    ((TrilinearTextureFilter)currentTexture).MipMapFactor = v.MipMapFactor;
                }

                // Textures are not stored in premultiplied color space.
                // This means that we have to wait until we find the lookup tolerance before we can premultiply
                //  (otherwise Alpha will be way off)

                Color texel          = currentTexture.FilteredTextureLookup(v.TextureCoordinates);
                Color texelTolerance = emptyColor;
                if (currentTexture.HasErrorEstimation)
                {
                    texelTolerance = currentTexture.FilteredErrorLookup(
                        v.UVToleranceMin,
                        v.UVToleranceMax,
                        texel);
                }

                // Now we can premultiply.
                Color premultTexel          = ColorOperations.PreMultiplyColor(texel);
                Color premultTexelTolerance = ColorOperations.PreMultiplyTolerance(texelTolerance, texel.A);

                // Modulate precomputed lighting (which is also premultiplied) by the Brush value
                Color premultColor     = ColorOperations.Modulate(v.PrecomputedLight[pass], premultTexel);
                Color premultTolerance = ColorOperations.Modulate(v.PrecomputedLight[pass], premultTexelTolerance);

                // PrecomputedLightTolerance is NOT premultipled yet (see ComputeVertexProgram above).
                //  This is because we needed to know the final alpha value of lighting * texture.
                //
                Color premultLightTolerance = ColorOperations.PreMultiplyTolerance(v.PrecomputedLightTolerance[pass], premultColor.A);
                premultTolerance = ColorOperations.Add(premultTolerance, premultLightTolerance);

                // For additive materials, we need to force the alpha channel to zero.
                // See notes on premultiplied blending in ColorOperations.cs
                if (currentTexture.MaterialType != MaterialType.Diffuse)
                {
                    premultColor.A = 0x00;
                    // Nothing needs to be done to tolerance's alpha
                    //  because the framebuffer's alpha value will be used in the blend
                }

                // we need to blend
                // Write to frame buffer according to alpha value of pixel
                v.Color = ColorOperations.PreMultipliedAlphaBlend(premultColor, v.Color);

                // Accumulate tolerance for each material pass
                totalTexturingTolerance = ColorOperations.PreMultipliedToleranceBlend(
                    premultTolerance,
                    totalTexturingTolerance,
                    premultColor.A);
            }

            // Only set a pixel if we actually rendered at least one material for it ...
            if (rendered)
            {
                // Add texturing tolerance to our existing lighting tolerance.
                v.ColorTolerance = ColorOperations.Add(v.ColorTolerance, totalTexturingTolerance);

                // Send the pixel to be rendered
                buffer.SetPixel(
                    (int)Math.Floor(v.ProjectedPosition.X),
                    (int)Math.Floor(v.ProjectedPosition.Y),
                    (float)v.ProjectedPosition.Z,
                    v.Color,
                    v.ColorTolerance
                    );
            }
        }