DirectX 3D紋理

紋理就是3D模型外表面上的圖案。在3D場景中紋理極大地增加了物體的真實性。紋理的本質是把平面圖形貼到3D物體表面。在Direct3D中紋理的x和y座標一般稱爲Tu和Tv座標,紋理座標範圍都是0.0-1.0。如果知道一個面的頂點座標,使面的頂點座標和句型圖片紋理座標相對應,就可以將這些二維圖片貼到3D圖形表面。在Direct 3D中Texture類定義紋理。

如果希望爲牆壁貼上瓷磚,可以只繪製一個瓷磚的平面圖形,然後把瓷磚圖形自動平鋪到牆壁上。這裏運用了Direct 3D默認的尋址模式TextureAddress.Wrap,如果紋理的x座標大於1,例如爲n,表示圖片沿X軸方向重複貼圖n次。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace 牆壁貼瓷磚
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        VertexBuffer vertexBuffer1 = null;
        Texture texture = null;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏顯示,在一個窗口顯示
                presentParams.SwapEffect = SwapEffect.Discard;		 //後備緩存交換的方式
                presentParams.EnableAutoDepthStencil = true;			 //允許使用自動深度模板測試
                //深度緩衝區單元爲16位二進制數
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立設備類對象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //設置設備重置事件(device.DeviceReset)事件函數爲this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定義方法,初始化Device的工作放到這個方法中
                this.OnResetDevice(device, null);//調用設備重置事件(device.DeviceReset)事件函數
            }		//設備重置事件函數要設置Device參數,初始函數中必須調用該函數
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            vertexBuffer1 = new VertexBuffer(typeof(CustomVertex.PositionTextured), 6, dev, 0, CustomVertex.PositionTextured.Format, Pool.Default);
            vertexBuffer1.Created += new EventHandler(vertexBuffer1_Created);
            this.vertexBuffer1_Created(vertexBuffer1, null);
            texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p2.bmp");
        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.CullMode = Cull.None;		//取消背面剔除
            dev.RenderState.Lighting = false;			//取消燈光
            SetupMatrices();		//在程序運行期間,Device的3個變換不改變,因此放在此處

        }

        public void Render()		//渲染方法,本方法沒有任何渲染代碼,可認爲是渲染方法的框架
        {
            if (device == null) //如果未建立設備對象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.LightCoral, 1.0f, 0);
            device.BeginScene();//開始渲染
            SetupMatrices();
            device.SetTexture(0, texture);	//爲Device類對象device增加使用的第0個紋理
            device.SetStreamSource(0, vertexBuffer1, 0);
            device.VertexFormat = CustomVertex.PositionTextured.Format;
            device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
            device.EndScene();		//渲染結束
            device.Present();		//更新顯示區域,把後備緩存的D圖形送到圖形卡的顯存中顯示

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        void vertexBuffer1_Created(object sender, EventArgs e)
        {
            CustomVertex.PositionTextured[] verts =
            (CustomVertex.PositionTextured[])vertexBuffer1.Lock(0, 0);//牆壁
            verts[0].Position = new Vector3(-2.0f, -2.0f, 2.0f);	  //頂點0位置
            verts[0].Tu = 0.0f;    	  	//頂點0紋理座標Tu
            verts[0].Tv = 10.0f;
            verts[1].Position = new Vector3(-2.0f, 2.0f, 2.0f);	  	  //頂點1位置
            verts[1].Tu = 0.0f;    	  	//頂點1紋理座標Tu
            verts[1].Tv = 0.0f;
            verts[2].Position = new Vector3(2.0f, 2.0f, 2.0f);	      //頂點2位置
            verts[2].Tu = 10.0f;    	//頂點2紋理座標Tu
            verts[2].Tv = 0.0f;
            verts[3].Position = new Vector3(-2.0f, -2.0f, 2.0f);	  //頂點3位置
            verts[3].Tu = 0.0f;    	  	//頂點3紋理座標Tu
            verts[3].Tv = 10.0f;
            verts[4].Position = new Vector3(2.0f, 2.0f, 2.0f);	  	  //頂點4位置
            verts[4].Tu = 10.0f;    	//頂點4紋理座標Tu
            verts[4].Tv = 0.0f;
            verts[5].Position = new Vector3(2.0f, -2.0f, 2.0f);	      //頂點5位置
            verts[5].Tu = 10.0f;    	//頂點5紋理座標Tu
            verts[5].Tv = 10.0f;
            vertexBuffer1.Unlock();

        }

        private void SetupMatrices()		//修改Device的3個變換
        {
            device.Transform.World = Matrix.RotationY(0);	//世界變換矩陣
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -4.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 100.0f);	//投影變換矩陣
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}


