【翻译】Managed DirectX(第十一章)

[原创]Managed DirectX 基础使用教程(零) hangtao_me@yahoo.com.cn        由于下学期的毕业设计,最近开始研究起了.NET平台下的DirectX.本来是不打算用DirectX的,因为我不会DirectX - -||。但是DEMO出来后,发现用C#的GDI+绘图的效率是如此低下。最后不得不得硬着头皮上DirectX。而且是资料相对较少的Managed DirectX(托管版DX)。很多都是直接 阅读详情

第十一章 可编程渲染管道以及高级着色语言入门

翻译:clayman
clayman_joe@yahoo.com.cn
仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^

至今为止,我们都在使用固定功能的管道(fixed-function pipeline)进行渲染。回到那段古老的日子(DirectX 8.0之前),这是唯一渲染物体的方法。固定功能的渲染管道本质上就是一系列用来控制如何渲染特定类型数据的规则以及行为。虽然在某些方面这已经够用了,但却限制了许多开发人员使用高级功能的能力。举个例子,使用固定功能的管道,灯光是根据每个顶点而不是每个象素来计算的。由于渲染管道是“固定”的,因此根本没欧办法来改变许多渲染选项,刚才说的灯光就是一个例子。

DirectX 8.0带来了可编程的管道。随着这个版本带来的革命性功能,开发人员几乎可以控制管道的所有方面。他们可以使用称为顶点着色器(Vertex Shaders)的功能控制顶点的处理过程,使用像素着色器(Pixel Shader)控制像素的处理。这些着色程序相当强大,但使用起来却不是太方便,因为这些程序都是使用汇编语言来写的。

在DirectX 9中发布了高级着色语言(High Level Shader Language, HLSL)。HLSL是一种和C很类似的语言,可以编译为着色器代码,却相当的利于开发人员阅读、维护以及编写。在带来了方便的同时,保留了可编程管道的强大力量。这一章,我们将讨论HLSL的基本内容,包括:

n          使用可编程管道

n          顶点变换

n          使用像素着色器

 

使用可编程管道渲染三角形

         说了这么多,到底什么是“固定功能的管道”呢?固定功能的管道控制了一切:如何渲染顶点,如何对他们进行变换,如何照亮物体,几乎包含了所有方面。当你设置device的顶点格式时,实际上是在告诉device根据所给的格式,使用特定方法来渲染这些顶点。

         这样设计,最大的缺点就在于对于图形卡所支持的每一种功能,都必须设计和实现一个固定功能的API与之相对应。但是,由于如今显卡的发展速度之快(甚至超过了CPU的发展速度),原来的API可能很快就过时了。就算设计了数量庞大并且难懂的API来完成这些任务,还有一个潜在的问题:开发者不知道使用这些API时,到底发生了什么。对程序员来说,获得完全的控制才是他们想要的 。

         本书的第一个例子讨论了如何显示一个旋转的三角形。现在来看看使用可编程管道如何来完成同样的任务。创建一个新工程,做好各种所需的准备,添加如下变量:

private VertexBuffer vb = null;

private Effect effect = null;

private VertexDeclaration decl = null;

private Matrix worldMatrix;

private Matrix viewMatrix;

private Matrix projMatrix;

private float angle = 0.0f ;

         自然,使用顶点缓冲来储存顶点数据。由于不使用device进行变换,所以需要为可编程管道单独保存这些变换矩阵。第二、三个变量则是新内容。Effect对象就是用来处理HLSL的主要对象。Vertex Declaration类则与固定功能管道中的VertexFormat枚举类似。他会告诉Direct3D运行时应该从顶点缓冲中读取的数据大小和类型。

         由于这个技术会使用一些相对比较新的图形卡功能,完全有可能你的显卡不支持它。如果这样,那么你将不得不使用DirectX SDK中的参考设备(reference device)。参考设备将以纯软件的方式来实现所有API,可能会相当慢。这一次,初始化的代码将复杂一点

public bool InitializeGraphics()

