Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to understand 3D rendering and it seems that everytime you render a new object (A 3D Cube or something) you need to have a new BasicEffect for each Box you render unless you want the exact same texture?

...so if I have over a hundred boxes with each different textures, I need at least as many BasicEffects? Will that not be "too much" for the CPU/GPU in the end or result in lagging? Is there any good way to render multiple objects (cubes or other shapes) at the same time?

I've tried changing the BasicEffect.Texture with each cube drawn, but it resulting in changing the first Cube's texture too.

Any suggestions would be really appreciated, I'm really new to 3D in XNA so I'm trying to wrap my head around the best methods for example render a Map with objects (of shapes).

Example: I create some Cube3D (by providing location and size) and it creates a list of Vertices.

I have to render it this way:

            gameEffect.TextureEnabled = true;
            gameEffect.Texture = gameTexture;
            gameEffect.EnableDefaultLighting();

            foreach (EffectPass pass in gameEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                foreach (Cube3D cube in gameCubes)
                {
                    cube.Render(GraphicsDevice);
                }
            }

...thereby having the same Texture on each Cube. Are there any other ways?

share|improve this question
    
I'm not really familiar with XNA, but you should be able to bind different textures without changing the effects/shaders. As always, batching drawcalls together to minimize the number of texture changes might be worth doing –  melak47 Jun 27 '12 at 16:23
    
But in XNA, rendering a cube requires a BasicEffect (as far as I've learned... might be other ways) and a BasicEffect needs a Texture and if I change it after it drawn one box, the first box will have a new texture. So I have no clue on how to proceed. –  Deukalion Jun 27 '12 at 16:36
    
reoredering draw calls to reduce render state changes is advanced optimization techniquie, i dont think you need that now. You actually dont need BasicEffect, you need just Effect (using your custom shader) but that requires either modification of your draw code or content pipeline that embeds basiceffect to your model. –  Kikaimaru Jun 27 '12 at 18:01
    
I create the shapes and I don't load a model into the world. So for each Box I use DrawPrimitives on a Cube3D.Render(GraphicsDevice device) method, but I first set a BasicEffect to be able to do this and if I set one texture on the BasicEffect and change it, all cubes get changed so to be able to render my Cube I need a BasicEffect of some sort or an effect and then with each different texture it needs a new one, this way at least... –  Deukalion Jun 28 '12 at 12:52
    
In short: I render Primitives, not loaded models and the way I render it now is through the use of BasicEffect, error occurs if I skip the BasicEffect which means I have to have it. But that's probably because I know no better method. Any suggestions? –  Deukalion Jun 28 '12 at 12:54
add comment

3 Answers

It's actually simpler to embed the texture reference with the model itself. That way, when you load your model via the content pipeline, the texture is loaded with it automatically. This thread has some information on that:

http://www.dreamincode.net/forums/topic/227811-how-do-i-put-a-texture-to-a-3d-model/

Then when you draw your scene, you can loop through your models something like:

protected override void Draw(GameTime gameTime)
{
    graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

    // Copy any parent transforms.
    Matrix[] transforms = new Matrix[myModel.Bones.Count];
    myModel.CopyAbsoluteBoneTransformsTo(transforms);

    // Draw the model. A model can have multiple meshes, so loop.
    foreach (ModelMesh mesh in myModel.Meshes)
    {
        // This is where the mesh orientation is set, as well 
        // as our camera and projection.
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.EnableDefaultLighting();
            effect.World = transforms[mesh.ParentBone.Index] * 
                Matrix.CreateRotationY(modelRotation)
                * Matrix.CreateTranslation(modelPosition);
            effect.View = Matrix.CreateLookAt(cameraPosition, 
                Vector3.Zero, Vector3.Up);
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45.0f), aspectRatio, 
                1.0f, 10000.0f);
        }
        // Draw the mesh, using the effects set above.
        mesh.Draw();
    }
    base.Draw(gameTime);
}

This tutorial might help you make sense of loading and drawing 3D models with XNA:

http://msdn.microsoft.com/en-us/library/bb197293(v=xnagamestudio.31).aspx


If you are going to render your own primitives in code, I don't know any other way to apply a texture than a BasicEffect. If Cube3D is your own class, I'd suggest adding a BasicEffect and a Texture2D to the class. That way, you can supply the texture to the Cube3D constructor and it setup the BasicEffect for you. If it's not, you could extend it.

