| Catalin 的个人资料Catalin 's Blog日志列表 | 帮助 |
|
|
1月14日 Ziggyware XNA Holiday Contest winners announced!
I happily announce that I have again won Ziggyware's XNA Holiday Contest The three winning articles are: 1. Deferred Shading in XNA - Catalin Zima 2. Depth of Field - Kyle Schouviller 3. Shadow Mapping - Andrew Joll I'd like to congratulate all who entered, and thank Ziggyware for organizing the contest. 12月24日 New tutorial Coming Soon...
Sorry for the lack of posts recently, but I've been very busy with school and other stuff. Anyway, since XNA 2.0 came out, and Ziggyware has a new contest, I've decided to put some more time into XNA, and try something new. One of the new things in XNA 2.0 is the support for Multiple Render Targets on the Xbox. Now that this became available I had the opportunity to try one of my older desires: implementing a deferred renderer. So, my next tutorial will cover implementing a deferred renderer in XNA 2.0. Here are some screenshots from what will come soon: Lizard drawn with normal mapping, and about 16 moving point lights. One point light moving around a ship Over 20 lights lighting the ship Stay tuned for more... 11月20日 XNA Game Studio 2.0 beta released!
Ok, so I know lots of other sites will have this announced, and if you frequent creators.xna.com you already know this, but I can't not announce this too: The beta version of XNA Game Studio 2.0 has been released. It's been told that the final version will come pretty soon also, but until then you can experiment with new features included in the beta: multiplayer, virtualised device, project management, etc. Go get it HERE. 11月4日 XNA Achievements (sort of)John Wells released a nice little component, which allows us to display messages similar to the Achievement notices on the Xbox 360. Of course, it will not alter your gamerscore, but it adds a very cool touch to a game. Here's how it looks in action:
10月27日 PieMenu Component
For the people who want some UI stuff in XNA, here's a small sample that contains a Pie Menu Component, attached to a cursor. If you don't know what a pie menu is, read about it on wikipedia. Now, about the sample. My PieMenu supports deep menus, as seen in the sample. Currently it is just a quick version, made in two days. Because of this, the graphics are not spectacular, and some things may not be extremely flexible right now (the parameters passed to delegates). But as it is, each menu entry has associated with it an image, a text description, and a delegate, for the action that should be performed. The PieMenu also supports submenus, as seen in this sample. The cursor can operate in two modes: mouse-friendly and gamepad friendly. In the mouse friendly mode, the menu options are selected with the cursor, while in gamepad friendly mode, they are selected with the left thumbstick. The current sample contains the following menus:
This is just as an example. The menu can be easily customized. Also, the Cursor.ShowPieMenu() function has an overload that allows you to specify the menu that will be shown. This allows for different menus, depending on the selected object (this is NOT illustrated in this sample) Controls:
You can find the sample here. You can use the code as you see fit, with one exception. If you're working on an entry for the Imagine Cup 2008 competition, and you plan to use it, please give me credit :) Comments? Suggestions? (Besides "the graphics suck, make them better") 10月16日 Mass Effect review in GameInformerwww.xbox360fanboy.com informs us that GameInformer made a review of Mass Effect, and it received an amazin 9.75
Here's the review for those interested.
I'm proud to be a fan of this game ;)
10月14日 Tutorial Contest Winner!Ziggyware just announced the winners of the XNA Tutorial Contest, and the first place goes to.... ME! Hurraaaay! Party!!!! I'm extremely happy about this, and I want to thank everyone who supported me, who voted for me, and who somehow contributed to this. Also, I want to congratulate all other contestants for their good tutorials! Special thanks go to: Michael Morton, for organizing the contest! Lidia, for every little thing she does, and for her support, understanding, caring and love. Nick Gravelyn, for helping Michael with putting my article online All my voters :) All of the XNA Community The XNA Team Thank you! I'll do my best to continue providing tutorials and help to the community. Gamefest 2007 slides available
Let's Kill Dave has posted the list of Gamefest presentations what will have slides and recordings available for them. Since most of the links were not posted right, Leaf made the needed corrections. You can now find all the links here. The titles sound extremely interesting, and I can't wait to devour them. I wish you all Happy Reading / Listening :) 9月22日 Running the VTF Tutorial samples on ATI or SM 2.0 cards
I was talking to Michael Morton (Ziggyware owner) about the possibility of making my code run on ATI cards, and I told him that someone else tried using R2VB in XNA and failed. In that moment, an idea came to me: "Let's simulate R2VB on the CPU". Yes, I know, this sound crazy, but let's analyze a little. In my tutorials, because I wanted to use vertex textures, I had to store lots of data in textures and do simulations in textures. Examples of these are: the particle systems, the deformation map creation, applying the deformation map to the displacement map, etc. These were, in a way, secondary effects of using VTF, which actually proved to increase the performance. So, rather than doing everything on the CPU, we will still do these texture manipulations on the GPU. First, let me explain how R2VB works. For the most part, the operations I did in the tutorials are exactly the same: use some pixel shader for simulations and deformations. The difference between VTF and R2VB comes on play when you finally have a texture, and you want to use the information from this texture to alter the vertices. As we saw in the tutorial, VTF reads from this texture inside the vertex shader. On the other hand, R2VB takes that information and draws it in a "texture". That "texture" is at the same GPU memory address as a Vertex Buffer, so, when writing to the texture, the information is actually written to the vertex buffer. Hence, the name Render To Vertex Buffer. We will emulate this behavior in software, on the CPU. So all the performance gained by doing the simulations using pixel shaders and render-to-texture remains. We take the second tutorial, the one with morphing terrain. Let's see what needs to be done. Open Grid.cs, and add the following function. Single[] textureData; public void DrawCPUSingle(Texture2D displacementTexture) { displacementTexture.GetData<Single>(textureData); for (int i = 0; i < displacementTexture.Height; i++) {for (int j = 0; j < displacementTexture.Width; j++) vertices[i * displacementTexture.Width + j].Position.Y = textureData[j * displacementTexture.Height + i]; } IGraphicsDeviceService igs = (IGraphicsDeviceService)game.Services.GetService(typeof(IGraphicsDeviceService));device = igs.GraphicsDevice; device.VertexDeclaration = vertexDecl; device.Indices = ib; device.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, 2 * dimension * dimension); } public void LoadGraphicsContent() { textureData = new Single[(dimension + 1) * (dimension + 1)];[...] } As you can see, we take as input the texture that would be used as a displacement texture, then we use GetData() on it, and we write that data to our vertex array. The index array is the same as before. After this, instead of using a dynamic vertex buffer, we use the DrawUserIndexedPrimitives. Now, we need to modify the VTFDisplacement.fx effect file. The modifications appear in the vertex shader: VS_OUTPUT TransformCPU(VS_INPUT In) {VS_OUTPUT Out = (VS_OUTPUT)0; float4x4 viewProj = mul(view, proj); float4x4 worldViewProj= mul(world, viewProj); // we don't read from the texture anymore float height = In.position.y;In.position.y = height * maxHeight; Out.worldPos = mul(In.position, world); Out.position = mul( In.position , worldViewProj); Out.uv = In.uv; float4 TexWeights = 0; TexWeights.x = saturate( 1.0f - abs(height - 0) / 0.2f); TexWeights.y = saturate( 1.0f - abs(height - 0.3) / 0.25f); TexWeights.z = saturate( 1.0f - abs(height - 0.6) / 0.25f); TexWeights.w = saturate( 1.0f - abs(height - 0.9) / 0.25f); float totalWeight = TexWeights.x + TexWeights.y + TexWeights.z + TexWeights.w;TexWeights /=totalWeight; Out.textureWeights = TexWeights; return Out;} [...] //pixe shader remains the sametechnique GridDrawCPU {pass P0 { //we can use SM 2.0vertexShader = compile vs_2_0 TransformCPU(); pixelShader = compile ps_2_0 PixelShader(); } } The final modifications are done in the Draw function in Game1.cs foreach (EffectPass pass in gridEffect.CurrentTechnique.Passes) {pass.Begin(); grid.DrawCPUSingle(morphRenderTarget.GetTexture()); pass.End(); } That's all. The Steps in Snow sample is converted in exactly the same way. For the particle system sample, we have the following modifications. In the vertex shader of the file Particle.fx, change the line float4 realPosition = tex2Dlod ( positionSampler, float4(In.vertexData.x, In.vertexData.y,0,0)); into float4 realPosition = In.vertexData; In Game1.cs, modify the following code:
Vector4[] textureData; protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) { textureData = new Vector4[particleCount * particleCount];[...] } [...] } protected override void Draw(GameTime gameTime) {graphics.GraphicsDevice.Clear(Color.Black); Render2TextureMorph((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds) * 0.5f + 0.5f);Render2TextureNormalCompute(); SimulateParticles(gameTime); graphics.GraphicsDevice.RenderState.CullMode = CullMode.None; [...] graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.One; Texture2D positionTexture = positionRT.GetTexture(); positionTexture.GetData<Vector4>(textureData); for (int i = 0; i < positionTexture.Height; i++) {for (int j = 0; j < positionTexture.Width; j++) {vertices[i * positionTexture.Width + j].Position.X = textureData[j * positionTexture.Height + i].X; vertices[i * positionTexture.Width + j].Position.Y = textureData[j * positionTexture.Height + i].Y; vertices[i * positionTexture.Width + j].Position.Z = textureData[j * positionTexture.Height + i].Z; } } using (VertexDeclaration decl = new VertexDeclaration( graphics.GraphicsDevice, VertexPositionColor.VertexElements)) {graphics.GraphicsDevice.VertexDeclaration = decl; renderParticleEffect.Begin(); renderParticleEffect.CurrentTechnique.Passes[0].Begin(); graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.PointList, vertices, 0, particleCount * particleCount); renderParticleEffect.CurrentTechnique.Passes[0].End(); renderParticleEffect.End(); } [...] Same technique used here: process the data on the GPU, in the textures, and then just GetData from the texture, and use it in to draw the particles. The problem of performance: here are some experiments I did:
The system this was ran on is Intel Core2 6300 (1.87Ghz), 1 GB RAM, GeForce 7600 GS 256MB Some care still has to be taken. Grid.Dimension has to be of size power-of-two-minus-one (255,511, etc). This is just because of my code. By doing this on the CPU, we loose the billinear filtering done in the vertex shader, so the Dimension of the grid has to be the same as the dimension of the displacement texture. (actually, that size minus one, as explained earlier). So, for a heightmap of 256*256, the grid's dimension has to be 255. The bilinear filtering can of course be done on the CPU also, but you'll have to see if it is worth it. These are the only restrictions I can think of. I hope this made some of you (ATI owners) more happy about my tutorial :) The source code for the modified chapters is found here: Chapter2CPU.zip, Chapter3CPU.zip and Chapter4CPU.zip Vertex Textures tutorial online!My article was just posted online on www.ziggyware.com . You can read it HERE. Lots of thanks go to Michael Morton and Nick Gravelyn who formatted the article and put it online. Thank you guys very much! Please post any comments either on the article's site, or here. 9月21日 Four uses of Vertex TexturesI have finished writing my tutorial on vertex textures, and I have submitted it to Ziggyware's XNA Tutorial Contest. It's now in the process of being formatted and arranged, and it will soon be put online. The tutorial will cover four ways in which you can use Vertex Textures. The four effects covered will begin with basic operations, and will gradually increase in difficulty, touching different techniques that can be used together with vertex textures. Some chapters may contain a Bonus section, in which I will shortly explain how to apply certain additional techniques to the effects. Here's screenshots from the four chapters, and the downloadable code for them: Chapter I: Terrain Rendering Using Heightmaps 9月12日 Fog of War SampleBy semi-popular request (I heard one person asking for it, and thought it was an interesting idea :) ), I've put together a quick sample that shows a way to implement Fog Of War in XNA, for a 3D game. As a word of warning, this is put together in a couple of hours, so it may be hacky in some parts. The idea is to have the Fog Of War in a texture. The texture represents a view from above, covering all terrain. Using render to texture, I draw a white gradient disk in this texture for each friendly unit of the player, using additive blending. After this, I draw the scene normally, and when drawing the enemies, the pixel shader gets, based on its position, the corresponding pixel from the Fog of War Texture. Using this information, it sets the alpha value of the output. This way, when the enemy unit is close to the friendly unit, you can see it, at the borders it fades away, and when out of range, it is invisible. The controls are similar to the ones in SkinnedModel Sample. If you use this for any project, please send me a screenshot. The sample can be found here. (Thanks again Kyle, for hosting my files) And some pictures: 9月11日 BloxorzI found this absolutely great game. It's a game with blocks. Fortunately, it only has 33 stages, and I already reached stage 25. I say fortunately because it's so addictive that I can't let it out of my hands. Hopefully, the last 8 levels won't be too difficult, so I can get back to coding soon. Oh, almost forgot: the game can be found here. Now back to block rotations! Converting Displacement Maps into Normal Maps in HLSLWorking on my VTF tutorial, I came across the need to apply lighting to a terrain. For lighting, we need normals, of course, but I only had heightmaps available. When the terrain is static, this poses no problems at all. All we have to de is generate a normal map from the heightmaps with whatever tools we want. For example, NVIDIA has a Photoshop plugin for this here. However, when we have dynamic terrain, with real time deformation, this is no longer an option. This is especially the case when we make the deformations on the displacement map. After lots of reading and searching, I've come across the Sobel Filter, and a sample from ATI that uses it to compute normal maps. As a result, I made a pixel shader that takes as input the displacement map and outputs the normal map. I believe this could be used for static terrain, and computed in a Content Processor, but I'm not very experienced with Content Processors, so I didn't try it. At runtime, after modifying the displacement map, I apply this shader and put the result into a render target. This result is then used when drawing the terrain, when computing lighting in the pixel shader. So here's the HLSL code: float textureSize = 256.0f;float texelSize = 1.0f / textureSize ; //size of one texel; float normalStrength = 8;float4 ComputeNormalsPS(in float2 uv:TEXCOORD0) : COLOR {float tl = abs(tex2D (displacementSampler, uv + texelSize * float2(-1, -1)).x); // top left float l = abs(tex2D (displacementSampler, uv + texelSize * float2(-1, 0)).x); // left float bl = abs(tex2D (displacementSampler, uv + texelSize * float2(-1, 1)).x); // bottom left float t = abs(tex2D (displacementSampler, uv + texelSize * float2( 0, -1)).x); // top float b = abs(tex2D (displacementSampler, uv + texelSize * float2( 0, 1)).x); // bottom float tr = abs(tex2D (displacementSampler, uv + texelSize * float2( 1, -1)).x); // top right float r = abs(tex2D (displacementSampler, uv + texelSize * float2( 1, 0)).x); // right float br = abs(tex2D (displacementSampler, uv + texelSize * float2( 1, 1)).x); // bottom right // Compute dx using Sobel: // -1 0 1 // -2 0 2 // -1 0 1 float dX = tr + 2*r + br -tl - 2*l - bl; // Compute dy using Sobel: // -1 -2 -1 // 0 0 0 // 1 2 1 float dY = bl + 2*b + br -tl - 2*t - tr; // Build the normalized normalfloat4 N = float4(normalize(float3(dX, 1.0f / normalStrength, dY)), 1.0f); //convert (-1.0 , 1.0) to (0.0 , 1.0), if needed return N * 0.5f + 0.5f;} You should tweak normalStrength until the result you get is satisfactory. And here is the result of applying that code to two heightmaps, and some terrain lit using a normal map generated by this shader. Until next time, Happy Coding! 8月31日 Mass Effect Release Date Announced!The release date for my most anticipated game has just been announced. It's November 20 for U.S. and November 23 for Europe. For those who don't know, Mass Effect is a Sci-Fi Roleplaying Game made by none other than BIOWARE, the company that gave us Baldur's Gate, Neverwinter Nights, Star Wars: KOTOR, and Jade Empire. For more information about the game, go to the official page, where you can see some screenshots, or watch some videos. Can't wait to get my hands on this one. 8月25日 XNA Gamefest Videos Online!The videos from the first day of Gamefest are online! Check them out here. 8月24日 Introduction to Vertex Textures
Ever since the appearance of programmable GPUs, there has been a significant difference between the capabilities of vertex and pixel shaders. Shader Model 3.0 took the first steps in providing common functionality between the two, and DirectX 10 took the final step and unified the Instruction Set between all types of shaders (Pixel, Vertex and the new Geometry Shaders). Since this is a XNA blog, and I didn't have the chance to experiment with DirectX10, I will focus on one feature of Shader Model 3.0 that builds towards this unification, which is Vertex Texture Fetch ( VTF ). This article will only be introductory, with little to no actual code. But a full tutorial will follow, covering several effects that can be achieved using VTF. As you probably know by now, traditionally, Vertex Shaders deal with transforming the vertices, and manipulating or setting properties like position, color, normal, texture coordinates. After this, vertices define triangles, which are then transformed into pixels. At this step, Pixel Shaders come into play, and can be used for texturing, bump mapping, normal mapping, and lots of other effects we all love. Vertex Texture Fetch allows us to read data from textures inside a Vertex Shader, just like Pixel Shaders do. Actually, not EXACTLY like Pixel Shaders do, there are some limitations, but I'll come back to that in a moment. To use VTF, you will need either an Xbox 360 (which has an unified shader architecture), or a NVIDIA graphics card from the GeForce 6 series, or greater. For those owning ATI GPUs there is another technique called Render To Vertex Buffer (R2VB), which can be used to achieve similar results. The assembler function used to read textures in a Vertex Shader is texldl. However, since I like HLSL more, and never wrote a shader in asm, I'll talk about the HLSL version. So, in HLSL, the most important instruction used for VTF is tex2Dlod. The usage is tex2Dlod( s , t ), where s is a 2D texture sampler, and t is a 4 component vector. The instruction reads a texture, using an user-defined mipmap level. This mipmap level is specified through the 4th component of the texture coordinate vector ( t.w ). Depending on the application you might get to use the mipmap level, or not. In most cases, I've used the default level 0, so a usual call took the form:
Different mipmap levels can be used when you intend to simulate water or terrain using VTF, but the levels have to be computed manually. Vertex Textures behave like Pixel Textures except for the following restrictions:
Implementing bilinear filtering in vertex textures is not too complicated, and most times, the performance hit will not be too high, since neighboring pixels are usually present in the cache. Other types of filtering (trilinear, bicubic) can also be implemented, but they need more texture fetches, and use several mipmaps levels, so the performance hit is much higher. I will cover bilinear filtering in one part of the tutorial that will come soon. Keep in mind that a vertex texture fetch is not as fast as a pixel texture fetch, so using vertex textures carelessly can yield some serious performance hits. Some tips on improving performance when using VTF are:
That concludes the introduction to vertex textures. The tutorial will continue, and show some examples of what can be done using vertex textures. You can find a small sample that morphs terrain between two heightmaps, using vertex textures, here. It is for Windows, so you'll need a NVIDIA GeForce 6 series video card, or higher. Here is the Xbox 360 version, but I didn't get to test this before uploading it, since my Xbox is not available, at the moment. Note: the downloads are .ccgame packages, so you'll need to have XNA GSE 1.0 Refresh installed. I hope this was interesting enough. If you have any suggestions, or if there are any mistakes in my facts, please point them to me. 8月23日 First entry in my blogHi there! I've been thinking for a while to get my own blog started, but I just didn't have the time. I begin today, with this post. My name is Catalin Zima, and I am a student in Computer Science, at the Technical University of Cluj Napoca, Romania. "What will this blog be about?" Mainly, it will be about Microsoft's XNA Framework, XNA Game Studio, and game development, but from time to time, you will see posts about certain games or books that interest me most, like Mass Effect, or George R.R. Martin's "A Song of Ice and Fire". "What? Another XNA blog?" My intentions are not reinventing the wheel, nor saying what lots of others have said. Instead, I'll try to post about interesting techniques that I use in my games, or troubles I run into that others might run into themselves. My code may not always be of top-performance (unless it's a post on performance :) ), but it will try to illustrate ideas as clear as possible. First, some resources for those that want to start XNA:
That's about it, for now. My next entry (in a few days) will be a short introduction about a very cool feature of Shader Model 3.0, namely Vertex Texture Fetch, followed by a tutorial on several uses of VTF, sometime in the following weeks. Suggestions? Comments? |
|
|