public void RenderPlane(IRenderContext context, IEffect effect, IEffectParameterSet effectParameterSet, Matrix transform, TextureAsset texture, Vector2 topLeftUV, Vector2 bottomRightUV)
        {
            if (!context.IsCurrentRenderPass <I3DRenderPass>())
            {
                throw new InvalidOperationException("Can't use 3D rendering utilities in 2D context.");
            }

            var vertexes = new[]
            {
                new VertexPositionNormalTexture(new Vector3(0, 0, 0), new Vector3(0, -1, 0), new Vector2(topLeftUV.X, topLeftUV.Y)),
                new VertexPositionNormalTexture(new Vector3(0, 0, 1), new Vector3(0, -1, 0), new Vector2(topLeftUV.X, bottomRightUV.Y)),
                new VertexPositionNormalTexture(new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector2(bottomRightUV.X, topLeftUV.Y)),
                new VertexPositionNormalTexture(new Vector3(1, 0, 1), new Vector3(0, -1, 0), new Vector2(bottomRightUV.X, bottomRightUV.Y))
            };

            var indicies = new short[]
            {
                0, 2, 1,
                3, 1, 2
            };

            var semantic = effectParameterSet.GetSemantic <ITextureEffectSemantic>();

            if (semantic.Texture != texture.Texture)
            {
                semantic.Texture = texture.Texture;
            }

            var world = context.World;

            context.World = transform;

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawUserIndexedPrimitives(
                    PrimitiveType.TriangleList,
                    vertexes,
                    0,
                    vertexes.Length,
                    indicies,
                    0,
                    indicies.Length / 3);
            }

            context.World = world;
        }
