Processing Model -- extended model content importer loads custom Effects

Source: Internet
Author: User
Problem

You want to use a custom content processor to change the model's effect rather than real-time processing. In this way, the model can be correctly loaded into the xNa project without the need to save all textures and other information in the original effect in real time.

Note:If you want to learn how to extend the default model processor, you 'd better take a look at the next tutorial.

Solution

Extend the default model processor and override the convertmaterial method. This method is called by each materialcontent In the model. Rewrite this method to pass all materialcontent information to the custom material processor.

In this custom material processor, you will create an empty material object, and then link the custom effect to this object. You can also copy the texture of the original materialcontent to this new object, and set all HLSL variables of effect.

Working Principle

Because this tutorial needs to expand the default content processor, make sure you have read the content pipeline knowledge in 3-9. First, create a new content pipeline project. For more information, see section 3-9 "extend an existing content processor" in the tutorial.

In this tutorial, you will extend the default model processor, as shown in Figure 4-16. When the default model importer reads a model from the disk and creates a nodecontent object, it stores the effect in the materialcontent object. Your model processor only changes these materialcontent objects and stores them in nodecontent. The rest of the nodecontent object remains unchanged.

Figure 4-16 custom model processor in the content Pipeline

Note:If you compare values 4-15 and 3-6, you will find that you also have extended processors. However, because the processor processes models rather than textures, its input and output are different.

By extending the process method, you can fully control the content of a model object before it is loaded into an xNa project. In this tutorial, because effect is stored in the material information, you want to change the material processing method in the model. In the custom model processor class, you do not need to override the process method, but you need to override the convertmaterial method. This method is called by default every time the model loads materials.

Use the followingCodeReplace Process Method:

 
[Contentprocessor] public class failed: modelprocessor {protected override materialcontent convertmaterial (materialcontent material, encryption context) {return context. Convert <materialcontent, materialcontent> (material, "Callback ");}}

The above Code creates a modelcustomeffectprocessor class. Because you only override the convertmaterial method, this processor will process geometric data in the same way as the default model processor. In the convertmaterial method, the material you specify must be processed by the materialcustomeffectprocessor class.

After the modelcustomeffectprocessor class, add the materialcustomeffectprocessor class:

[Contentprocessor] public class materialcustomeffectprocessor: materialprocessor {public override materialcontent process (materialcontent input, contentprocessorcontext context) {return base. Process (input, context );}}

From the parameters, we can see that this processor processes materials. By inheriting from the material processor, you use a materialcontent as the input, and then process it to return the updated materialcontent object. This time, because you want to change the method of processing the materialcontent object, you need to override the process method of materialcustomeffectprocessor.

Note:In the modelcustomeffectprocessor class, you overwrite the Processing Methods of all the materialcontent objects in nodeobject. Similarly, because textures and effect are also stored in the materialcontent object, you can also change the processing method of the effectcontent and texturecontent objects by overwriting buildeffect or buildtexture in the materialcustomeffectprocessor class.

Now the process method only calls its base class materialprocessor. Of course, you need to change this method so that you can change the processing process of materialcontent.

Now, change the content of the Process Method to the following code:

Jsontmaterialcontent mymaterial = new jsontmaterialcontent (); string map = path. getdirectoryname (input. identity. sourcefilename); string effectfile = path. combine (MAP, "colorchannels. FX "); mymaterial. effect = new externalreference <effectcontent> (effectfile );

The above Code creates an empty effectmaterialcontent object and stores a link to the custom effect file. First, find the folder where the model is stored and append the name of the effect file. When the compiler runs this line of code, the effect will be added to the material list, in this way, the default effectprocessor's effect can be automatically loaded, but you also ensure that the effect file is stored in the same directory as the model file.

Most models also contain textures. You need to convert the original materialcontent object into a new one. The effect used in this example samples the color from a texture called xtexture, allowing you to set the intensity of the red-green basket color channel separately. Most models have only one texture for each effect, but some have multiple textures (for example, a concave-convex ing, see tutorial 5-15 ). Because it is not associated with the texture serial number of the original effect, this code can only get the last texture of the xtexture variable, but it also shows how to variable multiple textures.

You can access the texture set of the original effect and bind these texture variables to the HLSL texture variable of the custom effect.

 
If (input. textures! = NULL) foreach (string key in input. textures. Keys) mymaterial. textures. Add ("xtexture", input. Textures [Key]);

If you want to adjust some HLSL parameters when loading the model, the following method is used:

Mymaterial. opaquedata. Add ("Hangzhou", 1.1f); mymaterial. opaquedata. Add ("xgreenintensity", 0.8f); mymaterial. opaquedata. Add ("Hangzhou", 0.8f );

