接觸directX 3D已經有1個多月了。自己做的一個三維控制項終於完成,不過還有些讓人頭痛的bug來修改.今天給大家寫的是是現在3d裡的texture貼圖,並實現了其半透明效果。
在這個例子裡,我繪製了一個矩形,貼上了一張帶alpha通道的圖片,並繪製了一個三角形,透過貼圖可以看到此三角形。
例子的如下:
用到的圖片pic.bmp如下:
一,首先保證你機子上裝了directx,沒裝的趕緊下載去裝。
二,建立一個c#的windows應用程式,添加兩個引用Microsoft.DirectX和Microsoft.DirectX.Direct3D;
三,form1.cs中代碼為:
//--------------------------------------------------------
// Copyright (C), 2000-2008, 黃博文(flysky).
// Author: flysky Version: 1.0 Date: 2008-8-13
// Description: 實現維裡的texture貼圖,並實現了貼圖的aplpha通道
// Others: 主要繪製了一個矩形,並在此矩形上貼上一張半透明的圖片,透過此貼圖可以看到後面的三角形
//--------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;
namespace TextureTest
{
public partial class Form1 : Form
{
//繪圖裝置
Device device = null;
//材質
Microsoft.DirectX.Direct3D.Texture texture;
//要貼圖的矩形框
VertexBuffer rectangleVertexBuffer = null;
//做映襯的三角形
VertexBuffer triangleVertexBuffer = null;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 初始化繪製by flysky
/// </summary>
/// <returns></returns>
public bool InitializeGraphics()
{
try
{
// Now let's setup our D3D stuff
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
device.RenderState.ZBufferEnable = true;
InitVertexBuffer();
device.DeviceReset += new System.EventHandler(this.OnResetDevice);
device.DeviceResizing += new CancelEventHandler(this.CancelResize);
this.OnResetDevice(device, null);
return true;
}
catch (DirectXException)
{
return false;
}
}
/// <summary>
/// 重設裝置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnResetDevice(object sender, EventArgs e)
{
Device dev = (Device)sender;
dev.RenderState.CullMode = Cull.None;
//從檔案中載入材質(大家可以選取其他的圖片來比較效果,如果要實現半透明的話圖片本身要是帶alpha通道的)
texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\pic.bmp");
}
/// <summary>
/// 尺寸大小改變
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CancelResize(object sender, CancelEventArgs e)
{
e.Cancel = true;
}
/// <summary>
/// 初始化頂點緩衝by flysky 2008-8-13
/// </summary>
private void InitVertexBuffer()
{
//初始化要貼圖的矩形框頂點資料
rectangleVertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 6, device, 0, CustomVertex.PositionNormalTextured.Format, Pool.Default);
//構造個點,以構成貼圖的矩形表面
CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])rectangleVertexBuffer.Lock(0, 0);
//設定每個點的位置,法線,和Tu,Tv分量.Tu分量是貼圖的寬度位置(將貼圖的整個寬度看做為,Tu取值在和之間),Tv分量是選取貼圖的高度位置(將貼圖的整個高度看做為,Tv取值在和之間)
verts[0].Position = new Vector3(-20, -20, -20);
verts[0].Normal = new Vector3(-20, -20, -21);
verts[0].Tu = 0.0f;
verts[0].Tv = 1.0f;
verts[1].Position = new Vector3(-20, 20, -20);
verts[1].Normal = new Vector3(-20, 20, -21);
verts[1].Tu = 0.0f;
verts[1].Tv = 0.0f;
verts[2].Position = new Vector3(20, 20, -20);
verts[2].Normal = new Vector3(20, 20, -21);
verts[2].Tu = 1.0f;
verts[2].Tv = 0.0f;
verts[3].Position = new Vector3(20, -20, -20);
verts[3].Normal = new Vector3(20, -20, -21);
verts[3].Tu = 1.0f;
verts[3].Tv = 1.0f;
verts[4].Position = new Vector3(-20, -20, -20);
verts[4].Normal = new Vector3(-20, -20, -21);
verts[4].Tu = 0.0f;
verts[4].Tv = 1.0f;
verts[5].Position = new Vector3(20, 20, -20);
verts[5].Normal = new Vector3(20, 20, -21);
verts[5].Tu = 1.0f;
verts[5].Tv = 0.0f;
rectangleVertexBuffer.Unlock();
//初始化做映襯的三角形的頂點資料
triangleVertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, device, 0, CustomVertex.PositionColored.Format, Pool.Default);
CustomVertex.PositionColored[] vertxs = (CustomVertex.PositionColored[])triangleVertexBuffer.Lock(0, 0);
vertxs[0].Position = new Vector3(-10, -10, 0);
vertxs[1].Position = new Vector3(-10, 10, 0);
vertxs[2].Position = new Vector3(10, 10, 0);
for (int i = 0; i < 3; i++)
{
vertxs[i].Color = Color.Red.ToArgb();
}
triangleVertexBuffer.Unlock();
}
public void Render()
{
if (device == null)
return;
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0f, 0);
SetupCamera();
device.BeginScene();
device.RenderState.Lighting = false;
device.SetStreamSource(0, triangleVertexBuffer, 0);
device.VertexFormat = CustomVertex.PositionColored.Format;
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
//開啟裝置的alpha通道,設定混合模式
device.RenderState.AlphaBlendEnable = true;
device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
//設定材質
device.SetTexture(0, texture);
//設定材質的屬性
device.TextureState[0].ColorOperation = TextureOperation.Modulate;
device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
//設定材質的alpha通道屬性
device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse;
device.SetStreamSource(0, rectangleVertexBuffer, 0);
device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
//將材質置空並關閉alpha通道
device.SetTexture(0, null);
device.RenderState.AlphaBlendEnable = false;
device.EndScene();
device.Present();
}
//重載繪製函數
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
this.Render(); // Render on painting
}
/// <summary>
/// 設定攝像機的位置
/// </summary>
private void SetupCamera()
{
//設定世界矩陣,根據系統已耗用時間而變化
device.Transform.World = Matrix.RotationX((float)Math.Sin(Environment.TickCount / 1000.0f));
//設定攝像機的位置,它在z軸上-50處,看著原點,y軸為正方向
device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -50f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
//設定攝像機的視界,角度為度,看的最近為,看的最遠處為.不再這個視界中的影像都不會被顯示
device.Transform.Projection = Matrix.PerspectiveFovLH(((float)(float)Math.PI / 2), 1.0f, 10.0f, 200.0f);
}
}
}
四,program.cs中的代碼為:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace TextureTest
{
static class Program
{
/// <summary>
/// 應用程式的主進入點。
/// </summary>
[STAThread]
static void Main()
{
using (Form1 frm = new Form1())
{
if (!frm.InitializeGraphics()) // Initialize Direct3D
{
MessageBox.Show("Could not initialize Direct3D. This tutorial will exit.");
return;
}
frm.Show();
// While the form is still valid, render and process messages
while (frm.Created)
{
frm.Render();
Application.DoEvents(); //處理當前在訊息佇列中的所有 Windows 訊息
}
}
}
}
}
這個例子的參考價值還是很高的哦,大家要看仔細。