{

     PresentParameters presentParams = new PresentParameters();

     presentParams.Windowed = true;

     presentParams.SwapEffect = SwapEffect.Discard;

     presentParams.AutoDepthStencilFormat = DepthFormat.D16;

     bool canDoShaders = true;

     Caps hardware = Manager.GetDeviceCaps(0,DeviceType.Hardware);

     if(hardware.VertexShaderVersion >= new Version(1,1))

     {

         CreateFlags flags = CreateFlags.SoftwareVertexProcessing;

         if(hardware.DeviceCaps.SupportsHardwareTransformAndLight)

              flags = CreateFlags.HardwareVertexProcessing;

         if(hardware.DeviceCaps.SupportsPureDevice)

              flags |= CreateFlags.PureDevice;

         device = new Device(0,DeviceType.Hardware,this,flags,presentParams);

     }

     else

     {

canDoShaders = false;

         device = new Device(0,DeviceType.Reference,this,CreateFlags.SoftwareVertexProcessing,presentParams);

     }

     vb = new VertexBuffer(typeof(CustomVertex.PositionOnly),3,device,Usage.Dynamic | Usage.WriteOnly,CustomVertex.PositionOnly.Format,Pool.Managed);

     projMatrix = Matrix.PerspectiveFovLH((float)Math.PI/4, this.Width/this.Height, 1.0f , 100.0f );

     viewMatrix = Matrix.LookAtLH(new Vector3(0,0, 5.0f ),new Vector3(),new Vector3(0,1,0));

     VertexElement[] elements = new VertexElement[]

     {

         new VertexElement(0,0,DeclarationType.Float3,DeclarationMethod.Default,DeclarationUsage.Position,0),

VertexElement.VertexDeclarationEnd

     };

     decl = new VertexDeclaration(device,elements);

     return canDoShaders;

}

         这段代码假设使用默认的适配器进行渲染。为了简单,这里实际山还省略了许多因该做的枚举。创建设备之前,应该先检查所创建设备的能力,因此,先获得Caps结构。这个程序我们只使用可编程的管道进行渲染,因此,必须确保显卡至少支持第一代的顶点着色器。随着新版本的API发布,顶点和相色着色器的版本也是不断更新的。比如,DirectX 9就允许使用顶点和像素着色器的3.0版本。第一代的着色器自然是1.0版,不过在DirectX 9中已经使用1.1来代替这个版本,所以我们在这里检测是否支持它。

         假设你的显卡支持这些功能,那么就能创建一个“最理想”的设备了。默认使用software vertex processing,但是如果可以使用hardware vertex processing以及pure device,那么就使用这些功能。如果显卡不支持着色器,那么就使用参考设备。

         接下来创建顶点缓冲。对于渲染一个三角形来说,只需要3个带有位置信息的顶点就可以了。

private void OnVertexBufferCreate(object sender, EventArgs e)

{

     VertexBuffer buffer = (VertexBuffer)sender;

     CustomVertex.PositionOnly[] verts = new CustomVertex.PositionOnly[3];

     verts[0].Position = new Vector3( 0.0f , 1.0f , 1.0f );

     verts[1].Position = new Vector3( -1.0f , -1.0f , 1.0f );

     verts[2].Position = new Vector3( 1.0f , -1.0f , 1.0f );

     buffer.SetData(verts,0,LockFlags.None);

}

         创建了顶点缓冲之后,保存即将用到的观察和投影矩阵。用和以前一样的方法创建这些矩阵。最后,来到顶点声明的部分。顶点申明告诉DirectX关于这些即将传入到编程管道中的顶点的所有所需信息。在创建vertex declaration对象时,把所用的device和一个vertex element数组作为参数,vertex element数组中的每一个成员都描述了顶点数据中的一个元素(component)。来看看 vertex elment的构造函数:

public VertexElement(short stream, short offset, DeclarationType declType, DeclarationMethod declMethod, DeclarationUsage declUsage, byte usageIndex);

         其中,第一个参数是流所使用的顶点数据。当对device调用SetStreamSource方法时,就把顶点缓冲中的数据分配为一个流,作为第一个参数。至今为止,我们都把所有数据保存在一个顶点缓冲中,并转换为一个流来使用,但是,完全有可能把来自多个顶点缓冲中的数据分配为多个流来渲染一个对象。由于在0号流中只有一个顶点缓冲,所以直接把这个参数设置为0。

         第二个参数是缓冲中数据开始的偏移位置。这里,顶点缓冲中只有一种类型的数据,自然值就为0。但是,如果包含了多种元素(component),则需要相应的进行偏移。举个例子,第一种元素是位置信息(三个float值),第二种元素是法线(同样也是三个float值),那么第一个元素的偏移值为0(因为它是第一个元素),同时,法线元素的偏移值就为12(3个float占用12字节)。

         第三个参数用来通知Direct3D所要使用的数据类型。由于只需要位置信息,所以可以使用Float3(我们将在后面讨论这个类型)。

         第四个参数描述了这个声明所使用的方法。在大多数情况下(除非你使用高要求的图元),使用默认值就可以了。

         第五个参数描述了每个元素的usage,比如位置、法线、颜色等等。使用三个浮点数来描述位置。最后一个参数是用来控制usage数据的,允许你指定多种usage类型。大多数情况下使用0就可以了。

         需要特别注意的是,vertex element数组必须使用VertexElement.VertexDeclarationEnd作为他的最后一个元素。好了,对于最简单的情况来说,我们使用编号为0的流,使用3个腹点值来表示位置。在创建了vertex elemen数组之后,就可以创建vertex declaration对象了。最后,返回一个布尔值,true表示可以硬件支持使用着色器,false则使用参考设备。

         在处理完初始化方法之后, 你需要处理它的返回值了,更新main方法:

static void Main ()

{

     using(Form1 frm = new Form1())

     {

         frm.Show();

         if(!frm.InitializeGraphics())

         {

              MessageBox.Show("your card does not support shaders, This application will run in ref mode instead");

         }

         Application.Run(new Form1());

     }

}

         还有什么没完成呢?只剩下渲染场景了。这里和贯穿本书的所有渲染方法一样,重载OnPaint方法:

protected override void OnPaint(PaintEventArgs e)

{

     device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,Color.CornflowerBlue, 1.0f ,0);

     UpdateWorld();

     device.BeginScene();

     device.SetStreamSource(0,vb,0);

     device.VertexDeclaration = decl;

     device.DrawPrimitives(PrimitiveType.TriangleList,0,1);

     device.EndScene();

     device.Present();

     this.Invalidate();

}

         Clearn了设备之后,调用UpdateWorld方法,这个方法只是简单的增加旋转角度以及修改世界矩阵而已:

private void UpdateWorld()

{

     worldMatrix = Matrix.RotationAxis(new Vector3(angle/((float)Math.PI * 2.0f ),angle/((float)Math.PI* 4.0f ),angle/((float)Math.PI* 6.0f )),angle/(float)Math.PI);

     angle += 0.1f ;

}

         好了,除了用vertex devlaration属性代替vertex format属性以外,以上大部分的代码都是很熟悉的,现在运行程序看看,除了一个蓝色的屏幕外,什么也没有。为什么?Direct3D运行时并不知道你想做什么。你需要为编程管道编写一个“程序”。

         给工程添加一个名为“simple.fx”的空白文件。你将使用这个文件来保存HLSL程序。 让我们来添加HLSL代码吧:

struct VS_OUTPUT

{

    float4 pos  : POSITION;

    float4 diff : COLOR0;

};

float4x4 WorldViewProj : WORLDVIEWPROJECTION;

float Time = 1.0f ;

VS_OUTPUT Transform(

    float4 Pos  : POSITION)

{

    VS_OUTPUT Out = (VS_OUTPUT)0;

    Out.pos = mul(Pos, WorldViewProj);

    Out.diff.r = 1 - Time;

    Out.diff.b = Time * WorldViewProj[2].yz;

    Out.diff.ga = Time * WorldViewProj[0].xy; 

    return Out;

}

         你看,HLSL实际上和C很类似。先来看看这段代码干了些什么吧。首先声明了顶点程序输出数据的结构。这里变量的声明有一点点特别。每个变量的后面都添加了一个语义标识符。语义表示了如何把这些变量与图形流水线相连接。

         问什么顶点缓冲只包含了位置信息,但是输出结构里却要同时包含位置和颜色信息呢?只有输出结构包含了位置和颜色数据(以及相应的语义),Direct3D才知道使用顶点程序返回的值来渲染,而不是使用顶点缓冲中的值。

         接下来,有两个“全局”变量;综合了世界,观察,投影变换的矩阵,以及一个用来改变颜色的时间变量。程序运行时,每一帧都必须更新这几个变量。

         最后,就是实际的顶点程序方法了。它把我们刚才所创建的结构作为返回值,接受一个顶点位置作为参数。这个方法将被所有顶点调用一次。需要注意的是输入值同样包含了语义,以便让Direct3D知道在处理什么类型的数据。

         这个方法之内的代码实际上是很简单的。你声明了作为返回值的变量——Out。把顶点和变换矩阵相乘,完成坐标变换。你使用了内置函数mul,因为矩阵的类型是float4*4,而位置是float4。使用标准的相乘符号会导致类型不匹配。

         之后,使用了一个公式对颜色的每一个因素作恒定的变换。注意看我们是如何设置颜色的每个元素的,首先是红色,接下来是蓝色,最后是绿色和alpha。位置和颜色都设置好之后,就可以填充返回的结构了。

         (此处省略介绍HLSL语法的若干内容,建议大家去看《Cg教程——可编程实时图像权威指南》)

 