Note:In the HLSL effect file, the red, green, and basket Color Channels of each pixel need to be multiplied by this variable. The above Code makes the red color more powerful than other colors, simulating the effect of the sun. This is also useful in simple post-processing effect!

Finally, you need to return the newly created materialcontent. You can directly return it, but it is best to pass this object to the default material processor. This ensures that errors (for example, you do not specify the desired domain) will be corrected. You can do this by calling the base. Process class or using the following code, and the effects are the same.

 
Return context. Convert <materialcontent, materialcontent> (mymaterial, "materialprocessor ");

This line of code searches for the processor called materialprocessor and uses a materialcontent object as the input parameter and generates another materialcontent object. this newly created material object is returned and stored in the model.

Note:Compare this line of code with the last line of code in the convertmaterial method (Translator's note: Return context. Convert <materialcontent, materialcontent> (material, "materialcustomeffectprocessor ")).

Use the custom effect to import the model to the xNa project, and then select the new modelcustomeffectprocessor, as shown in Figure 4-17 (do not select materialcustomeffectprocessor because it is also in the list ).

Figure 4-17 select a custom model Processor

Load this model in the loadcontent method:

 
Mymodel = content. Load <model> ("tank"); modeltransforms = new matrix [mymodel. Bones. Count];

Now your model contains the specified effect! When creating a model, you can set parameters with much clearer code:

 
Mymodel. copyabsolutebonetransformsto (modeltransforms); foreach (modelmesh in mymodel. meshes) {foreach (effect in mesh. effects) {effect. parameters ["xworld"]. setvalue (modeltransforms [mesh. parentbone. index]); effect. parameters ["xview"]. setvalue (fpscam. getviewmatrix (); effect. parameters ["xprojection"]. setvalue (fpscam. getprojectionmatrix (); effect. parameters ["xredintensity"]. setvalue (1.2f);} mesh. draw ();}

This method is clearer than tutorial 4-7.

Code

first, let materialcustomeffectprocessor process each materialcontent object in the model. Of course, you need to define this custom material processor.

Namespace modelcustomeffectpipeline {[contentprocessor] public class modelcustomeffectprocessor: modelprocessor {protected override materialcontent convertmaterial (materialcontent material, contentprocessorcontext context) {return context. convert <materialcontent, materialcontent> (material, "materialcustomeffectprocessor") ;}} [contentprocessor] public class materialcustomeffectprocessor: mater Ialprocessor {public override materialcontent process (materialcontent input, contentprocessorcontext context) {ttmaterialcontent mymaterial = new effectmaterialcontent (); string map = path. getdirectoryname (input. identity. sourcefilename); string effectfile = path. combine (MAP, "colorchannels. FX "); mymaterial. effect = new externalreference <effectcontent> (effectfile); If (input. textures! = NULL) foreach (string key in input. textures. keys) mymaterial. textures. add ("xtexture", input. textures [Key]); mymaterial. opaquedata. add ("xredintensity", 1.1f); mymaterial. opaquedata. add ("xgreenintensity", 0.8f); mymaterial. opaquedata. add ("xblueintensity", 0.8f); Return context. convert <materialcontent, materialcontent> (mymaterial, "materialprocessor ");}}}

Next, import the model to the xNa project, select the custom model processor to process the model and load it:

 
Protected override void loadcontent () {Device = graphics. graphicsdevice; basiceffect = new basiceffect (device, null); ccross = new coordcross (device); mymodel = content. load <model> ("tank"); modeltransforms = new matrix [mymodel. bones. count];}

When this step is performed, the model loads the custom effect, allowing you to set parameters before drawing:

Protected override void draw (gametime) {Device. clear (clearoptions. target | clearoptions. depthbuffer, color. cornflowerblue, 1, 0); ccross. draw (fpscam. viewmatrix, fpscam. projectionmatrix); // draw model matrix worldmatrix = matrix. createscale (0.01f, 0.01f, 0.01f); mymodel. copyabsolutebonetransformsto (modeltransforms); foreach (modelmesh in mymodel. meshes) {foreach (effect in mesh. effects) {effect. parameters ["xworld"]. setvalue (modeltransforms [mesh. parentbone. index] * worldmatrix); effect. parameters ["xview"]. setvalue (fpscam. viewmatrix); effect. parameters ["xprojection"]. setvalue (fpscam. projectionmatrix); effect. parameters ["xredintensity"]. setvalue (1.2f);} mesh. draw ();} base. draw (gametime );}

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.