用c#进行directx 3D编程:实现texture贴图的alpha通道
接触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 消息
}
}
}
}
}
这个例子的参考价值还是很高的哦,大家要看仔细。