Rendering Shader Programs with Techniques

         现在完成了顶点程序的编写,如何使用它呢?顶点程序中并没有一个“入口点”,只有一个方法而言。如何调用这个方法呢?很简单,你只需要使用一个称为“technique”的东西就可以了。一个technique由一个或多个pass组成。每一个pass都能设置device state同时设置顶点和像素着色器来使用你的HLSL代码。来看看可用于这个程序的technique,在simple.fx文件中添加代码:

technique TransformDiffuse

{

    pass P0

    {

        CullMode = None;

        VertexShader = compile vs_1_1 Transform();

        PixelShader  = NULL;

    }

}

这里,你声明了一个称为TransformDiffuse的technique。这个名字仅仅是做修饰而以,没有什么特别的用处。在这个technique里,声明了一个pass。裁剪模式被设置为null,可以同时看到三角形的正面和背面。还记得以前写过的程序吗,这个任务是通过编写C#来完成的。使用pass来保存device state是一个不错的地方,所以在这里设置裁剪模式是很合适的。

接下来,你想对即将进行渲染的顶端使用这个顶点程序,因此,使用vs_1_1标志来编译它。这个标志符应该根据你显卡的能力来进行选择。由于以及知道了拟定设备至少支持vertex shader1.1,所以使用这个标志。如果使用vertex shader2.0,那么标志就设置为vs_2_0。而相应的pixel shader标志就设置为ps_2_0。

由于没有像素程序,因此把PixelShader成员设置为null就可以了。Pass到这里就完成了。接下来需要更新C#代码了。

首先,我们将使用Effect对象,应为他是处理HLSL的主要对象。在InitializeGraphics方法中添加如下代码(在创建device之后):

effect = Effect.FromFile(device,@"../../simple.fx",null,ShaderFlags.None,null);

effect.Technique = "TransformDiffuse";

     我们通过一个文件来创建effect对象。同时设置了technique成员,因为整个程序都使用同一个technique。Effect对象会完成所有对HLSL的处理工作。另外还有两个需要每帧都更新的变量。在UpdateWorld方法的最后添加如下代码:

Matrix worldViewProj = worldMatrix * viewMatrix * projMatrix;

effect.SetValue("Time", (float)Math.Sin(angle / 5.0f ));

effect.SetValue("WorldViewProj", worldViewProj);

     这里,储存并合并了矩阵。同时更新HLSL中的变量。最后要做的只剩下更新渲染对象的代码了,在DrawPrimitives方法中添加代码:

int numPasses = effect.Begin(0);

for (int i = 0; i < numPasses; i++)

{

     effect.Pass(i);

     device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

}

effect.End();

(注意,新版的DirectX已经改为了

int numPasses = effect.Begin(0);

for (int i = 0; i < numPasses; i++)

{

     effect.BeginPass(i);

     device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

     effect.EndPass();

}

effect.End();

)

     由于已经为effect设置了technique,所以当渲染的时候,需要调用Begin方法。这个方法的参数允许你选择是否保存一个特定的状态,对于这个例子来说,不是太重要。这个方法同时还返回了当前technique中pass的数量。就算只有一个pass在technique里,最好还是使用一个循环来保证渲染了所有希望的technique。最后在渲染之前,还必须调用effect对象的Pass方法。这个方法唯一的参数就是你所使用的pass索引。这个方法让设备为渲染指定的pass做好准备,更新设备状态,同时设置顶点和像素着色器方法。最后嗲用DrawPrimitive方法。渲染完成之后,还必须调用effect对象的End方法。好了,现在运行程序看看吧。

 

使用可编程管道渲染Mesh

     简单三角形例子唯一的特点就是:简单。你不可能只使用一个顶点程序和一个三角就完成一个游戏,因此,这一节我们将渲染整个mesh。删除文件里关于顶点和顶点缓冲的声明,添加mesh对象:

private Mesh mesh = null;

     对于渲染mesh来说,有一个方便的地方就是在渲染时会自动设置vertex declaration。自然,删除所有处理顶点声明和顶点缓冲的代码。同时,更新InitializeGraphics创建mesh。创建了mesh和effect对象之后,添加代码:

mesh = Mesh.Teapot(device);

     最后,修改OnPaint方法,使用DrawSubset方法代替DrawPrimitives:

mesh.DrawSubset(0);

     你看这里并没有多少需要修改的地方,现在运行程序,可以得到一个和三角形颜色效果差不多的茶壶。由于茶壶所以位置的颜色都一样,导致它看起来不太像一个茶壶。还记得我们以前也遇到过这种情况吗,添加一个方向灯情况就会好的多。

     由于本章的目的是不使用固定管道来进行渲染,所以不使用device的lights属性。我们将更新HLSH代码来实现一个白色的方向灯。在HLSL代码中添加如下变量;

float3 LightDir = { 0.0f , 0.0f , -1.0f );

     接下来,使用以下代码代替现有的方法:

VS_OUTPUT Transform(

    float4 Pos  : POSITION,

    float3 Normal : NORMAL )

{

    VS_OUTPUT Out = (VS_OUTPUT)0;

    float4 transformedNormal = mul( Normal , WorldViewProj);

    Out.diff.rb = 1.0f ;

    Out.diff.ga = 0.0f ;

    Out.diff *= dot(transformedNormal, LightDir);

    Out.pos = mul(Pos, WorldViewProj);

    return Out;

}

注意我们使用了一个新的参数作为法线数据。你必须保证每个使用这个technique的顶点都有法线数据,否则将导致异常。Mesh类创建的茶壶已经包含了法线信息,所以这里不会出什么问题。接下来,需要把法线数据和顶点转换到同一个坐标系中。对不同坐标系下的顶点和法线进行光照计算是没有意义的。

如果你看过SDK中关于实现方向光的数学原理,就知道它实际上是使用顶点法线和灯光方向的点积再乘以光的颜色来实现的。可以把rgba混合值都设置为1,并且通过计算得到最后的值。

这个程序现在因该渲染了一个旋转的白色茶壶。添加了灯光之后,茶壶看起来要真实多了。你可以任意修改灯光的颜色来看看。

 

使用HLSL编写Pixel Shader

     至今为止,我们之使用了顶点程序来控制顶点,然而,这只是可编程管道的一半而已。如何处理每一个独立像素的颜色呢?我们还是使用第五章MeshFile的例子作为基础,把它更新为使用编成管道的程序。使用这个例子的原因是他不仅渲染了顶点,还使用纹理来着色,而这正是使用pixel shader的地方。

     打开项目知道,线添加一些必要的变量:

private Effect effect = null;

private Matrix worldMatrix;

private Matrix viewMatrix;

private Matrix projMatrix;

     同样根据上一节的方法,更新initializeGraphics方法,检查显卡是否支持编成管道。这一次我们需要同时检查对vertex shader和pixel shader的支持。按照上一节中的方法,更改以下代码:

if((hardware.VertexShaderVersion >= new Version(1,1)) && (hardware.PixelShaderVersion >= new Version(1,1)))

……………

effect = Effect.FromFile(device,@"../../simple.fx",null,ShaderFlags.None,null);

effect.Technique = "TransformTexture";

projMatrix = Matrix.PerspectiveFovLH((float)Math.PI/4,this.Width / this.Height, 1.0f , 10000.0f );

viewMatrix = Matrix.LookAtLH(new Vector3(0, 0,580.0f ),new Vector3(), new Vector3(0, 1.0f ,0));

     这里和之前的方法很类似。由于SetupCamera方法使用了固定管道中的变换和光照,所以可以把它完全删除了。自然,还需要修改OnPaint方法。接下来,更新DrawMesh方法,使用HLSL来进行渲染。

     同样,每帧调用这个方法的时候都会更新合并之后的变换矩阵以及HLSL中的变量。接下来使用technique中的每一个pass渲染每一个mesh中的子集。好了,可以添加HLSL代码了,添加“simple.fx”文件:

float4x4 WorldViewProj : WORLDVIEWPROJECTION;

sampler TextureSampler;

void Transform(

    in float4 inputPosition : POSITION,

    in float2 inputTexCoord : TEXCOORD0,

    out float4 outputPosition : POSITION,

    out float2 outputTexCoord : TEXCOORD0

    )

{

    // Transform our position

    outputPosition = mul(inputPosition, WorldViewProj);

    // Set our texture coordinates

    outputTexCoord = inputTexCoord;

}

 

void TextureColor(

 in float2 textureCoords : TEXCOORD0,

 out float4 diffuseColor : COLOR0)

{

    // Get the texture color

    diffuseColor = tex2D(TextureSampler, textureCoords);

};

 

technique TransformTexture