Esempio n. 2
0
        public void LoadParameterSet(IRenderContext renderContext, IEffectParameterSet effectParameters, bool skipMatricSync)
        {
            if (!skipMatricSync)
            {
                if (effectParameters.HasSemantic <IWorldViewProjectionEffectSemantic>())
                {
                    var semantic = effectParameters.GetSemantic <IWorldViewProjectionEffectSemantic>();
                    semantic.World      = renderContext.World;
                    semantic.Projection = renderContext.Projection;
                    semantic.View       = renderContext.View;
                }
            }

            ((ProtogameParameterSet)effectParameters).Load(renderContext, _targetEffect);
        }
        public void RenderLine(IRenderContext context, IEffect effect, IEffectParameterSet effectParameterSet, Vector3 start, Vector3 end, TextureAsset texture, Vector2 startUV, Vector2 endUV)
        {
            if (!context.IsCurrentRenderPass <I3DRenderPass>())
            {
                throw new InvalidOperationException("Can't use 3D rendering utilities in 2D context.");
            }

            var vertexes = _renderCache.GetOrSet(
                "renderlinetex3dvb:" + start + ":" + end + ":" + startUV + ":" + endUV,
                () =>
            {
                var vb = new VertexBuffer(context.GraphicsDevice, VertexPositionTexture.VertexDeclaration, 2,
                                          BufferUsage.WriteOnly);
                vb.SetData(new[] { new VertexPositionTexture(start, startUV), new VertexPositionTexture(end, endUV) });
                return(vb);
            });
            var indicies = _renderCache.GetOrSet(
                "renderline3dib",
                () =>
            {
                var ib = new IndexBuffer(context.GraphicsDevice, IndexElementSize.SixteenBits, 2,
                                         BufferUsage.WriteOnly);
                ib.SetData(new short[] { 0, 1 });
                return(ib);
            });

            context.GraphicsDevice.SetVertexBuffer(vertexes);
            context.GraphicsDevice.Indices = indicies;

            var semantic = effectParameterSet.GetSemantic <ITextureEffectSemantic>();

            if (semantic.Texture != texture.Texture)
            {
                semantic.Texture = texture.Texture;
            }

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, 1);
            }
        }
        private IEffectParameterSet GetEffectParameterSet(IMaterial material, ref bool changedRenderRequest, ref string changedRenderRequestBy)
        {
            if (_effectUsedForParameterSetCache == _cachedEffect &&
                changedRenderRequest == false &&
                (!_lastDidSetDiffuseTexture || _lastSetDiffuseTexture == _lastCachedDiffuseTexture?.Texture) &&
                (!_lastDidSetNormalMap || _lastSetNormalMap == _lastCachedNormalMapTexture?.Texture) &&
                (!_lastDidSetSpecularPower || _lastSetSpecularPower == _lastCachedSpecularPower) &&
                (!_lastDidSetSpecularColorMap || _lastSetSpecularColorMap == _lastCachedSpecularColorMapTexture?.Texture) &&
                (!_lastDidSetSpecularColor || _lastSetSpecularColor == _lastCachedSpecularColor) &&
                (!_lastDidSetDiffuseColor || _lastSetDiffuseColor == (material.ColorDiffuse ?? Color.Black)))
            {
                // Reuse the existing parameter set.
                return _cachedEffectParameterSet;
            }

            changedRenderRequest = true;
            changedRenderRequestBy += ":parameterset";

            // Create a new parameter set and cache it.
            _cachedEffectParameterSet = _cachedEffect.CreateParameterSet();
            _effectUsedForParameterSetCache = _cachedEffect;

            _lastSetDiffuseTexture = null;
            _lastSetNormalMap = null;
            _lastSetSpecularPower = null;
            _lastSetSpecularColorMap = null;
            _lastSetSpecularColor = null;
            _lastSetDiffuseColor = null;
            _lastDidSetDiffuseTexture = false;
            _lastDidSetNormalMap = false;
            _lastDidSetSpecularPower = false;
            _lastDidSetSpecularColorMap = false;
            _lastDidSetSpecularColor = false;
            _lastDidSetDiffuseColor = false;

            if (_cachedEffectParameterSet.HasSemantic<ITextureEffectSemantic>())
            {
                if (_lastCachedDiffuseTexture?.Texture != null)
                {
                    _cachedEffectParameterSet.GetSemantic<ITextureEffectSemantic>().Texture =
                        _lastCachedDiffuseTexture.Texture;
                    _lastSetDiffuseTexture = _lastCachedDiffuseTexture.Texture;
                    _lastDidSetDiffuseTexture = true;
                }
            }

            if (_cachedEffectParameterSet.HasSemantic<INormalMapEffectSemantic>())
            {
                if (_lastCachedNormalMapTexture?.Texture != null)
                {
                    _cachedEffectParameterSet.GetSemantic<INormalMapEffectSemantic>().NormalMap =
                        _lastCachedNormalMapTexture.Texture;
                    _lastSetNormalMap = _lastCachedNormalMapTexture.Texture;
                    _lastDidSetNormalMap = true;
                }
            }

            if (_cachedEffectParameterSet.HasSemantic<ISpecularEffectSemantic>())
            {
                if (_lastCachedSpecularPower != null)
                {
                    var semantic = _cachedEffectParameterSet.GetSemantic<ISpecularEffectSemantic>();
                    semantic.SpecularPower = _lastCachedSpecularPower.Value;
                    _lastSetSpecularPower = _lastCachedSpecularPower.Value;
                    _lastDidSetSpecularPower = true;

                    if (_lastCachedSpecularColorMapTexture != null)
                    {
                        semantic.SpecularColorMap = _lastCachedSpecularColorMapTexture.Texture;
                        _lastSetSpecularColorMap = _lastCachedSpecularColorMapTexture.Texture;
                        _lastDidSetSpecularColorMap = true;
                    }
                    else if (_lastCachedSpecularColor != null)
                    {
                        semantic.SpecularColor = _lastCachedSpecularColor.Value;
                        _lastSetSpecularColor = _lastCachedSpecularColor.Value;
                        _lastDidSetSpecularColor = true;
                    }
                }
            }

            if (_cachedEffectParameterSet.HasSemantic<IColorDiffuseEffectSemantic>())
            {
                var v = material.ColorDiffuse ?? Color.Black;
                _cachedEffectParameterSet.GetSemantic<IColorDiffuseEffectSemantic>().Diffuse = v;
                _lastSetDiffuseColor = v;
                _lastDidSetDiffuseColor = true;
            }

            return _cachedEffectParameterSet;
        }
        public void RenderLine(IRenderContext context, IEffect effect, IEffectParameterSet effectParameterSet, Vector3 start, Vector3 end, TextureAsset texture, Vector2 startUV, Vector2 endUV)
        {
            if (!context.IsCurrentRenderPass<I3DRenderPass>())
            {
                throw new InvalidOperationException("Can't use 3D rendering utilities in 2D context.");
            }

            var vertexes = _renderCache.GetOrSet(
                "renderlinetex3dvb:" + start + ":" + end + ":" + startUV + ":" + endUV,
                () =>
                {
                    var vb = new VertexBuffer(context.GraphicsDevice, VertexPositionTexture.VertexDeclaration, 2,
                        BufferUsage.WriteOnly);
                    vb.SetData(new[] { new VertexPositionTexture(start, startUV), new VertexPositionTexture(end, endUV) });
                    return vb;
                });
            var indicies = _renderCache.GetOrSet(
                "renderline3dib",
                () =>
                {
                    var ib = new IndexBuffer(context.GraphicsDevice, IndexElementSize.SixteenBits, 2,
                        BufferUsage.WriteOnly);
                    ib.SetData(new short[] { 0, 1 });
                    return ib;
                });

            context.GraphicsDevice.SetVertexBuffer(vertexes);
            context.GraphicsDevice.Indices = indicies;

            var semantic = effectParameterSet.GetSemantic<ITextureEffectSemantic>();
            if (semantic.Texture != texture.Texture)
            {
                semantic.Texture = texture.Texture;
            }

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, 1);
            }
        }
        public void RenderPlane(IRenderContext context, IEffect effect, IEffectParameterSet effectParameterSet, Matrix transform, TextureAsset texture, Vector2 topLeftUV, Vector2 bottomRightUV)
        {
            if (!context.IsCurrentRenderPass<I3DRenderPass>())
            {
                throw new InvalidOperationException("Can't use 3D rendering utilities in 2D context.");
            }

            var vertexes = new[]
            {
                new VertexPositionNormalTexture(new Vector3(0, 0, 0), new Vector3(0, -1, 0), new Vector2(topLeftUV.X, topLeftUV.Y)),
                new VertexPositionNormalTexture(new Vector3(0, 0, 1), new Vector3(0, -1, 0), new Vector2(topLeftUV.X, bottomRightUV.Y)),
                new VertexPositionNormalTexture(new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector2(bottomRightUV.X, topLeftUV.Y)),
                new VertexPositionNormalTexture(new Vector3(1, 0, 1), new Vector3(0, -1, 0), new Vector2(bottomRightUV.X, bottomRightUV.Y))
            };

            var indicies = new short[]
            {
                0, 2, 1,
                3, 1, 2
            };

            var semantic = effectParameterSet.GetSemantic<ITextureEffectSemantic>();
            if (semantic.Texture != texture.Texture)
            {
                semantic.Texture = texture.Texture;
            }

            var world = context.World;

            context.World = transform;

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawUserIndexedPrimitives(
                    PrimitiveType.TriangleList,
                    vertexes,
                    0,
                    vertexes.Length,
                    indicies,
                    0,
                    indicies.Length / 3);
            }

            context.World = world;
        }
        private void RenderTexture(
            IRenderContext context,
            IEffect effect, 
            IEffectParameterSet effectParameterSet, 
            Matrix matrix, 
            Texture2D texture, 
            Color? color = null, 
            bool flipHorizontally = false, 
            bool flipVertically = false, 
            Rectangle? sourceArea = null)
        {
            if (color != null)
            {
                throw new NotSupportedException();
            }

            if (flipHorizontally)
            {
                throw new NotSupportedException();
            }

            if (flipVertically)
            {
                throw new NotSupportedException();
            }

            if (sourceArea != null)
            {
                throw new NotSupportedException();
            }

            var semantic = effectParameterSet.GetSemantic<ITextureEffectSemantic>();
            if (semantic.Texture != texture)
            {
                semantic.Texture = texture;
            }

            var vertexes = new[]
            {
                new VertexPositionTexture(Vector3.Transform(new Vector3(0, 0, 0), matrix), new Vector2(0, 1)), 
                new VertexPositionTexture(Vector3.Transform(new Vector3(0, 1, 0), matrix), new Vector2(0, 0)), 
                new VertexPositionTexture(Vector3.Transform(new Vector3(1, 0, 0), matrix), new Vector2(1, 1)), 
                new VertexPositionTexture(Vector3.Transform(new Vector3(1, 1, 0), matrix), new Vector2(1, 0))
            };
            var indicies = new short[] { 1, 3, 0, 2 };

            context.GraphicsDevice.BlendState = BlendState.NonPremultiplied;

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawUserIndexedPrimitives(
                    PrimitiveType.TriangleStrip, 
                    vertexes, 
                    0, 
                    vertexes.Length, 
                    indicies, 
                    0, 
                    vertexes.Length - 2);
            }

            context.GraphicsDevice.BlendState = BlendState.Opaque;
        }