class Cube3D {

    ...
    public BasicEffect Effect { get; set; }
    public Texture2D Texture { 
        get { return Effect.Texture; }
        set { Effect.Texture = value; }
    }
    ...

    public Cube3D( Texture2D t ) {
        ...
        this.Texture = t;
    }

    ...
}

It seems as though you can also use the Effect class to apply a texture as well:

http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2/Textures.php

share|improve this answer
    
That was a "model", what I'm currently interested in are just plain Primitives that I can create shapes out of. For instance, creating boxes and later changing their vertices to custom shapes and not necessarily loading Models with each effect. So if I have 5 cubes (not loaded through a Model.fbx file) and they all have different Textures. Do I need a BasicEffect for each, or do I create a handle that "handles" shapes and pair a shape with a texture (if it already used) otherwise load it. Or something similiar. –  Deukalion Jun 28 '12 at 12:46
    
But that's the problem though, if I have 10 cubes with the exact same BasicEffect / Texture - wouldn't that drag down performance? Having the same texture at multiple locations and a BasicEffect for each Cube. Wouldn't it give more performance to have some kind of handler that "Adds" cubes and when added, it checks if the Texture has been used before and if it has doesn't store the same Texture twice? Therefor having a List of Cubes, a list of Textures and a in the Cube just a reference to the Texture so when we call the handler "Render()" it takes the texture/effect from itself not the cube. –  Deukalion Jun 28 '12 at 15:59
    
There's not much point in optimizing before you even know if you have a problem. Besides, XNA's content manager won't load the same asset twice. If you try, it will just return a reference to the already loaded asset, so you really don't have to worry about dealing with loading multiples of the same texture. –  Cypher Jun 28 '12 at 16:01
    
Ok. But still rendering multiple shapes, do I require to use some kind of effect or are there some other way to do it? Because like my problem is, that I've seen two ways to render a shape. Through a BasicEffect that I apply a texture to, which means each shape needs its own Effect. Our using spriteBatch to render Rectangles. That's about it. Can't seem to find any more "ways" to render multiple objects having different textures at once. –  Deukalion Jun 29 '12 at 8:15
    
How many more ways do you need? :) There are lots of ways to layout the code to do it, but in the end, when texturing primitives you still need to use a BasicEffect or Effect objects (or when rendering sprites with SpriteBatch one or more Texture2D objects). –  Cypher Jun 29 '12 at 15:33
add comment

Unless i am missing something i think that XNA approach is flawed. You shoud have something like this:

class Model
{
   public List<Material> Materials;
   public ModelMesh Mesh;
}

and Model should be created in game by new Model(Content.Load()) and not cached (or loaded by some alternative from xml). Materials should be collection of parameters that you pass to effects inside Mesh.MeshParts[].Effects (like texture)

share|improve this answer
add comment

For drawing multiple objects in XNA you can have one or multiple effects.

If you have only one you must set all parameters (texture, light color, light direction...) for each object before drawing it. All common values for all objects (view and projection matrix for example) can be set once at the beginning of drawing.

If you have multiple effects. For each object exactly one instance. You must set only that parameters that are changing (view and projection matrix, etc..) each frame.

Definitely is not good to create new BasicEffect or load custom effects in Draw method. Create it in Load method.

There are also another method how to draw models in XNA. BasicEffect is actually a shader and you can write your own. Something more about shaders and how to use them you can read here: http://digitalerr0r.wordpress.com/tutorials/

share|improve this answer
    
Yes, I can have multiple effects but the way I've worked right now with primitives (Boxes and Triangles) and not object loaded from an *.fbx file, I have to create an effect for each Shape (Box/Triangle) and that Effect needs a texture if I want to give the Box/Triangle a texture. –  Deukalion Jun 28 '12 at 12:48
    
you can set/unset texture before drawing that primitive –  Vodáček Jun 28 '12 at 15:16
    
...how? changing by using basicEffect.Texture = cube3d.Texture changes all previous textures of the Cubes. –  Deukalion Jun 29 '12 at 8:16
    
I mean all other cubes on screen thats been rendered by the Effect. –  Deukalion Jun 29 '12 at 8:16
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.