{

    pass P0

    {

        // shaders

        VertexShader = compile vs_1_1 Transform();

        PixelShader  = compile ps_1_1 TextureColor();

}

}

     你可能马上就注意到了这里的着色程序和先前的不同。这次我们没有使用一个结构来作为返回值,而是把要返回的值作为方法的out参数。对于顶点程序来说,我们只关心顶点位置和纹理坐标。接下来的则是pixel shader。他接受当前像素的纹理坐标,并返回这个像素颜色用于渲染。这里,我们只使用了在这个纹理坐标上的默认颜色,因此使用了内建的tex2D方法。它在给定坐标对纹理进行采样,并且返回这个位置的颜色。这几乎是最简单的pixel shader了。运行程序看看吧。

但是,pixel shader并没有完成什么用固定管道不能完成的功能。让我们来做点有趣的工作吧。你将在这个HLSL中使用多个technique,添加如下代码:

void InverseTextureColor(

 in float2 textureCoords : TEXCOORD0,

 out float4 diffuseColor : COLOR0)

{

    // Get the inverse texture color

    diffuseColor = 1.0f - tex2D(TextureSampler, textureCoords);

};

 

technique TransformInverseTexture

{

    pass P0

    {

        // shaders

        VertexShader = compile vs_1_1 Transform();

        PixelShader  = compile ps_1_1 InverseTextureColor();

    }

}

     这里的代码和第一个pixel shader差不多,唯一的区别就是使用 1.0f 减去所采样的颜色值,这样会得到这个像素的反转颜色。同时还创建了一个新的technique来调用新的pixel shader。接下来,更新C#代码,实现在两种效果之间跳转:

protected override void OnKeyPress(KeyPressEventArgs e)

{

     switch(e.KeyChar)

     {

         case '1':

              effect.Technique = "TransformTexture";

              break;

         case '2':

              effect.Technique = "TransformInverseTexture";

              break;

     }

     base.OnKeyPress (e);

}

现在运行程序看看两种不同的效果吧。在源码中,我们还包含了只允许或不允许蓝色通道的遮罩效果。

[原创]Managed DirectX 基础使用教程(一) hangtao_me@yahoo.com.cn 本次内容:如何用Managed  DirectX 显示图片(2D),以及一些变形.上回我们已经学习了MDX的一些基本知识,现在我们就要来使用它了.准备:创建一个Windows 窗体应用程序然后在引用中右键添加引用然后选择需要的.NET项目然后在代码中写上相应的using .......现在准备工作已经做好了,那么在 阅读详情

相关推荐

Managed DirectX Shader技术实战指南

本文还有配套的精品资源,点击获取 简介:Managed DirectX是微软开发的一套API,允许开发者利用.NET环境控制硬件图形处理。本主题探讨了在.NET中使用Managed DirectX实现复杂图形渲染效果的Shader技术,特别是顶点Shader和像素Shader的应用。Managed DirectX支持高级图形效果的Shader Model 2.0及以上版本。...

weixin_42284380的博客 1220

使用C# + Managed DIrectX 制作 2D 游戏使用C# + Managed DIrectX 制作 2D 游戏

主旨:虽然目前Microsoft已经发布了XNA Game Studio,让游戏编程员能够更轻松的在Windows(XB360不在本文考虑范围内)制作游戏,不过这个XNAGS有个缺点,它要求系统必须有至少能够支援Shader Model 1.1的显示卡。这表示TNT,GeForce 1, 2, 和 GeForce 3 & 4 MX 系列的显示卡,以及较早期的 integrated display

shaily读书学习 6786

Managed DirectX电子书

学习directX 3D开发的好东西

【翻译】managed DirectX (第三章)

使用简单的渲染技术翻译:clayman    至今为止,我们的渲染工作效率都很低。每次渲染场景时,都要分配新的顶点列表,并且所有东西存储在系统内存里。现代显卡集成了足够显存,把顶点数据存放在显存可以获得大幅的新能提升:存放在系统内存里的数据,渲染每一帧时都要拷贝到显卡,这会带来极大的损失。只有移除每帧时的这种分配才能帮助我们提高性能。  使用顶点缓冲(Using Vertex Buffers)Di

Clayman的专栏 5027

Managed DirectX 9(中文版)

Managed DirectX 9(中文版)是受欢迎的directx教材,此版为中文版

Managed DirectX9.0中文教程

Managed DirectX9.0中文教程 有需要的就下吧