爲有光照的空心圓柱增加紋理,此時還需要考慮光照的影響。Device類對象的TextureState數組記錄了每一個紋理的狀態,允許多層紋理,數組的索引值爲0~7,其屬性ColorOperation記錄了該元素所代表的紋理圖片顏色和其他參數(e.g.光照顏色)的混合方法;屬性ColorArgument1和ColorArgument2用來指定屬性ColorOperation使用的參數

實現如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace 爲空心圓柱增加紋理
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        VertexBuffer vertexBuffer = null;
        Material mtrl;
        Texture texture = null;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏顯示,在一個窗口顯示
                presentParams.SwapEffect = SwapEffect.Discard;		 //後備緩存交換的方式
                presentParams.EnableAutoDepthStencil = true;			 //允許使用自動深度模板測試
                //深度緩衝區單元爲16位二進制數
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立設備類對象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //設置設備重置事件(device.DeviceReset)事件函數爲this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定義方法,初始化Device的工作放到這個方法中
                this.OnResetDevice(device, null);//調用設備重置事件(device.DeviceReset)事件函數
            }		//設備重置事件函數要設置Device參數,初始函數中必須調用該函數
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;			//注意陰影部分
            vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 100, dev,
            Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
            this.OnCreateVertexBuffer(vertexBuffer, null);
            mtrl = new Material();
            mtrl.Diffuse = System.Drawing.Color.Yellow;		//物體的顏色
            mtrl.Ambient = System.Drawing.Color.Red;			//反射環境光的顏色
            texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p1.JPG");

        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.CullMode = Cull.None;				//取消背面剔除
            device.RenderState.ZBufferEnable = true;			//打開Z緩衝
            device.RenderState.Lighting = true;				//打開燈光
            SetupLights();				//設置燈光

        }

        public void Render()		//渲染方法,本方法沒有任何渲染代碼,可認爲是渲染方法的框架
        {
            if (device == null) 	//如果未建立設備對象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            SetupMatrices();
            device.BeginScene();		//開始渲染


            device.SetTexture(0, texture);
            device.TextureState[0].ColorOperation = TextureOperation.Modulate;
            device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;//紋理顏色
            device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;//光照顏色
            device.TextureState[0].AlphaOperation = TextureOperation.Disable;
            device.SetStreamSource(0, vertexBuffer, 0);
            device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, (4 * 25) - 2);
            device.EndScene();//渲染結束
            device.Present();//更新顯示區域,把後備緩存的D圖形送到圖形卡的顯存中顯示

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        public void OnCreateVertexBuffer(object sender, EventArgs e)
        {
            CustomVertex.PositionNormalTextured[] verts =
                        (CustomVertex.PositionNormalTextured[])vertexBuffer.Lock(0, 0);
            for (int i = 0; i < 50; i++)
            {
                float theta = (float)(2 * Math.PI * i) / 49;
                verts[2 * i].Position = new Vector3((float)Math.Sin(theta), -1, (float)Math.Cos(theta));
                verts[2 * i].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
                verts[2 * i].Tu = ((float)i) / (50 - 1);
                verts[2 * i].Tv = 1.0f;
                verts[2 * i + 1].Position = new Vector3((float)Math.Sin(theta), 1, (float)Math.Cos(theta));
                verts[2 * i + 1].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
                verts[2 * i + 1].Tu = ((float)i) / (50 - 1);
                verts[2 * i + 1].Tv = 0.0f;
            }
            vertexBuffer.Unlock();
        }

        private void SetupMatrices()
        {
            device.Transform.World = Matrix.RotationAxis(new Vector3((float)Math.Cos(Environment.TickCount / 250.0f), 1, (float)Math.Sin(Environment.TickCount / 250.0f)), Environment.TickCount / 3000.0f);
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 3.0f, -5.0f),
                        new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 100.0f);
        }

        private void SetupLights()
        {
            device.Material = mtrl;
            device.Lights[0].Type = LightType.Directional;
            device.Lights[0].Diffuse = System.Drawing.Color.White;
            device.Lights[0].Direction = new Vector3((float)Math.Cos(Environment.TickCount / 250.0f),
                                    1.0f, (float)Math.Sin(Environment.TickCount / 250.0f));
            device.Lights[0].Enabled = true;
            device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x404040);
        }

        private void Form1_load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}

