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

2016-08-20 11:07:30来源:http://nowpaper.blog.51cto.com/3893223/710920作者:nowpaper人点击


对于3D来说,主要的组成要素是:模型、灯光、摄像机,模型中的贴图部分不容忽视,贴图为模型带来生命力,在游戏开发当中非常重要,了解贴图的方式可以帮助我们作出,这一篇主要是说有关于贴图方面的内容。下面是今天的实例:




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


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




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


material=newMaterial(); Balder.Imaging.Imageimage=Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>("/Balder_Studio;component/Res/map01.jpg"); material.DiffuseMap=newImageMap(image); material.DiffuseMapOpacity=1; material.Opacity=1; material.DoubleSided=true;
上面的代码是创建一个基本的材质,然后从资源中读取一个贴图给Diffuse上,上次有位朋友问我如何在Balder中读取一个图片,其方式就是上面的方式,需要提醒的是,现在这种方法只能读取自身工程的文件,如果是外部的话,就会报错。

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




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


<UserControlxmlns="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> <Gridx:Name="LayoutRoot"Background="White"d:IsLocked="True"/><StackPanelMargin="12,8,0,0"HorizontalAlignment="Left"Height="218"VerticalAlignment="Top"><StackPanelMargin="0"Orientation="Horizontal"Visibility="Collapsed"><TextBlockMargin="0,9,0,0"FontSize="12"Width="118"><RunText="贴图透明度"/></TextBlock><Sliderx:Name="SliderOpacity"Value="1"Width="140"Maximum="1"LargeChange="0.2"/><TextBlockx:Name="TextValue"Text="{BindingValue,ElementName=SliderOpacity}"Margin="0,9,0,0"FontSize="12"Width="71"/></StackPanel><StackPanelHeight="28"Orientation="Horizontal"VerticalAlignment="Bottom"><TextBlockMargin="0,8,0,0"FontSize="12"Width="118"Text="贴图"/><ComboBoxx:Name="DiffuseMapSel"Width="140"></ComboBox><ButtonContent="清理贴图"Width="60"Click="Button_Click_ClearDiffuseMap"></Button></StackPanel><StackPanelMargin="0"Orientation="Horizontal"><TextBlockMargin="0,9,0,0"FontSize="12"Width="118"><RunText="贴图"/><RunText="透明度"/></TextBlock><Sliderx:Name="SliderDOpacity"Width="140"Maximum="1"Value="1"LargeChange="0.2"/><TextBlockText="{BindingValue,ElementName=SliderDOpacity}"Margin="0,9,0,0"FontSize="12"Width="71"/></StackPanel><StackPanelHeight="28"Orientation="Horizontal"VerticalAlignment="Bottom"><TextBlockMargin="0,8,0,0"FontSize="12"Width="118"Text="反射贴图"/><ComboBoxx:Name="ReflectionMapSel"Width="140"/><ButtonContent="清理贴图"Width="60"Click="Button_Click_ClearReflectionMap"></Button></StackPanel><StackPanelMargin="0"Orientation="Horizontal"><TextBlockMargin="0,9,0,0"FontSize="12"Width="118"><RunText="反射"/><RunText="贴图"/><RunText="透明度"/></TextBlock><Sliderx:Name="SliderROpacity"Width="140"Maximum="1"Value="1"LargeChange="0.2"/><TextBlockText="{BindingValue,ElementName=SliderROpacity}"Margin="0,9,0,0"FontSize="12"Width="71"/></StackPanel></StackPanel> </Grid></UserControl>

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


后台代码

