Sliverlight3D Shader教程1——环境光照

这篇文章其实就是XNA Shader编程教程1-环境光照在silverlight上的实现,有了Silverlight 5 3D的帮助,代码只需稍作修改就可以实现浏览器上的Web 3D。其中的原理在XNA中已经解释得很清楚,所以文中只贴出相关代码,与Silverlight 5有关的知识可参见本网站的其他文章。

首先,从Silverlight Toolkit中的Silverlight 3d Application模板生成了一个默认项目,我命名为SL1_AmbientLight。然后移除项目中的VertexPositionColorNormal.cs,导入僵尸模型Object.x,将XNA Shader编程教程1-环境光照源代码项目中的Shader.fx的内容复制到此项目中的CustomEffect.slfx中,替换原有的内容。

Cube.cs重命名为MyModel.cs,并对代码进行如下的修改:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Silverlight3dApp
{
    public class MyModel
    {
        #region 字段

        readonly Scene scene;
        readonly GraphicsDevice graphicsDevice;
        readonly Model model;      
        
        readonly SilverlightEffect effect;
        readonly SilverlightEffectParameter projectionParameter;  
        readonly SilverlightEffectParameter viewParameter;
        readonly SilverlightEffectParameter worldParameter;
        readonly SilverlightEffectParameter ambientIntensityParameter;
        readonly SilverlightEffectParameter ambientColorParameter;  
        
        #endregion

        #region 属性

        public Matrix World
        {
            set{ worldParameter.SetValue(value);}
        }

        public Matrix Projection
        {
            set { projectionParameter.SetValue (value ); }
        }

        public Matrix View
        {
            set { viewParameter.SetValue(value); }
        }

        public float AmbientIntensity
        {
            set { ambientIntensityParameter.SetValue(value); }
        }

        public Vector4 AmbientColor
        {
            set { ambientColorParameter.SetValue(value); }
        } 

        #endregion

        #region 初始化

        public MyModel(Scene scene)
        {
            this.scene = scene;
            this.graphicsDevice = scene.GraphicsDevice;
            this.effect = scene.ContentManager.Load<silverlighteffect>("CustomEffect");
            this.model = scene.ContentManager.Load<Model>("Object"); 

            // 缓存effect参数
            worldParameter = effect.Parameters["World"];
            viewParameter = effect.Parameters["View"];
            projectionParameter = effect.Parameters["Projection"];

            ambientColorParameter = effect.Parameters["AmbientColor"];
            ambientIntensityParameter = effect.Parameters["AmbientIntensity"];            
        }

        #endregion

        #region 方法

        public void Draw()
        {
            foreach (var pass in effect.CurrentTechnique.Passes)
            {
                // Apply pass
                pass.Apply();

                // 所用的僵尸模型只有一个,这个ModelMesh只有一个ModelMeshPart
                ModelMeshPart meshPart = model.Meshes[0].MeshParts[0];

                // 设置顶点缓存和索引缓存
                graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer, meshPart.VertexOffset);
                graphicsDevice.Indices = meshPart.IndexBuffer;

                // 绘制模型
                graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
            }
        }

        #endregion
    }
}

将Scene.cs的代码修改为如下所示:

using System;
using System.Windows.Controls;
using System.Windows.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Silverlight3dApp
{
    public class Scene : IDisposable
    {
        #region 字段

        readonly DrawingSurface _drawingSurface;
        readonly ContentManager contentManager;
        readonly MyModel model;

        float aspectRatio;
        double rotateCamera = 0.0f;

        #endregion

        #region 属性

        public ContentManager ContentManager
        {
            get
            {
                return contentManager;
            }
        }

        public GraphicsDevice GraphicsDevice
        {
            get
            {
                return GraphicsDeviceManager.Current.GraphicsDevice;
            }
        }

        #endregion

        #region 初始化

        public Scene(DrawingSurface drawingSurface)
        {
            _drawingSurface = drawingSurface;

            // 注册控件大小改变的事件更新长宽比
            _drawingSurface.SizeChanged += _drawingSurface_SizeChanged;

            // 获取content manager用于访问素材管道
            contentManager = new ContentManager(null)
            {
                RootDirectory = "Content"
            };

            // 初始化模型
            model = new MyModel(this);
            model.AmbientIntensity = 1.0f;
            model.AmbientColor = new Vector4(0f,100f,0f,255f);            
            model.World = Matrix.Identity; 
        }

        #endregion

        #region 方法

        void _drawingSurface_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            aspectRatio = (float)(_drawingSurface.ActualWidth / _drawingSurface.ActualHeight);
        }

        public void Draw()
        {
            // 清除后备缓存
            GraphicsDeviceManager.Current.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(0.2f, 0.2f, 0.2f, 1.0f), 1.0f, 0);

            // 计算视矩阵和投影矩阵
            rotateCamera += 30f / 1000.0;
            Matrix view = Matrix.CreateLookAt(new Vector3(5.0f * (float)Math.Cos(rotateCamera), 2, 5.0f * (float)Math.Sin(rotateCamera)), new Vector3(0, 2, 0), Vector3.Up);            
            Matrix projection = Matrix.CreatePerspectiveFieldOfView(0.85f, aspectRatio, 0.01f, 1000.0f);

            // 更新shader中的矩阵变量            
            model.View = view;
            model.Projection = projection;

            // 绘制模型
            model.Draw();
        }

        public void Dispose()
        {
            _drawingSurface.SizeChanged -= _drawingSurface_SizeChanged;
        }


        #endregion
    }
}

运行程序,得到的结果与XNA Shader编程教程1-环境光照是相同的。你可以对照两个程序的源代码,看看是如何进行移植的。

源代码下载

文件下载(已下载 2211 次)

发布时间:2012/8/20 下午11:20:49  阅读次数:7731

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号