可以爲上面的空心圓柱添加背景,所謂的背景就是固定不動的圖像,也就是在進行三個變換時,背景位置不變。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace 空心圓柱添加背景
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        VertexBuffer vertexBuffer = null;
        Material mtrl;
        Texture texture = null;
        VertexBuffer vertexBuffer1 = null;
        Texture texture1 = null;

        public Form1()
        {
            InitializeComponent();
        }

        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏顯示,在一個窗口顯示
                presentParams.SwapEffect = SwapEffect.Discard;		 //後備緩存交換的方式
                presentParams.EnableAutoDepthStencil = true;			 //允許使用自動深度模板測試
                //深度緩衝區單元爲16位二進制數
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立設備類對象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //設置設備重置事件(device.DeviceReset)事件函數爲this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定義方法,初始化Device的工作放到這個方法中
                this.OnResetDevice(device, null);//調用設備重置事件(device.DeviceReset)事件函數
            }		//設備重置事件函數要設置Device參數,初始函數中必須調用該函數
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;			//陰影部分是所作的修改
            vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 100, dev,
            Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
            this.OnCreateVertexBuffer(vertexBuffer, null);
            mtrl = new Material();
            mtrl.Diffuse = System.Drawing.Color.Yellow;		//物體的顏色
            mtrl.Ambient = System.Drawing.Color.Red;			//反射環境光的顏色
            texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p1.JPG");
            vertexBuffer1 = new VertexBuffer(typeof(CustomVertex.TransformedTextured), 4, dev, 0, CustomVertex.TransformedTextured.Format, Pool.Default);
            vertexBuffer1.Created += new EventHandler(vertexBuffer1_Created);
            this.vertexBuffer1_Created(vertexBuffer1, null);
            texture1 = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p2.jpg");
        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.CullMode = Cull.None;				//取消背面剔除
            device.RenderState.ZBufferEnable = true;			//打開Z緩衝
            device.RenderState.Lighting = true;				//打開燈光
            SetupLights();

        }

        public void Render()		//渲染方法,本方法沒有任何渲染代碼,可認爲是渲染方法的框架
        {
            if (device == null) 					//如果未建立設備對象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.WhiteSmoke, 1.0f, 0);
            SetupMatrices();
            device.BeginScene();					//開始渲染
            device.SetTexture(0, texture1);			//這段代碼必須放在渲染圓柱體代碼之前
            device.RenderState.ZBufferEnable = false;
            device.SetStreamSource(0, vertexBuffer1, 0);
            device.VertexFormat = CustomVertex.TransformedTextured.Format;
            device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
            device.RenderState.ZBufferEnable = true;
            device.SetTexture(0, texture);
            device.TextureState[0].ColorOperation = TextureOperation.Modulate;
            device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
            device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
            device.TextureState[0].AlphaOperation = TextureOperation.Disable;
            device.SetStreamSource(0, vertexBuffer, 0);
            device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, (4 * 25) - 2);
            device.EndScene();		//渲染結束
            device.Present();		//更新顯示區域,把後備緩存的D圖形送到圖形卡的顯存中顯示


        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }

        public void OnCreateVertexBuffer(object sender, EventArgs e)
        {
            CustomVertex.PositionNormalTextured[] verts =
                        (CustomVertex.PositionNormalTextured[])vertexBuffer.Lock(0, 0);
            for (int i = 0; i < 50; i++)
            {
                float theta = (float)(2 * Math.PI * i) / 49;
                verts[2 * i].Position = new Vector3((float)Math.Sin(theta), -1, (float)Math.Cos(theta));
                verts[2 * i].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
                verts[2 * i].Tu = ((float)i) / (50 - 1);
                verts[2 * i].Tv = 1.0f;
                verts[2 * i + 1].Position = new Vector3((float)Math.Sin(theta), 1, (float)Math.Cos(theta));
                verts[2 * i + 1].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
                verts[2 * i + 1].Tu = ((float)i) / (50 - 1);
                verts[2 * i + 1].Tv = 0.0f;
            }
            vertexBuffer.Unlock();
        }

        private void SetupMatrices()
        {
            device.Transform.World = Matrix.RotationAxis(new Vector3((float)Math.Cos(Environment.TickCount / 250.0f), 1, (float)Math.Sin(Environment.TickCount / 250.0f)), Environment.TickCount / 3000.0f);
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 3.0f, -5.0f),
                        new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 100.0f);
        }

        private void SetupLights()
        {
            device.Material = mtrl;
            device.Lights[0].Type = LightType.Directional;
            device.Lights[0].Diffuse = System.Drawing.Color.White;
            device.Lights[0].Direction = new Vector3((float)Math.Cos(Environment.TickCount / 250.0f),
                                    1.0f, (float)Math.Sin(Environment.TickCount / 250.0f));
            device.Lights[0].Enabled = true;
            device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x404040);
        }

        void vertexBuffer1_Created(object sender, EventArgs e)
        {
            CustomVertex.TransformedTextured[] verts =
        (CustomVertex.TransformedTextured[])vertexBuffer1.Lock(0, 0);
            verts[0].Position = new Vector4(0, 0, 0, 1);
            verts[0].Tu = 0.0f;
            verts[0].Tv = 0.0f;
            verts[1].Position = new Vector4(this.Width, 0, 0, 1);
            verts[1].Tu = 1.0f;
            verts[1].Tv = 0.0f;
            verts[2].Position = new Vector4(this.Width, this.Height, 0, 1);
            verts[2].Tu = 1.0f;
            verts[2].Tv = 1.0f;
            verts[3].Position = new Vector4(0, this.Height, 0, 1);
            verts[3].Tu = 0.0f;
            verts[3].Tv = 1.0f;
            vertexBuffer1.Unlock();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }

    }
}


