用c#進行directx 3D編程:實現texture貼圖的alpha通道

來源:互聯網
上載者:User

接觸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 訊息
                }
            }
        }
    }
}

這個例子的參考價值還是很高的哦,大家要看仔細。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.