Esempio n. 8
0
        /// <summary>
        /// Creates a render request for the model using the specified transform.
        /// </summary>
        /// <param name="renderContext">
        ///     The render context.
        /// </param>
        /// <param name="effect"></param>
        /// <param name="effectParameterSet"></param>
        /// <param name="transform">
        ///     The transform.
        /// </param>
        public IRenderRequest CreateRenderRequest(IRenderContext renderContext, IEffect effect, IEffectParameterSet effectParameterSet, Matrix transform)
        {
            if (Vertexes.Length == 0 && Indices.Length == 0)
            {
                throw new InvalidOperationException(
                          "This model does not have any vertexes or indices.  It's most " +
                          "likely been imported from an FBX file that only contains hierarchy, " +
                          "in which case there isn't anything to render.");
            }

            LoadBuffers(renderContext.GraphicsDevice);

            VertexBuffer vertexBuffer;

            if (_cachedVertexBuffers.ContainsKey(effect))
            {
                vertexBuffer = _cachedVertexBuffers[effect];
            }
            else
            {
                // Find the vertex mapping configuration for this model.
                if (_cachedModelVertexMapping == null)
                {
                    _cachedModelVertexMapping =
                        _modelRenderConfigurations.Select(x => x.GetVertexMappingToGPU(this, effect))
                        .FirstOrDefault(x => x != null);
                    if (_cachedModelVertexMapping == null)
                    {
                        throw new InvalidOperationException(
                                  "No implementation of IModelRenderConfiguration could provide a vertex " +
                                  "mapping for this model.  You must implement IModelRenderConfiguration " +
                                  "and bind it in the dependency injection system, so that the engine is " +
                                  "aware of how to map vertices in models to parameters in effects.");
                    }
                }

                var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length);
                for (var i = 0; i < Vertexes.Length; i++)
                {
                    var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i]);
                    mappedVerticies.SetValue(vertex, i);
                }

                float maxX = 0f, maxY = 0f, maxZ = 0f;
                foreach (var vert in this.Vertexes)
                {
                    if (vert.Position.HasValue)
                    {
                        if (Math.Abs(vert.Position.Value.X) > maxX)
                        {
                            maxX = Math.Abs(vert.Position.Value.X);
                        }
                        if (Math.Abs(vert.Position.Value.Y) > maxY)
                        {
                            maxY = Math.Abs(vert.Position.Value.Y);
                        }
                        if (Math.Abs(vert.Position.Value.Z) > maxZ)
                        {
                            maxZ = Math.Abs(vert.Position.Value.Z);
                        }
                    }
                }

                var radius = new Vector3(maxX, maxY, maxZ).Length() * 2;

                _localisedBoundingRegion = new LocalisedBoundingRegion(radius);

                vertexBuffer = new VertexBuffer(
                    renderContext.GraphicsDevice,
                    _cachedModelVertexMapping.VertexDeclaration,
                    Vertexes.Length,
                    BufferUsage.WriteOnly);
                vertexBuffer.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                    vertexBuffer,
                    new[] { mappedVerticies });
                _cachedVertexBuffers[effect] = vertexBuffer;
            }

            if (effectParameterSet.HasSemantic <IBonesEffectSemantic>())
            {
                var bonesEffectSemantic = effectParameterSet.GetSemantic <IBonesEffectSemantic>();

                foreach (var bone in _flattenedBones)
                {
                    if (bone.ID == -1)
                    {
                        continue;
                    }

                    bonesEffectSemantic.Bones[bone.ID] = bone.GetFinalMatrix();
                }
            }

            // Create the render request.
            return(_renderBatcher.CreateSingleRequestFromState(
                       renderContext,
                       effect,
                       effectParameterSet,
                       vertexBuffer,
                       IndexBuffer,
                       PrimitiveType.TriangleList,
                       renderContext.World * transform, (m, vb, ib) =>
            {
                var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length * m.Count);
                var mappedIndicies = new int[Indices.Length * m.Count];

                for (var im = 0; im < m.Count; im++)
                {
                    for (var i = 0; i < Vertexes.Length; i++)
                    {
                        var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i].Transform(m[im]));
                        mappedVerticies.SetValue(vertex, im * Vertexes.Length + i);
                    }

                    for (var i = 0; i < Indices.Length; i++)
                    {
                        mappedIndicies[im * Vertexes.Length + i] = Indices[i] + Vertexes.Length * im;
                    }
                }

                vb.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                    vb,
                    new[] { mappedVerticies });
                ib.SetData(mappedIndicies);
            },
                       _localisedBoundingRegion));
        }