爲正方形增加紋理,如果正方形尺寸較大,而紋理的分辨率較低,這時紋理圖像可能要出現馬賽克,如果正方形尺寸較大,而紋理圖片分辨率較高時,此時要縮小圖形以適應正方形尺寸。爲了解決這個問題,可以使用紋理濾波器,紋理濾波器的本質是數學差值。3D圖形的表面可以貼多個圖片,稱爲多層紋理。爲正方形增加兩個紋理,一個是一面不規則的牆的圖案,另一個是一個光影。多紋理的混合需要一個是半透明的,兩個混合後纔有效果,通過設置紋理0的混合方法,再設置紋理1的混合方法,然後再把紋理0圖案的顏色設置爲半透明的即可。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace 正方形添加多紋理
{
    public partial class Form1 : Form
    {
        private Device device = null;
        bool pause = false;
        VertexBuffer vertexBuffer1 = null;
        Texture texture = null;
        Texture texture1 = null;
        public Form1()
        {
            InitializeComponent();
        }
        public bool InitializeGraphics()
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;				//不是全屏顯示,在一個窗口顯示
                presentParams.SwapEffect = SwapEffect.Discard;		 //後備緩存交換的方式
                presentParams.EnableAutoDepthStencil = true;			 //允許使用自動深度模板測試
                //深度緩衝區單元爲16位二進制數
                presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                device = new Device(0, DeviceType.Hardware, this, 	 //建立設備類對象
          CreateFlags.SoftwareVertexProcessing, presentParams);
                //設置設備重置事件(device.DeviceReset)事件函數爲this.OnResetDevice
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);//自定義方法,初始化Device的工作放到這個方法中
                this.OnResetDevice(device, null);//調用設備重置事件(device.DeviceReset)事件函數
            }		//設備重置事件函數要設置Device參數,初始函數中必須調用該函數
            catch (DirectXException)
            {
                return false;
            }
            return true;
        }

        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;   	//注意有陰影部分
            vertexBuffer1 = new VertexBuffer(typeof(CustomVertex.PositionTextured), 6, dev, 0,
         CustomVertex.PositionTextured.Format, Pool.Default);
            vertexBuffer1.Created += new EventHandler(vertexBuffer1_Created);
            this.vertexBuffer1_Created(vertexBuffer1, null);
            texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p1.bmp");
            texture1 = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\..\p2.bmp");

        }

        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;
            dev.RenderState.CullMode = Cull.None;		//取消背面剔除
            dev.RenderState.Lighting = false;			//取消燈光
            SetupMatrices();		//在程序運行期間,Device的3個變換不改變,因此放在此處
            device.SamplerState[0].MagFilter = TextureFilter.Linear;	//使用線性濾波器


        }

        public void Render()		//渲染方法,本方法沒有任何渲染代碼,可認爲是渲染方法的框架
        {
            if (device == null) 		//如果未建立設備對象,退出
                return;
            if (pause)
                return;
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Blue, 1.0f, 0);
            device.BeginScene();				//開始渲染	
            device.SetTexture(0, texture);		//索引號爲0的紋理是牆壁圖案
            device.SetTexture(1, texture1);		//索引號爲1的紋理是光影圖案
            device.TextureState[0].TextureCoordinateIndex = 0;	//紋理座標Tu和Tv初始值
            device.TextureState[1].TextureCoordinateIndex = 0;
            device.SamplerState[0].MagFilter = TextureFilter.Linear;  //放大圖形使用線形濾波器
            device.SamplerState[1].MagFilter = TextureFilter.Linear;  //縮小圖形使用線形濾波器
            device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
            device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
            //以下兩句設置紋理0爲半透明的,和紋理1混合後能看到混合效果,透明效果見10.2節
            device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
            device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
            device.TextureState[1].ColorOperation = TextureOperation.Modulate;
            device.TextureState[1].ColorArgument1 = TextureArgument.TextureColor;
            device.TextureState[1].ColorArgument2 = TextureArgument.Current;
            //device.TextureState[1].AlphaOperation = TextureOperation.Disable;
            //device.TextureState[2].ColorOperation = TextureOperation.Disable;
            //device.TextureState[2].AlphaOperation = TextureOperation.Disable;
            device.SetStreamSource(0, vertexBuffer1, 0);
            device.VertexFormat = CustomVertex.PositionTextured.Format;
            device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
            device.EndScene();		//渲染結束
            device.Present();		//更新顯示區域,把後備緩存的圖形送到圖形卡的顯存中顯示

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.Render();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
        }
        void vertexBuffer1_Created(object sender, EventArgs e)
        {
            CustomVertex.PositionTextured[] verts =
            (CustomVertex.PositionTextured[])vertexBuffer1.Lock(0, 0);		//牆壁
            verts[0].Position = new Vector3(-2.0f, -2.0f, 2.0f);	  	//頂點0位置
            verts[0].Tu = 0.0f;    	  //頂點0紋理座標Tu
            verts[0].Tv = 1.0f;
            verts[1].Position = new Vector3(-2.0f, 2.0f, 2.0f);	  	  		//頂點1位置
            verts[1].Tu = 0.0f;    	  //頂點1紋理座標Tu
            verts[1].Tv = 0.0f;
            verts[2].Position = new Vector3(2.0f, 2.0f, 2.0f);	      		//頂點2位置
            verts[2].Tu = 1.0f;    	  //頂點2紋理座標Tu
            verts[2].Tv = 0.0f;
            verts[3].Position = new Vector3(-2.0f, -2.0f, 2.0f);	  		//頂點3位置
            verts[3].Tu = 0.0f;    	  //頂點3紋理座標Tu
            verts[3].Tv = 1.0f;
            verts[4].Position = new Vector3(2.0f, 2.0f, 2.0f);	  	  		//頂點4位置
            verts[4].Tu = 1.0f;    	  //頂點4紋理座標Tu
            verts[4].Tv = 0.0f;
            verts[5].Position = new Vector3(2.0f, -2.0f, 2.0f);	      		//頂點5位置
            verts[5].Tu = 1.0f;    	  //頂點5紋理座標Tu
            verts[5].Tv = 1.0f;
            vertexBuffer1.Unlock();
        }

        private void SetupMatrices()		//修改Device的3個變換
        {
            device.Transform.World = Matrix.RotationY(0);	//世界變換矩陣
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -4.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 100.0f);	//投影變換矩陣
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeGraphics();
            this.Show();
            Render();
        }
    }
}

在程序運行時有時需要多個不同分辨率的同一張圖片,以適合大小不同的物體表面貼圖用,當物體離觀察者近的適合使用高質量的紋理,而物體離觀察者遠的時候使用低分辨率的紋理。這時就需要使用多級漸進紋理來控制渲染時紋理的質量,但是這樣做的代價是會吃掉更多的內存。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章