• Silverlight C# 游戏开发:L5 3D基本的灯光


    我们在设计和开发3D的时候最常用的就是灯光,它有的时候比摄像机还要重要,一些花哨漂亮的表现主要通过灯光实现,相比场景中只有一个的主要摄像机以外,灯光的类型和内容更加丰富,今天暂用小段时间一起研究一下Silverlight3D当中的灯光。下图是具体实现的预览效果:

    在开始之前,需要了解一下基本的灯光类型,Balder3D里有三种灯光类型,分别是OmniLight、ViewLight、DirectionalLight,如果玩过3Dmax的朋友应该是相当的熟悉,这些光的表现形式组合构成了游戏世界的绚丽多彩,没有光的世界大家可以通过最后程序实验一下,看看会如何呢。

    OmniLight:也称泛光灯或者点光,比较清楚理解,它就是一个点发出的光源

    ViewLight:有了方向和目标,除了这个方向方位之内的都不会被照亮

    DirectionalLight:是方向光,它是一个方向的照亮

    具体内容可以参考下面的图片说明来理解他们,图片截取自3DMAX,资源来源于网络。

    有一个好看的灯光,固然重要,但是我们要先学会如何控制它们,今次的代码比较多,涉及到了界面的操作,我将Lesson05代码全部贴上,我的建议还是下载源文件看比较好一些:)

    首先新建Lesson05这个控件,XAML代码如下:(下述代码使用Blend工具制作生成) 

    Lesson05.xaml
    <UserControl x:Class="Balder_Studio.Lesson05"
        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"
        mc:Ignorable
    ="d"
        d:DesignHeight
    ="300" d:DesignWidth="400">
        
        
    <Grid Background="White">
            
    <Grid x:Name="LayoutRoot"/>
            
    <StackPanel HorizontalAlignment="Left" Orientation="Vertical" VerticalAlignment="Top" Width="199" Height="132">
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Text="X轴" Width="38" Height="14"/>
                    
    <Slider Height="23" x:Name="slider_axis_x" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_x" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="38" Height="14"><Run Text="Y"/><Run Text="轴"/></TextBlock>
                    
    <Slider Height="23" x:Name="slider_axis_y" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_y" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="38" Height="14"><Run Text="Z"/><Run Text="轴"/></TextBlock>
                    
    <Slider Height="23" x:Name="slider_axis_z" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_z" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="38" Height="14" Text="亮度"/>
                    
    <Slider Height="23" x:Name="slider_Strength" Maximum="2" LargeChange="0.1" Margin="0" Width="100" Value="1" />
                    
    <TextBlock x:Name="StrengthText" Width="38" Height="14" Text="1"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="38" Height="14" Text="类型"/>
                    
    <ComboBox x:Name="LightType" Width="98"/>
                
    </StackPanel>
            
    </StackPanel>
            
    <StackPanel x:Name="LightExSetting" HorizontalAlignment="Left" Orientation="Vertical" VerticalAlignment="Top" Width="199" Height="132" Margin="198,0,-2,0" Visibility="Collapsed">
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Text="偏移/方向X" Width="64" Height="14"/>
                    
    <Slider Height="23" x:Name="slider_axis_x1" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_x1" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="64" Height="14"><Run Text="偏移/方向"/><Run Text="Y"/></TextBlock>
                    
    <Slider Height="23" x:Name="slider_axis_y1" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_y1" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal">
                    
    <TextBlock TextWrapping="Wrap" Width="64" Height="14"><Run FontFamily="Verdana, Arial, Arial Unicode MS, Lucida Sans Unicode, Lucida Grande" Text="偏移/方向"/><Run FontFamily="Verdana, Arial, Arial Unicode MS, Lucida Sans Unicode, Lucida Grande" Text="Z"/></TextBlock>
                    
    <Slider Height="23" x:Name="slider_axis_z1" SmallChange="1" Maximum="100" LargeChange="10" Margin="0" Width="100" Minimum="-100" />
                    
    <TextBlock x:Name="axis_z1" TextWrapping="Wrap" Width="38" Height="14" Text="0"/>
                
    </StackPanel>
                
    <StackPanel Orientation="Horizontal" Visibility="Collapsed">
                    
    <TextBlock TextWrapping="Wrap" Width="38" Height="14" Text="亮度"/>
                    
    <Slider Height="23" x:Name="slider_Strength1" Maximum="1" LargeChange="0.1" Margin="0" Width="100" Value="1" />
                    
    <TextBlock x:Name="StrengthText1" Width="38" Height="14" Text="1"/>
                
    </StackPanel>
            
    </StackPanel>
        
    </Grid>
    </UserControl>

    Lesson05.xaml.cs代码如下,具体实现请参照Lesson04的讲述

    Lesson05.xaml.cs
    using System;
    using System.Windows.Threading;
    using System.Windows.Controls;
    using System.Windows.Media;
    using Balder.Math;
    using Balder.Objects.Geometries;
    using Balder.View;
    using Balder.Lighting;
    using Balder.Execution;

    namespace Balder_Studio
    {
        
    public partial class Lesson05 : UserControl
        {
            
    //选择的灯光
            Light _SelectedLight = null;
            
    public Lesson05()
            {
                InitializeComponent();            
                slider_axis_x.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);
                slider_axis_y.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);
                slider_axis_z.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);
                slider_Strength.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);

                slider_axis_x1.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Offset_ValueChanged);
                slider_axis_y1.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Offset_ValueChanged);
                slider_axis_z1.ValueChanged 
    += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Offset_ValueChanged);
                
                
                OmniLight _OmniLight 
    = new OmniLight();
                ViewLight _ViewLight 
    = new ViewLight();
                DirectionalLight _DirectionalLight 
    = new DirectionalLight() {Direction=new Coordinate(-1,-1,0) };
                
    //设定在同一个默认位置
                _OmniLight.Position = _ViewLight.Position = _DirectionalLight.Position = new Coordinate(000);
                
    //最开始的时候都不会亮
                _OmniLight.IsEnabled = _ViewLight.IsEnabled = _DirectionalLight.IsEnabled = false;

                LightType.Items.Add(
    new TextBlock() { Text = "点光源", Tag = _OmniLight });
                LightType.Items.Add(
    new TextBlock() { Text = "聚光源", Tag = _ViewLight });
                LightType.Items.Add(
    new TextBlock() { Text = "方向光", Tag = _DirectionalLight });
                LightType.SelectedIndex 
    = 0;
                LightType.SelectionChanged 
    += new SelectionChangedEventHandler(LightType_SelectionChanged);

                
    #region L1 - L4的代码
                
    //L1
                Game game = new Game() { Width = 600, Height = 400 };
                game.Camera 
    = new Camera();
                game.Camera.Position 
    = new Coordinate(100120150);
                game.Camera.Target 
    = new Coordinate(000);
                
    #endregion
                game.Children.Add(_OmniLight);
                _OmniLight.IsEnabled 
    = true;
                _SelectedLight 
    = _OmniLight;
                game.Children.Add(_ViewLight);
                game.Children.Add(_DirectionalLight);
                
    #region L1 - L4的代码
                
    //L3
                Game_Axis axis_x = new Game_Axis(new Vertex(-30000), new Vertex(30000), Colors.Red);
                Game_Axis axis_y 
    = new Game_Axis(new Vertex(0-3000), new Vertex(03000), Colors.Blue);
                Game_Axis axis_z 
    = new Game_Axis(new Vertex(00-300), new Vertex(00300), Colors.Green);
                
    //L4
                Balder.Objects.Geometries.Geometry group = new Balder.Objects.Geometries.Geometry() { Name = "MeshGroup" };
                group.InteractionEnabled 
    = true;
                group.Children.Add(axis_x);
                group.Children.Add(axis_y);
                group.Children.Add(axis_z);
                
    //L2
                Mesh Teapot = new Mesh();
                Teapot.Position 
    = new Coordinate(000);

                Teapot.AssetName 
    = new Uri("/Balder_Studio;component/Res/teapot.ase", UriKind.Relative);
                
    //L4
                group.Children.Add(Teapot);
                group.Children.Add(
    new Box() { Dimension = new Coordinate(102030), Position = new Coordinate(100100), Name = "MyBox" });
                group.Children.Add(
    new Box() { Dimension = new Coordinate(103010), Position = new Coordinate(1010-100) });
                game.Children.Add(group);

                LayoutRoot.Children.Add(game);
                
    #endregion

            }
            
    #region 控制灯光的界面事件
            
    void LightType_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                
    //选择一个新的光源之时
                if (_SelectedLight != null)
                    _SelectedLight.IsEnabled 
    = false;
                _SelectedLight 
    = ((LightType.SelectedItem as TextBlock).Tag as Light);
                _SelectedLight.IsEnabled 
    = true;
                
    if (_SelectedLight is OmniLight)
                    LightExSetting.Visibility 
    = System.Windows.Visibility.Collapsed;
                
    else
                    LightExSetting.Visibility 
    = System.Windows.Visibility.Visible;
                
            }

            
    void slider_axis_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
            {
                axis_z.Text 
    = ((int)slider_axis_z.Value).ToString();
                _SelectedLight.Position.Z 
    = slider_axis_z.Value;
                axis_y.Text 
    = ((int)slider_axis_y.Value).ToString();
                _SelectedLight.Position.Y 
    = slider_axis_y.Value;
                axis_x.Text 
    = ((int)slider_axis_x.Value).ToString();
                _SelectedLight.Position.X 
    = slider_axis_x.Value;
                StrengthText.Text 
    = slider_Strength.Value.ToString();
                _SelectedLight.Strength 
    = slider_Strength.Value;
            }
            
    void slider_Offset_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
            {
                axis_z1.Text 
    = ((int)slider_axis_z1.Value).ToString();            
                axis_y1.Text 
    = ((int)slider_axis_y1.Value).ToString();            
                axis_x1.Text 
    = ((int)slider_axis_x1.Value).ToString();
                
                
    if (_SelectedLight is ViewLight)
                {
                    var l 
    = _SelectedLight as ViewLight;
                    l.XAngleOffset 
    = slider_axis_x1.Value;
                    l.YAngleOffset 
    = slider_axis_y1.Value;
                    l.ZAngleOffset 
    = slider_axis_z1.Value;
                }
                
    else
                {
                    var l 
    = _SelectedLight as DirectionalLight;
                    var X 
    = slider_axis_x1.Value / slider_axis_x1.Maximum;
                    var Y 
    = slider_axis_y1.Value / slider_axis_y1.Maximum;
                    var Z 
    = slider_axis_z1.Value / slider_axis_z1.Maximum;
                    l.Direction 
    = new Coordinate(X, Y, Z);
                }
            }

            
    #endregion
        }
    }

    我在其中加入了一些注释,希望有用:)细心的朋友可能会发现,这次没有讲解有关灯光颜色的问题,下次我专门写一篇有关颜色的部分,这样看起来更加直观,期望各位能够对Silverlight3D产生一些兴趣,加入这个开发方向上来。

    好吧下一步让我们看看运行效果,同时附送本文章的源代码点击这里下载。

    获取 Microsoft Silverlight

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

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

    free counters 

  • 相关阅读:
    用户控件
    垃圾弟弟
    如何解决“呈现控件时出错”的问题
    IE与FireFox差距
    NavigateUrl属性绑定
    table
    firefox不支持attachEvent,attach
    转 jQuery分类 
    GridView列数字、货币和日期的显示格式
    appendChild
  • 原文地址:https://www.cnblogs.com/nowpaper/p/1886439.html
Copyright © 2020-2023  润新知