Esempio n. 9
0
        private void BlitInternal(
            IRenderContext renderContext,
            Texture2D source,
            RenderTarget2D[] destinations = null,
            IEffect shader = null,
            IEffectParameterSet effectParameterSet = null,
            BlendState blendState = null,
            Vector2?offset        = null,
            Vector2?size          = null)
        {
            float destWidth, destHeight;

            if (destinations != null)
            {
                var destinationsBound = new RenderTargetBinding[destinations.Length];
                for (var i = 0; i < destinations.Length; i++)
                {
                    // Implicit cast.
                    destinationsBound[i] = destinations[i];
                }

                renderContext.PushRenderTarget(destinationsBound);
                destWidth  = destinations[0].Width;
                destHeight = destinations[0].Height;
            }
            else
            {
                // TODO: renderContext.GraphicsDevice.GetRenderTargets();
                destWidth  = renderContext.GraphicsDevice.PresentationParameters.BackBufferWidth;
                destHeight = renderContext.GraphicsDevice.PresentationParameters.BackBufferHeight;
            }

            offset = offset ?? new Vector2(0, 0);
            size   = size ?? new Vector2(1 - offset.Value.X, 1 - offset.Value.Y);

            if (blendState == null)
            {
                blendState = BlendState.Opaque;
            }

            if (shader == null && _blitEffect.IsReady)
            {
                shader = _blitEffect.Asset.Effects["Texture"];
            }

            if (shader == null)
            {
                // Can't perform blit; no shader is available.
                return;
            }

            if (effectParameterSet == null)
            {
                effectParameterSet = shader.CreateParameterSet();
            }

            if (_vertexBuffer == null)
            {
                _vertexBuffer = new VertexBuffer(renderContext.GraphicsDevice, typeof(VertexPositionNormalTexture),
                                                 _vertexes.Length, BufferUsage.WriteOnly);
                _vertexBuffer.SetData(_vertexes);
            }

            if (_indexBuffer == null)
            {
                _indexBuffer = new IndexBuffer(renderContext.GraphicsDevice, typeof(short), _indicies.Length,
                                               BufferUsage.WriteOnly);
                _indexBuffer.SetData(_indicies);
            }

            var oldWorld      = renderContext.World;
            var oldProjection = renderContext.Projection;
            var oldView       = renderContext.View;

            renderContext.GraphicsDevice.BlendState        = blendState;
            renderContext.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            renderContext.GraphicsDevice.SamplerStates[0]  = SamplerState.LinearWrap;
            renderContext.GraphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;

            renderContext.World      = Matrix.CreateScale(destWidth, destHeight, 1);
            renderContext.Projection =
#if !PLATFORM_WINDOWS
                Matrix.CreateTranslation(-0.5f, -0.5f, 0) *
#endif
                Matrix.CreateOrthographicOffCenter(
                    destWidth * (-offset.Value.X / size.Value.X),
                    destWidth * (-offset.Value.X / size.Value.X) + destWidth / size.Value.X,
                    destHeight * (-offset.Value.Y / size.Value.Y) + destHeight / size.Value.Y,
                    destHeight * (-offset.Value.Y / size.Value.Y),
                    0,
                    1);
            renderContext.View = Matrix.Identity;

            if (source != null && effectParameterSet != null)
            {
                var semantic = effectParameterSet.GetSemantic <ITextureEffectSemantic>();
                if (semantic.Texture != source)
                {
                    semantic.Texture = source;
                }
            }

            renderContext.GraphicsDevice.SetVertexBuffer(_vertexBuffer);
            renderContext.GraphicsDevice.Indices = _indexBuffer;

            shader.LoadParameterSet(renderContext, effectParameterSet);
            foreach (var pass in shader.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                renderContext.GraphicsDevice.DrawIndexedPrimitives(
                    PrimitiveType.TriangleStrip,
                    0,
                    0,
                    2);
            }

            renderContext.World      = oldWorld;
            renderContext.Projection = oldProjection;
            renderContext.View       = oldView;

            if (destinations != null)
            {
                renderContext.PopRenderTarget();
            }
        }
        private void RenderTexture(
            IRenderContext context,
            IEffect effect,
            IEffectParameterSet effectParameterSet,
            Matrix matrix,
            Texture2D texture,
            Color?color           = null,
            bool flipHorizontally = false,
            bool flipVertically   = false,
            Rectangle?sourceArea  = null)
        {
            if (color != null)
            {
                throw new NotSupportedException();
            }

            if (flipHorizontally)
            {
                throw new NotSupportedException();
            }

            if (flipVertically)
            {
                throw new NotSupportedException();
            }

            if (sourceArea != null)
            {
                throw new NotSupportedException();
            }

            var semantic = effectParameterSet.GetSemantic <ITextureEffectSemantic>();

            if (semantic.Texture != texture)
            {
                semantic.Texture = texture;
            }

            var vertexes = new[]
            {
                new VertexPositionTexture(Vector3.Transform(new Vector3(0, 0, 0), matrix), new Vector2(0, 1)),
                new VertexPositionTexture(Vector3.Transform(new Vector3(0, 1, 0), matrix), new Vector2(0, 0)),
                new VertexPositionTexture(Vector3.Transform(new Vector3(1, 0, 0), matrix), new Vector2(1, 1)),
                new VertexPositionTexture(Vector3.Transform(new Vector3(1, 1, 0), matrix), new Vector2(1, 0))
            };
            var indicies = new short[] { 1, 3, 0, 2 };

            context.GraphicsDevice.BlendState = BlendState.NonPremultiplied;

            effect.LoadParameterSet(context, effectParameterSet);
            foreach (var pass in effect.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                context.GraphicsDevice.DrawUserIndexedPrimitives(
                    PrimitiveType.TriangleStrip,
                    vertexes,
                    0,
                    vertexes.Length,
                    indicies,
                    0,
                    vertexes.Length - 2);
            }

            context.GraphicsDevice.BlendState = BlendState.Opaque;
        }
        private IEffectParameterSet GetEffectParameterSet(IMaterial material, ref bool changedRenderRequest, ref string changedRenderRequestBy)
        {
            if (_effectUsedForParameterSetCache == _cachedEffect &&
                changedRenderRequest == false &&
                (!_lastDidSetDiffuseTexture || _lastSetDiffuseTexture == _lastCachedDiffuseTexture?.Texture) &&
                (!_lastDidSetNormalMap || _lastSetNormalMap == _lastCachedNormalMapTexture?.Texture) &&
                (!_lastDidSetSpecularPower || _lastSetSpecularPower == _lastCachedSpecularPower) &&
                (!_lastDidSetSpecularColorMap || _lastSetSpecularColorMap == _lastCachedSpecularColorMapTexture?.Texture) &&
                (!_lastDidSetSpecularColor || _lastSetSpecularColor == _lastCachedSpecularColor) &&
                (!_lastDidSetDiffuseColor || _lastSetDiffuseColor == (material.ColorDiffuse ?? Color.Black)))
            {
                // Reuse the existing parameter set.
                return(_cachedEffectParameterSet);
            }

            changedRenderRequest    = true;
            changedRenderRequestBy += ":parameterset";

            // Create a new parameter set and cache it.
            _cachedEffectParameterSet       = _cachedEffect.CreateParameterSet();
            _effectUsedForParameterSetCache = _cachedEffect;

            _lastSetDiffuseTexture      = null;
            _lastSetNormalMap           = null;
            _lastSetSpecularPower       = null;
            _lastSetSpecularColorMap    = null;
            _lastSetSpecularColor       = null;
            _lastSetDiffuseColor        = null;
            _lastDidSetDiffuseTexture   = false;
            _lastDidSetNormalMap        = false;
            _lastDidSetSpecularPower    = false;
            _lastDidSetSpecularColorMap = false;
            _lastDidSetSpecularColor    = false;
            _lastDidSetDiffuseColor     = false;

            if (_cachedEffectParameterSet.HasSemantic <ITextureEffectSemantic>())
            {
                if (_lastCachedDiffuseTexture?.Texture != null)
                {
                    _cachedEffectParameterSet.GetSemantic <ITextureEffectSemantic>().Texture =
                        _lastCachedDiffuseTexture.Texture;
                    _lastSetDiffuseTexture    = _lastCachedDiffuseTexture.Texture;
                    _lastDidSetDiffuseTexture = true;
                }
            }

            if (_cachedEffectParameterSet.HasSemantic <INormalMapEffectSemantic>())
            {
                if (_lastCachedNormalMapTexture?.Texture != null)
                {
                    _cachedEffectParameterSet.GetSemantic <INormalMapEffectSemantic>().NormalMap =
                        _lastCachedNormalMapTexture.Texture;
                    _lastSetNormalMap    = _lastCachedNormalMapTexture.Texture;
                    _lastDidSetNormalMap = true;
                }
            }

            if (_cachedEffectParameterSet.HasSemantic <ISpecularEffectSemantic>())
            {
                if (_lastCachedSpecularPower != null)
                {
                    var semantic = _cachedEffectParameterSet.GetSemantic <ISpecularEffectSemantic>();
                    semantic.SpecularPower   = _lastCachedSpecularPower.Value;
                    _lastSetSpecularPower    = _lastCachedSpecularPower.Value;
                    _lastDidSetSpecularPower = true;

                    if (_lastCachedSpecularColorMapTexture != null)
                    {
                        semantic.SpecularColorMap   = _lastCachedSpecularColorMapTexture.Texture;
                        _lastSetSpecularColorMap    = _lastCachedSpecularColorMapTexture.Texture;
                        _lastDidSetSpecularColorMap = true;
                    }
                    else if (_lastCachedSpecularColor != null)
                    {
                        semantic.SpecularColor   = _lastCachedSpecularColor.Value;
                        _lastSetSpecularColor    = _lastCachedSpecularColor.Value;
                        _lastDidSetSpecularColor = true;
                    }
                }
            }

            if (_cachedEffectParameterSet.HasSemantic <IColorDiffuseEffectSemantic>())
            {
                var v = material.ColorDiffuse ?? Color.Black;
                _cachedEffectParameterSet.GetSemantic <IColorDiffuseEffectSemantic>().Diffuse = v;
                _lastSetDiffuseColor    = v;
                _lastDidSetDiffuseColor = true;
            }

            return(_cachedEffectParameterSet);
        }
