Manage shader -- import shader to your engine

Source: Internet
Author: User
Import shader to your engine

Thanks to DirectX and xNa, it is easy to load the FX file and set all required parameters (you have done this in the previous chapter when drawing 2D and 3D straight lines ). In the next chapter, you will use a more general class, which can accept many different shader and set all required parameters in a more optimized way, however, this chapter only uses simpleshader in the engine. FX file.

As before, you start by defining unit tests. Create a new file simpleshader. Cs in the namespace shader and write the followingCode:

 
# Region unit testingpublic static void testsimpleshader () {simpleshader shader = NULL; Model testmodel = NULL; texture testtexture = NULL; testgame. start ("test simpleshader. FX ", delegate {shader = new simpleshader (); testmodel = new model (" apple "); testtexture = new texture (" marble ");}, delegate {// render model shader. rendermodel (testmodel. xnamodel, testtexture) ;}// testsimpleshader # endregion

There is no rendermodel method for this unit test. Let's create it:

 
Public void rendermodel (xnamodel somemodel, texture) {}// rendermodel (somemodel, texture)

Now, after compilation, you can see a blank screen.

Compile shader

To display something on the screen in this unit test, you must first load and compile the shader. Just as you load models and textures, you use the content pipeline of xNa ). You only need. drag the FX file to your project (put it in the correct directory like other materials and models), so that the shader will be automatically compiled during project creation, if the shader has not been compiled, you will also get the error message of the shader compilation. At the same time, make sure that the marble. Dds texture is correctly loaded because it is used in your unit test.

Loading effect is as simple as loading texture. You only need to define an effect variable and load it in the simpleshader constructor:

 
# Region variableseffect effect = NULL; # endregion # region constructorpublic simpleshader () {effect = basegame. content. load <Effect> (path. combine (directories. contentdirectory, "simpleshader");} // simpleshader () # endregion

If you are on a Windows platform, you can also dynamically load the shader, which is useful for testing and changing the shader in the game. I usually use the un-compiled shader file. I don't want to change the shader anymore. The following code is used to compile and load the shader.

Note that these classes and methods only apply to Windows platforms. If you want to use this code for Xbox 360, replace # If! Xbox360 # endifProgramLine.

Compiledeffect = effect. compile1_tfromfile (path. combine ("shaders", shadercontentname + ". FX "), null, null, compileroptions. none, targetplatform. windows); effect = new effect (basegame. device, compiledeffect. getdeletcode (), compileroptions. none, null );
Parameters Used

As you learn how to build a shader, it is very important to convert 3D data from the world, observation and projection matrix, and display the data correctly on the screen. You should set all the shader parameters in the rendermodel method and call them by your unit test.

 
Basegame. worldmatrix = matrix. createscale (0.25f, 0.25f, 0.25f); effect. parameters ["worldviewproj"]. setvalue (basegame. worldmatrix * basegame. viewmatrix * basegame. projectionmatrix); effect. parameters ["world"]. setvalue (basegame. worldmatrix); effect. parameters ["viewinverse"]. setvalue (basegame. inverseviewmatrix); effect. parameters ["lightdir"]. setvalue (basegame. lightdirection); effect. parameters ["diffusetexture"]. setvalue (texture. xnatexture );

In this Code, first set the world matrix. This is very important, because if the world matrix is not set, unexpected values may be generated from previous operations. Of course, you do not want the 3D model to be in random positions. Because your apple. X is quite large, you should scale it down to fit the simplecamera class created in the previous chapter.

Calculate the worldviewproj matrix and other preset matrices. lightdir and diffusetexture are also very important, because the texture is automatically loaded in FX composer, but not in the program. You must set them yourself. If you load a model from a content pipeline, xNa automatically loads all the textures used from the model data. Therefore, the marble. Dds texture should be loaded in the unit test.

Vertex format

Before rendering your 3D Apple model, make sure that your program and shader know which vertex format to use. You can use a predefined fixed function vertex format in DirectX, but not in xNa. You must define the vertex declaration in a way similar to the vertexinput structure in the shader. Because you use the built-in vertexpositionnormaltexture structure, you do not need to define each value. However, in the next chapter, you will learn how to use your custom tangentvertex format.

 
// Use the vertexpositionnormaltexture vertex format in simpleshader. fxbasegame. device. vertexdeclaration = new vertexdeclaration (basegame. device, vertexpositionnormaltexture. vertexelements );

You do not need to create a new vertex declaration every time you call the rendermodel, but to keep it simple, you create a new vertex declaration every time you call the model. It uses the graphics device as the first parameter, and the vertexpositionnormaltexture structure of the vertex element as the second parameter. For more information, see Chapter 7th.

Use shader for rendering

To render Apple now, you should first specify the technique you want to use (set as the first technique by default, but it is best to know how to set technique ). You will always use the currenttechnique attribute of the effect class. You render 3D data for each pass in technique (as I have said before, there is usually only one pass. Rendering apple is not easy, because xNa only provides a mesh. Draw method. For details, see the model class code.

Another missing feature of xNa framework is the creation of box, ball, or teapot mesh helper class. You will also notice that most of the direct3dx namespace functions do not exist in xNa. When processing your own content processor, you can only use partial methods, which does not help your engine or test model, grid, or shader. Because all vertices and index buffers are only written, you cannot process any vertex or index data when loading the model. This is conducive to fast hardware access, but is not flexible enough. In your code, you only simulate the mesh. Draw method, but use your own effect class.

Effect. currenttechnique = effect. techniques ["specularperpixel"]; effect. begin (); foreach (effectpass pass in effect. currenttechnique. passes) {pass. begin (); // render all meshes foreach (modelmesh mesh in somemodel. meshes) {// render all mesh parts foreach (modelmeshpart part in mesh. meshparts) {// render data our own way basegame. device. vertices [0]. setsource (mesh. vertexbuffer, part. streamoffset, part. vertexstride); basegame. device. indices = mesh. indexbuffer; // and render basegame. device. drawindexedprimitives (primitivetype. trianglelist, part. basevertex, 0, part. numvertices, part. startindex, part. primitivecount);} // foreach pass. end ();} // foreffect. end ();

In detail, this means that you traverse every pass (only one here) and render all the grids (only one here ), then, after all the mesh parts you have set (and there is only one), you call the drawindexedprimitives method to render the vertices in all shader. Then pass and shader are closed, and you can finally see the apple with the marble. Dds texture displayed on the screen. (See Figure 6-16)


Figure 6-16

Test shader

Now the program can run. You can try to test other textures, materials, or rendering modes.

For example, you can see Figure 6-5 in front of the box to implement the effect of the box. You can change the fillmode before the shader starts:

 
Basegame. device. renderstate. fillmode = fillmode. wireframe;

Or another texture or model that can be loaded. The shader class allows this. The simplest way is to modify the ambient light, scattered light, and mirrored light values to render a strange Apple (see Figure 6-17 ).


Figure 6-17

 
Effect. parameters ["ambientcolor"]. setvalue (color. blue. tovector4 (); effect. parameters ["diffusecolor"]. setvalue (color. orange. tovector4 (); effect. parameters ["specularcolor"]. setvalue (color. orchid. tovector4 ());

Note that you must convert the color value to vector4. When you are in effect. begin () and effect. set the shader parameter between Ene (). You must call effect. commitchanges () method to ensure that the changes you made are sent to the GPU, But if you set the parameters like in The simpleshader class, then start effect. this is not required for begin.

If you use the shader parameter name to set parameters, you will learn how to set parameters more efficiently in the next chapter when you are not careful about spelling wrong parameters.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.