文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Silverlight C# 游戏开发:L8 材质和贴图

Silverlight C# 游戏开发:L8 材质和贴图

时间:2011-01-23  来源:nowpaper

记得有一位朋友曾经说过,3D世界总会回归到2D当中,此话很有道理,无论我们怎么构建3D世界仍然还只是在面前的屏幕上显示,而这个就是典型的3D到2D,其实,我们都被欺骗了,所有看到的都不是真正意义上的3D世界,是通过计算出来的结果,伟大的数学在这里发挥到了极致,就如Balder就是典型的通过计算的方式将3D控件渲染到Silverlight的平面上,只要对3D数学有一定的了解,都可以作出一个3D世界,说了这些有什么用呢?和贴图有很大的关系,大部分的开发者可能只是知道“贴”却对其原理一知半解,贴图的英文一般称之是Texture,贴图仅仅是另外一个子集下面的一个部分,而这个更大的集合是材质Material,要知道,世间万物并非仅仅只有纹理,它包含了诸如漫反射(diffuse)和反射(reflection)的属性,所以你仔细看某一个事物的时候,在不同的时空看到的结果不是一样。如果讨论3D世界,我想可能也非一时之事,今天咱们就之说说材质。

下面展示了一个3D世界中的典型材质赋予方式:

 

在Balder当中,Balder.Objects.Geometries对象都带有Material属性,只要对这个属性进行设置即可。

material = new Material(); Balder.Imaging.Image image = Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>("/Balder_Studio;component/Res/map01.jpg");
material.DiffuseMap = new ImageMap(image) ;
material.DiffuseMapOpacity = 1;
material.Opacity = 1;
material.DoubleSided = true;

 

上面的代码是创建一个基本的材质,然后从资源中读取一个贴图给Diffuse上,上次有位朋友问我如何在Balder中读取一个图片,其方式就是上面的方式,需要提醒的是,现在这种方法只能读取自身工程的文件,如果是外部的话,就会报错。

好吧,其实今天所有的核心就在上面的几行代码当中,下面仅仅是做了控制,现在我们弄一个UI控制界面,来操作材质和贴图使我们更加直观。

 

为了方便起见,这次用上了属性绑定,界面的XAML如下:

界面 <UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Balder_Studio" x:Class="Balder_Studio.Lesson08"
    mc:Ignorable="d"
    d:DesignHeight="441" d:DesignWidth="550">    
    <Grid>        
        <Grid x:Name="LayoutRoot" Background="White" d:IsLocked="True"/>
        <StackPanel Margin="12,8,0,0" HorizontalAlignment="Left" Height="218" VerticalAlignment="Top">
            <StackPanel Margin="0" Orientation="Horizontal" Visibility="Collapsed">
                <TextBlock Margin="0,9,0,0" FontSize="12" Width="118"><Run Text="贴图透明度"/></TextBlock>
                <Slider x:Name="SliderOpacity" Value="1" Width="140" Maximum="1" LargeChange="0.2"/>
                <TextBlock x:Name="TextValue" Text="{Binding Value, ElementName=SliderOpacity}" Margin="0,9,0,0" FontSize="12" Width="71"/>
            </StackPanel>
            <StackPanel Height="28" Orientation="Horizontal" VerticalAlignment="Bottom">
                <TextBlock Margin="0,8,0,0" FontSize="12" Width="118" Text="贴图"/>
                <ComboBox x:Name="DiffuseMapSel" Width="140">
                </ComboBox>
                <Button Content="清理贴图" Width="60" Click="Button_Click_ClearDiffuseMap"></Button>
            </StackPanel>
            <StackPanel Margin="0" Orientation="Horizontal">
                <TextBlock Margin="0,9,0,0" FontSize="12" Width="118"><Run Text="贴图"/><Run Text="透明度"/></TextBlock>
                <Slider x:Name="SliderDOpacity" Width="140" Maximum="1" Value="1" LargeChange="0.2"/>
                <TextBlock Text="{Binding Value, ElementName=SliderDOpacity}" Margin="0,9,0,0" FontSize="12" Width="71"/>
            </StackPanel>
            <StackPanel Height="28" Orientation="Horizontal" VerticalAlignment="Bottom">
                <TextBlock Margin="0,8,0,0" FontSize="12" Width="118" Text="反射贴图"/>
                <ComboBox x:Name="ReflectionMapSel" Width="140"/>
                <Button Content="清理贴图" Width="60" Click="Button_Click_ClearReflectionMap"></Button>
            </StackPanel>
            <StackPanel Margin="0" Orientation="Horizontal">
                <TextBlock Margin="0,9,0,0" FontSize="12" Width="118"><Run Text="反射"/><Run Text="贴图"/><Run Text="透明度"/></TextBlock>
                <Slider x:Name="SliderROpacity" Width="140" Maximum="1" Value="1" LargeChange="0.2"/>
                <TextBlock Text="{Binding Value, ElementName=SliderROpacity}" Margin="0,9,0,0" FontSize="12" Width="71"/>
            </StackPanel>
        </StackPanel>        
    </Grid>