Esempio n. 12
0
        /// <summary>
        /// Creates a render request for the model using the specified transform.
        /// </summary>
        /// <param name="renderContext">
        ///     The render context.
        /// </param>
        /// <param name="effect"></param>
        /// <param name="effectParameterSet"></param>
        /// <param name="transform">
        ///     The transform.
        /// </param>
        public IRenderRequest CreateRenderRequest(IRenderContext renderContext, IEffect effect, IEffectParameterSet effectParameterSet, Matrix transform)
        {
            if (Vertexes.Length == 0 && Indices.Length == 0)
            {
                throw new InvalidOperationException(
                    "This model does not have any vertexes or indices.  It's most " +
                    "likely been imported from an FBX file that only contains hierarchy, " +
                    "in which case there isn't anything to render.");
            }

            LoadBuffers(renderContext.GraphicsDevice);

            VertexBuffer vertexBuffer;
            if (_cachedVertexBuffers.ContainsKey(effect))
            {
                vertexBuffer = _cachedVertexBuffers[effect];
            }
            else
            {
                // Find the vertex mapping configuration for this model.
                if (_cachedModelVertexMapping == null)
                {
                    _cachedModelVertexMapping =
                        _modelRenderConfigurations.Select(x => x.GetVertexMappingToGPU(this, effect))
                            .FirstOrDefault(x => x != null);
                    if (_cachedModelVertexMapping == null)
                    {
                        throw new InvalidOperationException(
                            "No implementation of IModelRenderConfiguration could provide a vertex " +
                            "mapping for this model.  You must implement IModelRenderConfiguration " +
                            "and bind it in the dependency injection system, so that the engine is " +
                            "aware of how to map vertices in models to parameters in effects.");
                    }
                }

                var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length);
                for (var i = 0; i < Vertexes.Length; i++)
                {
                    var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i]);
                    mappedVerticies.SetValue(vertex, i);
                }

                vertexBuffer = new VertexBuffer(
                    renderContext.GraphicsDevice,
                    _cachedModelVertexMapping.VertexDeclaration,
                    Vertexes.Length,
                    BufferUsage.WriteOnly);
                vertexBuffer.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                    vertexBuffer,
                    new[] { mappedVerticies });
                _cachedVertexBuffers[effect] = vertexBuffer;
            }
            
            if (effectParameterSet.HasSemantic<IBonesEffectSemantic>())
            {
                var bonesEffectSemantic = effectParameterSet.GetSemantic<IBonesEffectSemantic>();

                foreach (var bone in _flattenedBones)
                {
                    if (bone.ID == -1)
                    {
                        continue;
                    }

                    bonesEffectSemantic.Bones[bone.ID] = bone.GetFinalMatrix();
                }
            }

            // Create the render request.
            return _renderBatcher.CreateSingleRequestFromState(
                renderContext,
                effect,
                effectParameterSet,
                vertexBuffer,
                IndexBuffer,
                PrimitiveType.TriangleList,
                renderContext.World*transform, (m, vb, ib) =>
                {
                    var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length * m.Count);
                    var mappedIndicies = new int[Indices.Length*m.Count];

                    for (var im = 0; im < m.Count; im++)
                    {
                        for (var i = 0; i < Vertexes.Length; i++)
                        {
                            var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i].Transform(m[im]));
                            mappedVerticies.SetValue(vertex, im*Vertexes.Length+i);
                        }

                        for (var i = 0; i < Indices.Length; i++)
                        {
                            mappedIndicies[im*Vertexes.Length + i] = Indices[i] + Vertexes.Length*im;
                        }
                    }

                    vb.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                        vb,
                        new[] { mappedVerticies });
                    ib.SetData(mappedIndicies);
                });
        }
        private void BlitInternal(
            IRenderContext renderContext,
            Texture2D source,
            RenderTarget2D[] destinations = null, 
            IEffect shader = null,
            IEffectParameterSet effectParameterSet = null,
            BlendState blendState = null,
            Vector2? offset = null,
            Vector2? size = null)
        {
            float destWidth, destHeight;
            if (destinations != null)
            {
                var destinationsBound = new RenderTargetBinding[destinations.Length];
                for (var i = 0; i < destinations.Length; i++)
                {
                    // Implicit cast.
                    destinationsBound[i] = destinations[i];
                }

                renderContext.PushRenderTarget(destinationsBound);
                destWidth = destinations[0].Width;
                destHeight = destinations[0].Height;
            }
            else
            {
                // TODO: renderContext.GraphicsDevice.GetRenderTargets();
                destWidth = renderContext.GraphicsDevice.PresentationParameters.BackBufferWidth;
                destHeight = renderContext.GraphicsDevice.PresentationParameters.BackBufferHeight;
            }

            offset = offset ?? new Vector2(0, 0);
            size = size ?? new Vector2(1 - offset.Value.X, 1 - offset.Value.Y);

            if (blendState == null)
            {
                blendState = BlendState.Opaque;
            }

            if (shader == null)
            {
                shader = _blitEffect;
            }

            if (effectParameterSet == null)
            {
                effectParameterSet = shader.CreateParameterSet();
            }

            if (_vertexBuffer == null)
            {
                _vertexBuffer = new VertexBuffer(renderContext.GraphicsDevice, typeof (VertexPositionNormalTexture),
                    _vertexes.Length, BufferUsage.WriteOnly);
                _vertexBuffer.SetData(_vertexes);
            }

            if (_indexBuffer == null)
            {
                _indexBuffer = new IndexBuffer(renderContext.GraphicsDevice, typeof (short), _indicies.Length,
                    BufferUsage.WriteOnly);
                _indexBuffer.SetData(_indicies);
            }

            var oldWorld = renderContext.World;
            var oldProjection = renderContext.Projection;
            var oldView = renderContext.View;

            renderContext.GraphicsDevice.BlendState = blendState;
            renderContext.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            renderContext.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
            renderContext.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

            renderContext.World = Matrix.CreateScale(destWidth, destHeight, 1);
            renderContext.Projection =
#if !PLATFORM_WINDOWS
                Matrix.CreateTranslation(-0.5f, -0.5f, 0) *
#endif
                Matrix.CreateOrthographicOffCenter(
                    destWidth * (-offset.Value.X / size.Value.X),
                    destWidth * (-offset.Value.X / size.Value.X) + destWidth / size.Value.X, 
                    destHeight * (-offset.Value.Y / size.Value.Y) + destHeight / size.Value.Y,
                    destHeight * (-offset.Value.Y / size.Value.Y),
                    0,
                    1);
            renderContext.View = Matrix.Identity;

            if (source != null && effectParameterSet != null)
            {
                var semantic = effectParameterSet.GetSemantic<ITextureEffectSemantic>();
                if (semantic.Texture != source)
                {
                    semantic.Texture = source;
                }
            }

            renderContext.GraphicsDevice.SetVertexBuffer(_vertexBuffer);
            renderContext.GraphicsDevice.Indices = _indexBuffer;
            
            shader.LoadParameterSet(renderContext, effectParameterSet);
            foreach (var pass in shader.NativeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                renderContext.GraphicsDevice.DrawIndexedPrimitives(
                    PrimitiveType.TriangleStrip,
                    0,
                    0,
                    2);
            }

            renderContext.World = oldWorld;
            renderContext.Projection = oldProjection;
            renderContext.View = oldView;

            if (destinations != null)
            {
                renderContext.PopRenderTarget();
            }
        }