Managed DirectX +C# 开发(入门篇)(一)

  前      言以前是用VC 作计算机图形学的,大约在一年前,公司接到一个用C#+DirecX的项目,从那时起便开始学习Mangaged DirectX ,现将在开发过程中的一点总结发表出来,和同行们共同参考,共同学习,共同进步,前面是一些基础内容,算是入门篇吧,现在正将开发过程中所用到的一些算法整理中,算是中级篇吧。1:在整理过程中,有些内容为从网上找的资料,部分为翻译国外文章,正所

dandanCool的专栏 8816

DirectX for Managed Code

适用于.net平台的DirectX动态链接库,适合于在.net平台下开发高级的3D界面等

Managed DirectX(第五章)

定义Mesh    虽然有很多时候,你需要手动创建顶点和索引数据,但更普遍的情况是从外部的资源加载已有的顶点数据,比如从一个文件。通常我们使用.X文件来保存这些信息。在前一章里,代码的大部分都用来创建几何体了。对于简单的三角形和立方体来说这似乎是完全可行的,但设想假如用相同的方式来创建拥有上万个顶点的物体将,所花费的时间和努力都将是很可怕的。     幸运的是,Managed DirectX里有一

sunkangta的专栏 1208

Managed DirectX 9.0 SDK 文档中文译本

Managed DirectX 9.0 SDK 文档中文译本 翻译内容选自官方帮助文档 pdf清晰版 极有价值

手把手教你获取全国街道级GeoJSON数据:前端地图开发必备技巧

本文详细介绍了获取全国街道级GeoJSON数据的多种方法,从前端地图开发的实际需求出发,涵盖了免费获取省市县级数据的工具如阿里云DataV.GeoAtlas和HashTang,以及进阶的街道级数据获取方案,包括使用Bigemap GIS Office和专业数据采购。文章还提供了数据处理与优化技巧,帮助开发者高效使用GeoJSON数据进行地图可视化。

weixin_29053383的博客 289

【翻译】Managed DirectX(第五章)

Rendering with Meshes翻译:claymanclayman_joe@yahoo.com.cn 定义Mesh    虽然有很多时候,你需要手动创建顶点和索引数据,但更普遍的情况是从外部的资源加载已有的顶点数据,比如从一个文件。通常我们使用.X文件来保存这些信息。在前一章里,代码的大部分都用来创建几何体了。对于简单的三角形和立方体来说这似乎是完全可行的,但设想假如用相同的方式来创建拥

Clayman的专栏 3645

基于555定时器的呼吸灯电路

呼吸灯是指LED灯在芯片的控制下完成由亮到暗的逐渐变化,感觉就像人在呼吸,其广泛使用在手机上,起到一个通知提醒的作用。呼吸灯在许多灯光装饰上也有大量使用,如音响、汽车广告牌等,在生活中较为常见。...

qq1074237849的博客 9496

【翻译】Managed DirectX(第九章)

第九章 使用其它Mesh类型翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^简化Mesh(Simplifying Meshes)         我们花了大量的时间来学习扩展库中的基本Mesh类,但实际上,还有3种其它Mesh类型我们没有讨论过,在这一章中,我们就来看看这几个对象。         我们已经知道如何通过使

Clayman的专栏 3572

基于角谱传播的MATLAB仿真:从相位恢复看自由空间光传播

本文详细介绍了基于角谱传播理论的MATLAB仿真方法,用于模拟自由空间光传播过程。通过傅里叶光学原理,将光场分解为频谱并应用传播相位滤波器,实现了从纯相位物体到可观测衍射图样的仿真。文章结合具体代码,演示了如何利用角谱法进行相位恢复,为计算成像和生物医学检测等领域的研究提供了实用的仿真工具和思路。

weixin_29055699的博客 282

不会写GLSL?用Cesium 1.120 + Heatmap.js 2.0.5也能搞定动态洪水模拟(附完整源码)

本文介绍了一种无需GLSL编程的3D洪水动态模拟方案,结合Cesium 1.120和Heatmap.js 2.0.5实现高效可视化。通过数据层、可视化层和集成层的技术降级方案,开发者可以快速构建专业级洪水演进效果,适用于应急管理、水利工程等场景。文章包含完整源码和性能优化技巧。

weixin_30329623的博客 523

【翻译】Managed DirectX(第七章)