</UserControl>

 

然后后台代码如下,做了简单的注释,相信各位高手会明白的。

后台代码 //////////////////////////////////////////////////
// Silvery Night
// Nowpaper原创Silverlight Balder3D文章,共同研究和探讨:)
// 
// http://www.nowpaper.net
// http://www.cnblogs.com/nowpaper
//////////////////////////////////////////////////
using System;
using System.Windows.Threading;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Balder.Math;
using Balder.Objects.Geometries;
using Balder.View;
using Balder.Lighting;
using Balder.Execution;
using System.Windows;
using System.Windows.Resources;
using Balder.Materials;
using Balder.Assets;
using System.Windows.Data;
using System.Collections.Generic;

namespace Balder_Studio
{
    public partial class Lesson08 : UserControl
    {
        //Heightmap
        Heightmap heightmap = new Heightmap();
        Camera camera = new Camera();
        //材质
        Material material = new Material();
        //贴图文件列表
        public List<string> ImageList = new List<string>()
        {
            "/Balder_Studio;component/Res/map01.jpg",
            "/Balder_Studio;component/Res/map02.jpg",
            "/Balder_Studio;component/Res/map03.jpg",
            "/Balder_Studio;component/Res/map04.jpg"
        };
        public Lesson08()
        {
            InitializeComponent();

            InitializeUILogic();

            //L1
            Game game = new Game() { Width = 600, Height = 400 };
            game.Camera = camera;
            game.Camera.Position = new Coordinate(100, 120, 150);
            game.Camera.Target = new Coordinate(0, 0, 0);
            game.Children.Add(new OmniLight()
            {
                Position = new Coordinate(0, 100, 0),
                Ambient = Colors.Transparent,
                Specular = Colors.Transparent,
                Diffuse = Colors.Transparent,
                Strength = 0.55,
            });
            //L3
            Game_Axis axis_x = new Game_Axis(new Vertex(-300, 0, 0), new Vertex(300, 0, 0), Colors.Red);
            Game_Axis axis_y = new Game_Axis(new Vertex(0, -300, 0), new Vertex(0, 300, 0), Colors.Blue);
            Game_Axis axis_z = new Game_Axis(new Vertex(0, 0, -300), new Vertex(0, 0, 300), Colors.Green);
            game.Children.Add(axis_x);
            game.Children.Add(axis_y);
            game.Children.Add(axis_z);

            
            heightmap.Dimension = new Dimension() { Width = 128, Height = 128 };
            heightmap.LengthSegments = 2;
            heightmap.HeightSegments = 2;
            heightmap.InteractionEnabled = true;

            //L8
            //从位图中创建高度图
            CreateHeightMapFormBitmap(new Uri("/Balder_Studio;component/Res/heightmap.jpg", UriKind.Relative));
            //通过ContentManager读取指定贴图
            Balder.Imaging.Image image = Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>("/Balder_Studio;component/Res/map01.jpg");
            //漫反射贴图
            material.DiffuseMap = new ImageMap(image) ;
            //漫射贴图透明度
            material.DiffuseMapOpacity = 1;
            //材质透明度
            material.Opacity = 1;
            //双面材质
            material.DoubleSided = true;
            //将材质附上
            heightmap.Material = material;

            game.Children.Add(heightmap);

            LayoutRoot.Children.Add(game);

            this.KeyDown += new System.Windows.Input.KeyEventHandler(Lesson08_KeyDown);            
        }
        //初始化UI
        private void InitializeUILogic()
        {            
            foreach (var item in ImageList)
            {
                Image image = new Image() { Width = 128, Height = 128 };
                Image image1 = new Image() { Width = 128, Height = 128 };
                image1.Source = image.Source = new BitmapImage(new Uri(item, UriKind.Relative));
                DiffuseMapSel.Items.Add(image);
                ReflectionMapSel.Items.Add(image1);
            }
            DiffuseMapSel.SelectionChanged += new SelectionChangedEventHandler(MapSel_SelectionChanged);
            ReflectionMapSel.SelectionChanged += new SelectionChangedEventHandler(MapSel_SelectionChanged);
            SliderOpacity.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged);
            SliderDOpacity.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged);
            SliderROpacity.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged);
        }        

        void MapSel_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var comboBox = sender as ComboBox;
            if(comboBox.SelectedIndex == -1)
                return;
            var filename = ImageList[comboBox.SelectedIndex];
            Balder.Imaging.Image image;
            image = Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>(filename);
            if (sender == DiffuseMapSel)
            {
                material.DiffuseMap = new ImageMap(image);
            }
            else
            {
                if (ReflectionMapSel == sender) 
                {
                    material.ReflectionMap = new ImageMap(image);
                }
            }
        }       

        void SliderOpacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (sender == SliderOpacity)
            {
                material.Opacity = e.NewValue;
            }
            else
            {
                if (sender == SliderDOpacity)
                {
                    material.DiffuseMapOpacity = e.NewValue;
                }
                else
                {
                    if (sender == SliderROpacity)
                    {
                        material.ReflectionMapOpacity = e.NewValue;
                    }
                }
            }
        }
        
        void Lesson08_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            switch (e.Key)
            {
                case System.Windows.Input.Key.W:
                    {
                        var c = camera.Target - camera.Position;
                        camera.Position += c / 10;
                        camera.Target += c / 10;
                    }
                    break;
                case System.Windows.Input.Key.S:
                    {
                        var c = camera.Target - camera.Position;
                        camera.Position -= c / 10;
                        camera.Target -= c / 10;
                    }
                    break;
            }
        }

        

        //从位图中创建高度图
        void CreateHeightMapFormBitmap(Uri uri)
        {
            BitmapImage bitmap = new BitmapImage();
            //从资源中取得BitmapStream
            StreamResourceInfo sri = Application.GetResourceStream(uri);
            bitmap.SetSource(sri.Stream);
            //生成WriteableBitmap
            WriteableBitmap writeablebitmap = new WriteableBitmap(bitmap);
            //创建高度图数组
            float[,] HeightmapArray = new float[bitmap.PixelHeight, bitmap.PixelWidth];
            //将数组拷贝到高度图数组
            for (int i = 0; i < bitmap.PixelHeight; i++)
            {
                for (int j = 0; j < bitmap.PixelWidth; j++)
                {
                    int index = bitmap.PixelWidth * i + j;
                    int pixel = writeablebitmap.Pixels[index];
                    byte[] bytes = BitConverter.GetBytes(pixel);
                    //计算:颜色越深则越低,颜色月浅则越高,50是最高的高度值
                    HeightmapArray[i, j] = ((float)(bytes[0] + bytes[1] + bytes[2]) / 3) / 255 * 50;
                }
            }
            //赋值
            heightmap.HeightmapArray = HeightmapArray;
        }

        private void Button_Click_ClearDiffuseMap(object sender, RoutedEventArgs e)
        {
            heightmap.Material.DiffuseMap = null;
        }

        private void Button_Click_ClearReflectionMap(object sender, RoutedEventArgs e)
        {
            heightmap.Material.ReflectionMap = null;
        }
    }
}

 

好了,我们下面看看效果,使用上述代码实现即可,可以点击直接下载工程浏览和测试,那么运行的预览效果如下:

工程中如果缺少Balder.dll请在这里快速下载:SL4_Balder.rar

下一篇我们介绍材质的应用,如何对模型进行贴图和更换贴图,以及贴图的属性,同时可能还结合HeightMap依据地理信息制作真实地图,那么下次再见。

推荐Silverlight游戏开发博客:深蓝色右手

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载