////////////////////////////////////////////////// //SilveryNight //Nowpaper原创SilverlightBalder3D文章,共同研究和探讨:) // //http://www.nowpaper.net //http://www.cnblogs.com/nowpaper ////////////////////////////////////////////////// usingSystem; usingSystem.Windows.Threading; usingSystem.Windows.Controls; usingSystem.Windows.Media; usingSystem.Windows.Media.Imaging; usingBalder.Math; usingBalder.Objects.Geometries; usingBalder.View; usingBalder.Lighting; usingBalder.Execution; usingSystem.Windows; usingSystem.Windows.Resources; usingBalder.Materials; usingBalder.Assets; usingSystem.Windows.Data; usingSystem.Collections.Generic; namespaceBalder_Studio { publicpartialclassLesson08:UserControl { //Heightmap Heightmapheightmap=newHeightmap(); Cameracamera=newCamera(); //材质 Materialmaterial=newMaterial(); //贴图文件列表 publicList<string>ImageList=newList<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" }; publicLesson08() { InitializeComponent(); InitializeUILogic(); //L1 Gamegame=newGame(){Width=600,Height=400}; game.Camera=camera; game.Camera.Position=newCoordinate(100,120,150); game.Camera.Target=newCoordinate(0,0,0); game.Children.Add(newOmniLight() { Position=newCoordinate(0,100,0), Ambient=Colors.Transparent, Specular=Colors.Transparent, Diffuse=Colors.Transparent, Strength=0.55, }); //L3 Game_Axisaxis_x=newGame_Axis(newVertex(-300,0,0),newVertex(300,0,0),Colors.Red); Game_Axisaxis_y=newGame_Axis(newVertex(0,-300,0),newVertex(0,300,0),Colors.Blue); Game_Axisaxis_z=newGame_Axis(newVertex(0,0,-300),newVertex(0,0,300),Colors.Green); game.Children.Add(axis_x); game.Children.Add(axis_y); game.Children.Add(axis_z);heightmap.Dimension=newDimension(){Width=128,Height=128}; heightmap.LengthSegments=2; heightmap.HeightSegments=2; heightmap.InteractionEnabled=true; //L8 //从位图中创建高度图 CreateHeightMapFormBitmap(newUri("/Balder_Studio;component/Res/heightmap.jpg",UriKind.Relative)); //通过ContentManager读取指定贴图 Balder.Imaging.Imageimage=Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>("/Balder_Studio;component/Res/map01.jpg"); //漫反射贴图 material.DiffuseMap=newImageMap(image); //漫射贴图透明度 material.DiffuseMapOpacity=1; //材质透明度 material.Opacity=1; //双面材质 material.DoubleSided=true; //将材质附上 heightmap.Material=material; game.Children.Add(heightmap); LayoutRoot.Children.Add(game); this.KeyDown+=newSystem.Windows.Input.KeyEventHandler(Lesson08_KeyDown); } //初始化UI privatevoidInitializeUILogic() { foreach(variteminImageList) { Imageimage=newImage(){Width=128,Height=128}; Imageimage1=newImage(){Width=128,Height=128}; imageimage1.Source=image.Source=newBitmapImage(newUri(item,UriKind.Relative)); DiffuseMapSel.Items.Add(image); ReflectionMapSel.Items.Add(image1); } DiffuseMapSel.SelectionChanged+=newSelectionChangedEventHandler(MapSel_SelectionChanged); ReflectionMapSel.SelectionChanged+=newSelectionChangedEventHandler(MapSel_SelectionChanged); SliderOpacity.ValueChanged+=newRoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged); SliderDOpacity.ValueChanged+=newRoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged); SliderROpacity.ValueChanged+=newRoutedPropertyChangedEventHandler<double>(SliderOpacity_ValueChanged); } voidMapSel_SelectionChanged(objectsender,SelectionChangedEventArgse) { varcomboBox=senderasComboBox; if(comboBox.SelectedIndex==-1) return; varfilename=ImageList[comboBox.SelectedIndex]; Balder.Imaging.Imageimage; image=Runtime.Instance.ContentManager.Load<Balder.Imaging.Image>(filename); if(sender==DiffuseMapSel) { material.DiffuseMap=newImageMap(image); } else { if(ReflectionMapSel==sender) { material.ReflectionMap=newImageMap(image); } } } voidSliderOpacity_ValueChanged(objectsender,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; } } } }voidLesson08_KeyDown(objectsender,System.Windows.Input.KeyEventArgse) { switch(e.Key) { caseSystem.Windows.Input.Key.W: { varc=camera.Target-camera.Position; camera.Position+=c/10; camera.Target+=c/10; } break; caseSystem.Windows.Input.Key.S: { varc=camera.Target-camera.Position; camera.Position-=c/10; camera.Target-=c/10; } break; } }//从位图中创建高度图 voidCreateHeightMapFormBitmap(Uriuri) { BitmapImagebitmap=newBitmapImage(); //从资源中取得BitmapStream StreamResourceInfosri=Application.GetResourceStream(uri); bitmap.SetSource(sri.Stream); //生成WriteableBitmap WriteableBitmapwriteablebitmap=newWriteableBitmap(bitmap); //创建高度图数组 float[,]HeightmapArray=newfloat[bitmap.PixelHeight,bitmap.PixelWidth]; //将数组拷贝到高度图数组 for(inti=0;i<bitmap.PixelHeight;i++) { for(intj=0;j<bitmap.PixelWidth;j++) { intindex=bitmap.PixelWidth*i+j; intpixel=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; } privatevoidButton_Click_ClearDiffuseMap(objectsender,RoutedEventArgse) { heightmap.Material.DiffuseMap=null; } privatevoidButton_Click_ClearReflectionMap(objectsender,RoutedEventArgse) { heightmap.Material.ReflectionMap=null; } } }
好了,我们下面看看效果,使用上述代码实现即可,可以点击直接下载工程浏览和测试,那么运行的预览效果如下:


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


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


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台