第七章 Using Advanced Mesh Features翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^这一章,我们将要调论一些关于Mesh对象的高级特性,包括:n                        优化(Optimizing)mesh数据n                        简化(Sim

Clayman的专栏 3884

华为OD机考双机位C卷 - 螺旋数字矩阵 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 数字螺旋矩阵(OD上机考试双机位C卷)。提供在线OJ刷题。Java、C++、Python、GO语言、C语言、JavaScript题解,并提供完整思路讲解。

算法大师! 3218

【翻译】Managed DirectX(第六章)

第六章 使用Managed DirectX编写游戏翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^选择游戏      虽然很多关于3D游戏编程的高级主题还没有讨论,但我们已经有足够的背景知识来写一个简单游戏了。这一章,我们将使用至今学过的知识,再加上一点点新的东西来创建游戏。     真正开始写游戏之前,最好先拟一份计划

Clayman的专栏 4175

基于STM32设计的电能质量控制系统_353

本项目基于STM32F103RCT6微控制器设计了一套电能质量控制系统,实现了对火焰、烟雾、环境温湿度、电压、电流及功率等多项参数的实时监测与报警。系统通过MQ2烟雾传感器、火焰传感器、SHT30温湿度传感器及电力参数采集模块采集数据,采用高电平触发有源蜂鸣器进行异常报警。采集的数据通过ESP8266无线模块以AP+TCP模式上传至基于Qt开发的手机APP和电脑上位机,实现远程实时监控和历史数据管理。系统配备1.44寸LCD显示屏,实现本地数据显示。软件采用Keil5开发,采用寄存器编程方式,提高系统响应速

253

全功能爬虫框架:Botasaurus 的详细使用(现代化、反检测、高并发的智能爬虫框架)

Botasaurus是一个基于 Python 的全栈式智能数据采集框架。它深度融合了以下关键技术: 无头浏览器自动化(Headless Browser Automation):基于 Playwright 或 Puppeteer,支持 Chromium、Firefox、WebKit; 高级反检测引擎(Anti-Detection Engine):自动绕过 WebDriver、Canvas、AudioContext 等 50+ 种指纹检测; 声明式任务模型(Declarative Task Model):用装

数据知道的博客 4371

【翻译】Managed DirectX(第八章)

第八章 理解资源(Understanding Resoruces)翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^资源是在Direct3D中渲染复杂对象的重要部分。在这一章的学习中,我们将会讨论关于资源的一些高级特性,包括:n          静态和动态的资源n          Updating the buffer

Clayman的专栏 3881

OpenClaw 性能调优五步法

本文介绍了优化OpenClaw性能的五步方法,将响应时间从3秒降至300毫秒。首先建立性能基线,分析模型加载、上下文检索等主要瓶颈。五步优化包括:1)启用模型缓存减少60%延迟;2)优化记忆检索策略降低25%延迟;3)并行化工具调用节省40%时间;4)智能选择轻量级模型减少50%推理时间;5)启用流式输出改善70%感知延迟。最终整体性能提升10倍,并建议建立持续监控机制。这些优化方法经过实战验证,适用于不同规模的OpenClaw部署场景。

刘一说的IT专栏 1438

【翻译】Managed DirectX(第十章)

第十章 使用助手类(Using the Helper Classes) 翻译:claymanclayman_joe@yahoo.com.cn仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^绘制直线         在第四章里我们就讨论过关于绘制直线的问题:使用基本图元里的line list或line strip绘制直线。但是这两种直线都不能改变宽度,也没有抗锯齿功能(除非整个场景都使用了

Clayman的专栏 5363

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Rendering terrains with Managed DirectX翻译

《翻译》 原文链接:http://www.codeproject.com/Articles/8195/Rendering-terrains-with-Managed-DirectX (忽然发现自己翻译的自己都不知道说的什么。。。也罢,一个小时的产物,不要要求太高) (丫的,翻译完也不不知道怎么实现的,还是老老实实去看代码吧,话说我还没用过c#,容我编程c++的,龙书第13章不就讲的地...

weixin_30301183的博客 121

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

翻译 managed DirectX9(第一章)

第一章 Introducing Direct 3D翻译:clayman创建设备  Device类是DirectX里的所有绘图操作所必须的。可以把这个类假想为真实的图形卡。场景里所有其他图形对象都依赖于device。你的计算机里可以有一个到几个device,在Mnaged DirctX3D里,你可以控制任意多个device。         Device共有三个构造函数,我们现在只讨论其中的一个,但

Clayman的专栏 9802
上一篇: 【翻译】Managed DirectX(第十章)
下一篇: 使用Managed DirectX编写游戏----理解sample framework 之枚举设备
soilwork
博客等级 码龄23年 290粉丝 116原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值