zoukankan      html  css  js  c++  java
  • 用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 消息
                    }
                }
            }
        }
    }

    这个例子的参考价值还是很高的哦,大家要看仔细。

  • 相关阅读:
    Excel 如何在程序运行期间提示信息“正在运行中。。。请稍候 38云淡淡
    EXT学习笔记第一课
    java学习日志1
    C语言基础知识
    js所学知识点
    javascript 取最大值和最小值!
    html常用标签
    javascript4位随机数(字体都有颜色)
    marginpadding区别及bug
    数独的优化回朔算法(四)
  • 原文地址:https://www.cnblogs.com/top5/p/1584955.html
Copyright © 2011-2022 走看看