Exemple #1
0
        internal static TextureFilter[] CreateTextures(
            List <Material> materials,
            Point originalMinUV,
            Point originalMaxUV,
            Rect screenSpaceBounds)
        {
            TextureFilter[] textures      = new TextureFilter[materials.Count];
            int             materialCount = 0;

            foreach (Material material in materials)
            {
                if (material is DiffuseMaterial)
                {
                    textures[materialCount] = TextureGenerator.RenderBrushToTextureFilter(
                        ((DiffuseMaterial)material).Brush,
                        originalMinUV, originalMaxUV, screenSpaceBounds);
                    if (textures[materialCount] != null)
                    {
                        textures[materialCount].MaterialType  = MaterialType.Diffuse;
                        textures[materialCount].MaterialColor = ((DiffuseMaterial)material).Color;
                        textures[materialCount].AmbientColor  = ((DiffuseMaterial)material).AmbientColor;
                    }
                }
                else if (material is SpecularMaterial)
                {
                    textures[materialCount] = TextureGenerator.RenderBrushToTextureFilter(
                        ((SpecularMaterial)material).Brush,
                        originalMinUV, originalMaxUV, screenSpaceBounds);
                    if (textures[materialCount] != null)
                    {
                        textures[materialCount].MaterialType  = MaterialType.Specular;
                        textures[materialCount].SpecularPower = ((SpecularMaterial)material).SpecularPower;
                        textures[materialCount].MaterialColor = ((SpecularMaterial)material).Color;
                    }
                }
                else if (material is EmissiveMaterial)
                {
                    textures[materialCount] = TextureGenerator.RenderBrushToTextureFilter(
                        ((EmissiveMaterial)material).Brush,
                        originalMinUV, originalMaxUV, screenSpaceBounds);
                    if (textures[materialCount] != null)
                    {
                        textures[materialCount].MaterialType  = MaterialType.Emissive;
                        textures[materialCount].MaterialColor = ((EmissiveMaterial)material).Color;
                    }
                }
                materialCount++;
            }
            return(textures);
        }
Exemple #2
0
        private void RenderGeometry(ProjectedGeometry pg, Matrix3D view, Material material, VisibleFaces faces)
        {
            if (material == null)
            {
                return;
            }

            Triangle[] triangles = null;

            // Choose list based on triangle winding/facing
            switch (faces)
            {
            case VisibleFaces.Front:
                triangles = pg.FrontFaceTriangles;
                break;

            case VisibleFaces.Back:
                triangles = pg.BackFaceTriangles;
                break;

            default:
                throw new NotSupportedException("Cannot render these type of faces: " + faces.ToString());
            }

            // We should only look into materials if we have any geometry to render.
            // Doing otherwise will throw exceptions when trying to use screen-space
            // bounds or UV coordinates.
            if (triangles.Length > 0)
            {
                // Create a flat, ordered list of textures to apply to this model
                List <Material> materials = ExtractMaterials(material);

                // Create a list of textures from the materials
                TextureFilter[] textures = TextureFilter.CreateTextures(
                    materials, pg.OriginalMinUV, pg.OriginalMaxUV, Rect.Intersect(bounds.RenderBounds, pg.ScreenSpaceBounds));

                // Use a precomputed light shader
                Shader shader = null;
                if (interpolation == InterpolationMode.Phong)
                {
                    shader = new PrecomputedPhongShader(triangles, buffer, lights, textures, view);
                }
                else
                {
                    shader = new PrecomputedGouraudShader(triangles, buffer, lights, textures, view);
                }
                shader.Rasterize(bounds.RenderBounds);
                RenderSilhouetteTolerance(pg, buffer, faces);
            }
        }
Exemple #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
                    );
            }
        }
Exemple #4
0
        private static TextureFilter RenderBrushToTextureFilter(TileBrush brush, Point uvMin, Point uvMax, Rect screenSpaceBounds)
        {
            if (brush.ViewportUnits == BrushMappingMode.Absolute)
            {
                // Convert to relative (including extra tiling caused by repeating UV's)

                Matrix scale = GetConversionToRelative(uvMin, uvMax);

                Point tl = brush.Viewport.TopLeft * scale;
                Point br = brush.Viewport.BottomRight * scale;

                brush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
                brush.Viewport      = new Rect(tl, br);
            }

            //

            double desiredWidth  = 0;
            double desiredHeight = 0;

            if (brush is ImageBrush)
            {
                ImageBrush ib = (ImageBrush)brush;
                desiredWidth  = ((BitmapSource)ib.ImageSource).PixelWidth;
                desiredHeight = ((BitmapSource)ib.ImageSource).PixelHeight;

                desiredWidth = desiredHeight = MathEx.Length(desiredWidth, desiredHeight);
            }
            else if (brush is DrawingBrush || brush is VisualBrush)
            {
                // We don't know how big to make it because WPF can scale the content to an arbitrary size
                //  and still look good (unlike images and their finite amount of data provided).
                //
                // If we make it too large, we will have more detail than WPF and if we make it too small,
                //  we won't have enough detail.  Making the image the as big as the diagonal of the screen
                //  space bounds Rect seems to work best.

                desiredWidth = desiredHeight = MathEx.Length(screenSpaceBounds.Width, screenSpaceBounds.Height);
            }

            double uvWidth  = uvMax.X - uvMin.X;
            double uvHeight = uvMax.Y - uvMin.Y;

            switch (brush.Stretch)
            {
            case Stretch.None:
                // Overwrite the previous computation and set bounds based on UV span
                desiredWidth  = uvWidth;
                desiredHeight = uvHeight;
                break;

            case Stretch.Uniform:
            case Stretch.UniformToFill:
                // Match the aspect ratio of the brush content (currently at 1:1)
                if (uvWidth > uvHeight)
                {
                    desiredWidth *= uvWidth / uvHeight;
                }
                else
                {
                    desiredHeight *= uvHeight / uvWidth;
                }
                break;

            case Stretch.Fill:
                // desiredWidth/Height are already correct
                break;
            }

            BitmapSource image = RenderBrushToImageData(brush, (int)desiredWidth, (int)desiredHeight);

            //// Avalon chooses different filtering based on brush type and tiling mode:
            ////      ImageBrush -> Trilinear
            ////      DrawingBrush -> Bilinear see Change 164703 by REDMOND\milesc on 2006/03/28 20:37:04
            ////      VisualBrush -> Bilinear see Change 164703 by REDMOND\milesc on 2006/03/28 20:37:04
            TextureFilter filter = (brush is ImageBrush)
                            ? new TrilinearTextureFilter(image)
                            : new BilinearTextureFilter(image);

            // Perform a texture lookup error estimation
            filter.HasErrorEstimation = true;
            return(filter);
        }