2011-01-12 14 views
5

He estado golpeando mi cabeza contra este problema durante horas. Lo que quiero hacer es dibujar un cubo, con diferentes texturas en cada lado; o más específicamente, quiero poder especificar cualquier textura que quiera por cada lado. Para empezar, utilicé el ejemplo here y luego intenté desarrollarlo más, para poder tener más de una textura. Sin embargo, no importa lo que haga, solo utiliza la última textura que se aplica al efecto y no presta atención a ninguna asignación anterior. Aquí está mi clase de forma:Dibujando un cubo con textura con lados múltiples en XNA 4.0

public class BasicShape { 

public Vector3 shapeSize; 
public Vector3 shapePosition; 
private VertexPositionNormalTexture[][] shapeVertices; 
private int shapeTriangles; 
private VertexBuffer shapeBuffer; 
public Texture2D topTexture; 
public Texture2D frontTexture; 
public Texture2D backTexture; 
public Texture2D leftTexture; 
public Texture2D rightTexture; 
public Texture2D bottomTexture; 

public BasicShape(Vector3 size, Vector3 position) { 
    shapeSize = size; 
    shapePosition = position; 
} 

private void BuildShape() { 
    shapeTriangles = 12; 

    shapeVertices = new VertexPositionNormalTexture[6][]; 
    for(int i = 0; i < 6; i++) { 
     shapeVertices[i] = new VertexPositionNormalTexture[6]; 
    } 

    Vector3 topLeftFront = shapePosition + 
    new Vector3(0.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomLeftFront = shapePosition + 
    new Vector3(0.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topRightFront = shapePosition + 
    new Vector3(1.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomRightFront = shapePosition + 
    new Vector3(1.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topLeftBack = shapePosition + 
    new Vector3(0.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 topRightBack = shapePosition + 
    new Vector3(1.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 bottomLeftBack = shapePosition + 
    new Vector3(0.0f, 0.0f, 1.0f) * shapeSize; 
    Vector3 bottomRightBack = shapePosition + 
    new Vector3(1.0f, 0.0f, 1.0f) * shapeSize; 

    Vector3 topLeftFront2 = shapePosition + 
    new Vector3(0.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomLeftFront2 = shapePosition + 
    new Vector3(0.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topRightFront2 = shapePosition + 
    new Vector3(1.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomRightFront2 = shapePosition + 
    new Vector3(1.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topLeftBack2 = shapePosition + 
    new Vector3(0.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 topRightBack2 = shapePosition + 
    new Vector3(1.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 bottomLeftBack2 = shapePosition + 
    new Vector3(0.0f, 0.0f, 1.0f) * shapeSize; 
    Vector3 bottomRightBack2 = shapePosition + 
    new Vector3(1.0f, 0.0f, 1.0f) * shapeSize; 

    Vector3 topLeftFront3 = shapePosition + 
    new Vector3(0.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomLeftFront3 = shapePosition + 
    new Vector3(0.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topRightFront3 = shapePosition + 
    new Vector3(1.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomRightFront3 = shapePosition + 
    new Vector3(1.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 topLeftBack3 = shapePosition + 
    new Vector3(0.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 topRightBack3 = shapePosition + 
    new Vector3(1.0f, 1.0f, 1.0f) * shapeSize; 
    Vector3 bottomLeftBack3 = shapePosition + 
    new Vector3(0.0f, 0.0f, 1.0f) * shapeSize; 
    Vector3 bottomRightBack3 = shapePosition + 
    new Vector3(1.0f, 0.0f, 1.0f) * shapeSize; 

    Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f) * shapeSize; 
    Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f) * shapeSize; 
    Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f) * shapeSize; 
    Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f) * shapeSize; 
    Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f) * shapeSize; 
    Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f) * shapeSize; 

    Vector2 textureTopLeft = new Vector2(1f * shapeSize.X, 0.0f * shapeSize.Y); 
    Vector2 textureTopRight = new Vector2(0.0f * shapeSize.X, 0.0f * shapeSize.Y); 
    Vector2 textureBottomLeft = new Vector2(1f * shapeSize.X, 1f * shapeSize.Y); 
    Vector2 textureBottomRight = new Vector2(0.0f * shapeSize.X, 1f * shapeSize.Y); 

    // Front face. 
    shapeVertices[0][0] = new VertexPositionNormalTexture(
    topLeftFront, frontNormal, textureTopLeft); 
    shapeVertices[0][1] = new VertexPositionNormalTexture(
    bottomLeftFront, frontNormal, textureBottomLeft); 
    shapeVertices[0][2] = new VertexPositionNormalTexture(
    topRightFront, frontNormal, textureTopRight); 
    shapeVertices[0][3] = new VertexPositionNormalTexture(
    bottomLeftFront, frontNormal, textureBottomLeft); 
    shapeVertices[0][4] = new VertexPositionNormalTexture(
    bottomRightFront, frontNormal, textureBottomRight); 
    shapeVertices[0][5] = new VertexPositionNormalTexture(
    topRightFront, frontNormal, textureTopRight); 

    // Back face. 
    shapeVertices[1][0] = new VertexPositionNormalTexture(
    topLeftBack, backNormal, textureTopRight); 
    shapeVertices[1][1] = new VertexPositionNormalTexture(
    topRightBack, backNormal, textureTopLeft); 
    shapeVertices[1][2] = new VertexPositionNormalTexture(
    bottomLeftBack, backNormal, textureBottomRight); 
    shapeVertices[1][3] = new VertexPositionNormalTexture(
    bottomLeftBack, backNormal, textureBottomRight); 
    shapeVertices[1][4] = new VertexPositionNormalTexture(
    topRightBack, backNormal, textureTopLeft); 
    shapeVertices[1][5] = new VertexPositionNormalTexture(
    bottomRightBack, backNormal, textureBottomLeft); 

    // Top face. 
    shapeVertices[2][0] = new VertexPositionNormalTexture(
    topLeftFront2, topNormal, textureBottomLeft); 
    shapeVertices[2][1] = new VertexPositionNormalTexture(
    topRightBack2, topNormal, textureTopRight); 
    shapeVertices[2][2] = new VertexPositionNormalTexture(
    topLeftBack2, topNormal, textureTopLeft); 
    shapeVertices[2][3] = new VertexPositionNormalTexture(
    topLeftFront2, topNormal, textureBottomLeft); 
    shapeVertices[2][4] = new VertexPositionNormalTexture(
    topRightFront2, topNormal, textureBottomRight); 
    shapeVertices[2][5] = new VertexPositionNormalTexture(
    topRightBack2, topNormal, textureTopRight); 

    // Bottom face. 
    shapeVertices[3][0] = new VertexPositionNormalTexture(
    bottomLeftFront2, bottomNormal, textureTopLeft); 
    shapeVertices[3][1] = new VertexPositionNormalTexture(
    bottomLeftBack2, bottomNormal, textureBottomLeft); 
    shapeVertices[3][2] = new VertexPositionNormalTexture(
    bottomRightBack2, bottomNormal, textureBottomRight); 
    shapeVertices[3][3] = new VertexPositionNormalTexture(
    bottomLeftFront2, bottomNormal, textureTopLeft); 
    shapeVertices[3][4] = new VertexPositionNormalTexture(
    bottomRightBack2, bottomNormal, textureBottomRight); 
    shapeVertices[3][5] = new VertexPositionNormalTexture(
    bottomRightFront2, bottomNormal, textureTopRight); 

    // Left face. 
    shapeVertices[4][0] = new VertexPositionNormalTexture(
    topLeftFront3, leftNormal, textureTopRight); 
    shapeVertices[4][1] = new VertexPositionNormalTexture(
    bottomLeftBack3, leftNormal, textureBottomLeft); 
    shapeVertices[4][2] = new VertexPositionNormalTexture(
    bottomLeftFront3, leftNormal, textureBottomRight); 
    shapeVertices[4][3] = new VertexPositionNormalTexture(
    topLeftBack3, leftNormal, textureTopLeft); 
    shapeVertices[4][4] = new VertexPositionNormalTexture(
    bottomLeftBack3, leftNormal, textureBottomLeft); 
    shapeVertices[4][5] = new VertexPositionNormalTexture(
    topLeftFront3, leftNormal, textureTopRight); 

    // Right face. 
    shapeVertices[5][0] = new VertexPositionNormalTexture(
    topRightFront3, rightNormal, textureTopLeft); 
    shapeVertices[5][1] = new VertexPositionNormalTexture(
    bottomRightFront3, rightNormal, textureBottomLeft); 
    shapeVertices[5][2] = new VertexPositionNormalTexture(
    bottomRightBack3, rightNormal, textureBottomRight); 
    shapeVertices[5][3] = new VertexPositionNormalTexture(
    topRightBack3, rightNormal, textureTopRight); 
    shapeVertices[5][4] = new VertexPositionNormalTexture(
    topRightFront3, rightNormal, textureTopLeft); 
    shapeVertices[5][5] = new VertexPositionNormalTexture(
    bottomRightBack3, rightNormal, textureBottomRight); 
} 

public void SetTopTexture(Texture2D tex) { 
    topTexture = tex; 
} 
public void SetSideTexture(Texture2D tex) { 
    frontTexture = tex; 
    backTexture = tex; 
    leftTexture = tex; 
    rightTexture = tex; 
} 
public void SetBottomTexture(Texture2D tex) { 
    bottomTexture = tex; 
} 

public void RenderShape(GraphicsDevice device, Effect effect) { 
    BuildShape(); 


    effect.Parameters["xTexture"].SetValue(topTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[2], 0, 2); 
    effect.Parameters["xTexture"].SetValue(bottomTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[3], 0, 2); 
    effect.Parameters["xTexture"].SetValue(frontTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[0], 0, 2); 
    effect.Parameters["xTexture"].SetValue(backTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[1], 0, 2); 
    effect.Parameters["xTexture"].SetValue(leftTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[4], 0, 2); 
    effect.Parameters["xTexture"].SetValue(rightTexture); 
    device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[5], 0, 2); 

} 

}

Y en el método de sorteo de mi juego:

cubeEffect.CurrentTechnique = cubeEffect.Techniques["Textured"]; 
    foreach(EffectPass pass in cubeEffect.CurrentTechnique.Passes) { 
     pass.Apply(); 
     BasicShape s = new BasicShape(new Vector3(1, 1, 1), new Vector3(0, 0, 3)); 
     s.SetTopTexture(TextureLoader.GetTexture(4)); 
     s.SetSideTexture(TextureLoader.GetTexture(35)); 
     s.SetBottomTexture(TextureLoader.GetTexture(4)); 
     s.RenderShape(GraphicsDevice, cubeEffect); 

    } 

Como se puede ver, yo estoy cargando diferentes texturas, sin embargo, el resultado es este :

my cube http://www.tinyimg.org/images/769MinecraftClassic_2011_.bmp

estoy seguro de que las texturas son diferentes, sin embargo, la misma textura se dibuja en todos los lados. ¿Necesito un efecto separado para cada lado? Eso definitivamente parece excesivo.

+0

¿Ha verificado que 'TextureLoader.GetTexture (35)' está volviendo lo que se espera que vuelva? – ChrisF

+0

@ChrisF - Bueno, la textura 35 es la única que muestra la textura, así que supongo que sí. Además, si tomo las dos primeras filas del código de dibujo en RenderShape y lo coloco al final, se renderiza la textura 4. Por lo tanto, solo está representando la última textura aplicada. – Bevin

+0

Parece una información útil que debe incluir en su pregunta. Sin embargo, no puedo ayudar con la respuesta: no estoy tan familiarizado con xna. – ChrisF

Respuesta

4

Cualquier parámetro establecido en el efecto no se aplica hasta que llame a EffectPass.Apply(). Esto se debe a que la aplicación de cambios a un efecto es costosa y es posible que desee realizar varios cambios de una vez.

Su función RenderShape debería ser algo como:

public void RenderShape(GraphicsDevice device, Effect effect) 
{ 
    BuildShape(); 

    foreach (EffectPass pass in effect.CurrentTechnique.Passes) 
    { 
     effect.Parameters["xTexture"].SetValue(topTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[2], 0, 2); 

     effect.Parameters["xTexture"].SetValue(bottomTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[3], 0, 2); 

     effect.Parameters["xTexture"].SetValue(frontTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[0], 0, 2); 

     effect.Parameters["xTexture"].SetValue(backTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[1], 0, 2); 

     effect.Parameters["xTexture"].SetValue(leftTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[4], 0, 2); 

     effect.Parameters["xTexture"].SetValue(rightTexture); 
     pass.Apply(); 
     device.DrawUserPrimitives(PrimitiveType.TriangleList, shapeVertices[5], 0, 2); 
    } 
} 
+0

@Empyrean - Entonces, ¿estás diciendo que esta no es la forma recomendada de hacerlo? ¿Cuál sería una forma más rápida? Voy a tener que dibujar muchos de estos cubos, por lo que debo optimizarlo tanto como sea posible. – Bevin

+0

Por lo general, solo puede hacer unos cientos de cambios de estado (llamados lotes) antes de encontrarse con problemas de rendimiento. En su código, la representación de cada cubo consta de 6 lotes. Eso significa que probablemente puedas renderizar menos de 100 cubos antes de que tu velocidad de fotogramas comience a ser inaceptable. Desea la menor cantidad posible de llamadas de sorteo, de modo que dibuje todas las caras de cubo con la misma textura en una llamada de sorteo. Mejor aún, combine sus seis texturas en una sola textura (textura atlasing). Además, los búferes de vértices son mucho más rápidos en PC que las llamadas DrawUserPrimitive. – Empyrean

+0

La manera más rápida sería utilizar el atlasing de texturas y representar todos los cubos en una sola llamada utilizando el búfer de vértices estático o dinámico dependiendo de si los cubos se mueven o no. Si algunos de ellos no se mueven, use un búfer de vértices estático para esos y un búfer de vértices dinámico para los que sí lo hacen. También debería usar índices para evitar el uso de vértices duplicados. Los vértices duplicados tienen que transformarse y pueden transformarse de forma ligeramente diferente dando lugar a las mallas. – Empyrean

Cuestiones relacionadas