Envie Artigos e Concorra a Prêmios
 
Artigos
Article List
Texturizando Primitivas Graficas com XNA
Texturizacao com mapeamentos parciais, completos e com um grid de Imagens. Alem de texturizar pontos.
Enviado por Luciano José em 4/5/2008 0:00:00

 

Para melhor proveito do material abaixo, será admitido que você tenha conhecimento nos tópicos:

Primitivas Gráficas com XNA – Artigo vital para o entendimento do que será proposto ao longo de todo o material
 
 
Usando um banco ou grid de imagens com o XNA – Esse artigo será vital para a 2º Demonstração abordada mais adiante.
 
 

Introdução

 
Texturização é o ato de aplicar imagens à superfície de objetos primitivos.
Qualquer objeto que aparece em um jogo, foi texturizado; foi aplicado uma textura(um objeto retangular, composto por texels) a algum ou alguns objetos primitivos que formam, na maioria das vezes, um retângulo.
 
Os pontos(texels) da textura podem ser acessadas através de coordenadas, geralmente conhecidas como UV ou mesmo XY.
 
Quando se vai texturizar algo, essas coordenadas, UV ou XY, podem assumir como valor mínimo 0(zero) e valor máximo 1.


Essas coordenadas(UV ou XY) informam um ponto na textura. Entenda os valores mínimos e máximos das coordenadas estando entre 0% e 100%. Observe o esquema abaixo:
 
  • Valor Mínimo: 0(zero) - um ponto da textura que equivale a 0%
 
  • Qualquer valor entre 0 e 1, por exemplo: 0.5f - um ponto da textura que equivale a 50% - 0.25f - um ponto da textura que equivale a 25%
 
  • Valor Máximo: 1 equivalendo a 100%
 
Essas equivalências valem tanto para a largura(X ou U) como para a altura(Y ou V) da textura.
 

Tipos de Vértices que possibilitam a texturização

 
O XNA FrameWork provê 3 tipos de vértices que permitem armazenar, e conseqüentemente, permitem que uma textura seja aplicada a este(s) objeto(s) primitivo(s):
  • VertexPositionTexture
  • VertexPositionColorTexture
  • VertexPositionNormalTexture
Para as demonstrações abaixo, será utilizado o tipo de vértice: VertexPositionTexture.
Esse tipo de vértice(VertexPositionTexture) armazena a posição em que o vértice estará no espaço e também, a coordenada da textura a ser mapeada para o vértice.
 

1º Demonstração – Texturização parcial e Total de Texturas em objetos retangulares

O responsável pela texturização é o Shader. Nas demonstrações abaixo, será utilizado o Shader provido pelo XNA FrameWork, o objeto BasicEffect.

///
/// Shader provido pelo XNA.
/// Reponsavel por renderizar as primitivas
///
BasicEffect basicEffect; 

Levando em consideração que uma textura é um objeto retangular e para representá-lo, na maioria dos casos precisa-se de no mínimo 4 vértices. Para o propósito deste material, como anunciado anteriormente, os vértices serão do tipo VertexPositionTexture. 

Nesta demonstração, serão utilizadas 2 “retângulos independentes” para aplicar a mesma textura com formas diferentes de mapeamento. Abaixo, observe os 2 arrays de vértices que “abraçarão” os vértices e suas propriedades de posição e coordenadas da textura.
///
/// Será aplicada uma textura completa
///
VertexPositionTexture[] fullTextureTriangleFan;
 
///
/// Será aplicada uma textura parcial; uma parte da textura,
/// neste caso, será a metade
///
VertexPositionTexture[] partialTextureTriangleFan;
 
O método LoadContent desta demonstração:
protected override void LoadContent()
{
. . .
 
//Os 2 metodos de definição, foram chamados no metodo LoadContent,
//pelo fato deles utilizarem valores da instância textura
this.define_FULL_Rectangular_Object(this.posicaoDaTexturaCompleta);
this.define_Partial_Rectangular_Object(this.posicaoDaTexturaParcial);
 
this.basicEffect = new BasicEffect(this.GraphicsDevice, null);
 
. . .
 
//Abilita a texturização; permiti que a textura seja aplicada           
this.basicEffect.TextureEnabled = true;
 
/*À toda primitiva renderizada por este efeito(basicEffect), e
* que tem a capacidade de guardar coordenadas de textura,
* a ela será aplicada esta textura*/           
this.basicEffect.Texture = textura;
 
base.LoadContent();
}
Toda essa 1º Demonstração, vai girar em torno destes 2 métodos: define_FULL_Rectangular_Object e define_Partial_Rectangular_Object.
 

Acessando pontos da textura

Inicialmente serão definidos 4 vértices do tipo VertexPositionTexture. Observe nas imagens abaixo, como seriam definidas as coordenadas de Textura dos 4 vértices, se o objetivo fosse:
 
  • obter uma textura mapeada por completo na superfície delimitada pelos 4 vértices:
 
      Foto 1
 

O código do método define_FULL_Rectangular_Object, faz o que foi abordado no ponto acima, e também, o que está sendo mostrado Foto 1:

 

///
/// Define um objeto retangular para o array de vertices FullTextureTriangleFan
///
///A Textura será renderizada a partir desse ponto
void define_FULL_Rectangular_Object(Vector2 posicao)
{
 
   //Instanciado os 4 vertices
            this.fullTextureTriangleFan = new VertexPositionTexture[4];
 
            fullTextureTriangleFan[0].Position.X = posicao.X;
            fullTextureTriangleFan[0].Position.Y = posicao.Y;
            fullTextureTriangleFan[0].TextureCoordinate = new Vector2(0, 0);
 
            fullTextureTriangleFan[1].Position.X = posicao.X + this.textura.Width;
            fullTextureTriangleFan[1].Position.Y = posicao.Y;
            fullTextureTriangleFan[1].TextureCoordinate = new Vector2(1, 0);
 
            fullTextureTriangleFan[2].Position.X = posicao.X + this.textura.Width;
            fullTextureTriangleFan[2].Position.Y = posicao.Y + this.textura.Height;
            fullTextureTriangleFan[2].TextureCoordinate = new Vector2(1, 1);
 
            fullTextureTriangleFan[3].Position.X = posicao.X;
            fullTextureTriangleFan[3].Position.Y = posicao.Y + this.textura.Height;
            fullTextureTriangleFan[3].TextureCoordinate = new Vector2(0, 1);
  }
 
  • Obter uma textura mapeada parcialmente na superfície delimitada pelos 4 vértices.

Foto 2 – Texturizando 100% da altura da textura e 50% da largura da textura. Toda a região escurecida será desprezada.

 

Observe na foto abaixo(Foto 3) que tanto a largura como a altura entre um vértice e outro, quando se comparado a Foto 1. Entretanto, o objetivo aqui, é mapear a textura parcialmente, e por padrão, quando o que foi mapeado da textura for menor que a superfície do objeto retangular(os vértices dispostos de forma retangular), isso será “esticado” para preencher toda a superfície do objeto retangular. A Foto 3 demonstra o que aconteceu: 

 
 
Foto 3 – Apenas a metade da textura(a metade das larguras) foi mapeada, então, como a superfície formada pelos vértices é maior que essa região mapeada, a textura será “esticada” para preencher.
 

O código do método define_Partial_Rectangular_Object, faz o que foi discutido neste ponto:

 

        ///
        /// Define um objeto retangular para o array de vertices PartialTextureTriangleFan
        ///
        ///A Textura será renderizada a partir desse ponto
        void define_Partial_Rectangular_Object(Vector2 posicao)
        {
            //Instanciado os 4 vertices
            this.partialTextureTriangleFan = new VertexPositionTexture[4];
 
            partialTextureTriangleFan[0].Position.X = posicao.X;
            partialTextureTriangleFan[0].Position.Y = posicao.Y;
            partialTextureTriangleFan[0].TextureCoordinate = new Vector2(0, 0);
 
            partialTextureTriangleFan[1].Position.X = posicao.X + this.textura.Width;
            partialTextureTriangleFan[1].Position.Y = posicao.Y;
            partialTextureTriangleFan[1].TextureCoordinate = new Vector2(0.5f, 0);
 
            partialTextureTriangleFan[2].Position.X = posicao.X + this.textura.Width;
            partialTextureTriangleFan[2].Position.Y = posicao.Y + this.textura.Height;
            partialTextureTriangleFan[2].TextureCoordinate = new Vector2(0.5f, 1);
 
            partialTextureTriangleFan[3].Position.X = posicao.X;
            partialTextureTriangleFan[3].Position.Y = posicao.Y + this.textura.Height;
            partialTextureTriangleFan[3].TextureCoordinate = new Vector2(0, 1);
        }
 

O resultado final com o modo de preenchimento FillMode.WireFrame dos 2 objetos retangulares definidos:

Foto 4

 

O resultado final com o modo de preenchimento padrão, o FillMode.Solid:

Foto 5
 
Projeto para Download:  texturizandoumretangulo.zip 262363 bytes
 

2º Demonstração – Texturização com um grid de Imagens 

 

 Quando uma textura for mapeada por completa, e a região da superfície dos vérticies, for menor que toda textura mapeada – toda a região fora dos limites da superfície dos vértices, não será mostrada na tela.

Esse conhecimento será útil para desenhar alguma região interna de um grid de imagens. Nesta demonstração, praticamente toda a classe Game1 é semelhante ao código da 1º demonstração. O que muda de fato, é o método que irá definir o array de vértices.
 

Observe o grid que será utilizado:

Imagens – Grid de imagens retirado do artigo publicado no SharpGames - Usando um banco ou grid de imagens com o XNA

 

O resultado final obtido será semelhante ao que foi mostrado no artigo de André Furtado: Usando um banco ou grid de imagens com o XNA
 

 

 

Campos Relevantes para esta demonstração

 
          ///
        /// A posicao do passarinho vermelho na tela
        ///
        Vector2 posicao1;
 
        ///
        /// A posicao do passarinho verde na tela
        ///
        Vector2 posicao2;
 
        ///
        /// Os campos (X,Y) do retangulo vão determinar a origem do local
        /// aonde o retangulo será definido na textura.
        ///
        Rectangle rectangle1;
 
        ///
        /// Os campos (X,Y) do retangulo vão determinar a origem do local
        /// aonde o retangulo será definido na textura.
        ///
        Rectangle rectangle2;
 

O método Initialize inicializando os campos acima, com os mesmo valores utilizados no Artigo Usando um banco ou grid de imagens com o XNA:

 

protected override void Initialize()
{
 
            // posicao do passarinho vermelho na tela
            this.posicao1 = Vector2.Zero;
 
            //Nesta demonstração, a posicao(X e Y) e
            //dimensões(Width e Height) escolhidas servirão para
            // mostrar o passarinho vermelho
            this.rectangle1 = new Rectangle(275, 0, 140, 90);
 
            // posicao do passarinho verde na tela
            this.posicao2 = new Vector2(200, 200);
 
            //Nesta demonstração, a posicao(X e Y) e
            //dimensões(Width e Height) escolhidas servirão para
            // mostrar o passarinho verde
            this.rectangle2 = new Rectangle(275, 90, 140, 75);
 
            base.Initialize();          
}

O método LoadContent chamando os métodos de construção do objeto retangular para desenhar alguma imagem isolada na textura:

 

protected override void LoadContent()
{
            ...
 
            this.define_Rectangular_Object(this.posicao1,
                this.rectangle1, ref this.triangleFan1);
 
            this.define_Rectangular_Object(this.posicao2,
                this.rectangle2, ref this.triangleFan2);
            ...
}

Observe o método de definição; o método principal desta demonstração:

        ///
        /// Define um objeto retangular para o array de vertices PartialTextureTriangleFan
        ///
        ///Posicao em que a imagem será desenhada na janela(Game Window
        ///Um retangulo que sera definido dentro da textura; sera
        /// este local retangular que será renderizado
        ///Array de vertices
        void define_Rectangular_Object(Vector2 posicao,           
            Rectangle rectangle,
            ref VertexPositionTexture[] triangleFan)
        {
            triangleFan = new VertexPositionTexture[4];
 
            float originWidthProportion = rectangle.X / (float)this.texture.Width;
            float originHeightProportion = rectangle.Y / (float)this.texture.Height;
 
            float Widthproportion = rectangle.Width / (float)this.texture.Width;
            float Heightproportion = rectangle.Height / (float)this.texture.Height;
 
            triangleFan[0].Position.X = posicao.X;
            triangleFan[0].Position.Y = posicao.Y;
            triangleFan[0].TextureCoordinate
                = new Vector2(originWidthProportion, originHeightProportion);
 
            triangleFan[1].Position.X = posicao.X + rectangle.Width;
            triangleFan[1].Position.Y = posicao.Y;
            triangleFan[1].TextureCoordinate =
                new Vector2(Widthproportion + originWidthProportion, originHeightProportion);
 
            triangleFan[2].Position.X = posicao.X + rectangle.Width;
            triangleFan[2].Position.Y = posicao.Y + rectangle.Height;
            triangleFan[2].TextureCoordinate =
                new Vector2(Widthproportion + originWidthProportion, Heightproportion + originHeightProportion);
 
            triangleFan[3].Position.X = posicao.X;
            triangleFan[3].Position.Y = posicao.Y + rectangle.Height;
            triangleFan[3].TextureCoordinate =
                new Vector2(originWidthProportion, Heightproportion + originHeightProportion);
        }

 

 

O resultado final com o modo de preenchimento FillMode.WireFrame dos 2 objetos retangulares definidos:

Foto 6

O resultado final com o modo de preenchimento padrão, o FillMode.Solid:

Foto 7

 

Projeto para Download:  texturizacaocomumgriddeimagens.zip 99466 bytes

 

3º Demonstração – Texturizando Pontos 

Nesta demonstração, o tipo de primitiva utilizado será: PrimitiveType.PointList.

Observe a imagem abaixo e veja os vários pontos:

 
Foto 8 – Uma lista de pontos; 25 pontos distribuídos na tela 


O intuito dessa demonstração é aplicar uma textura a cada um desses pontos. Na Foto 8, as texturas já estão aplicadas, mas visualizá-las no tamanho atual dos pontos, está inviável.


Para aumentar o tamanho dos pontos você terá que modificar o valor padrão desta propriedade:

this.graphics.GraphicsDevice.RenderState.PointSize 


A propriedade PointSize recebe um float


Nesta demonstração, o valor atribuído foi 50


No método LoadContent, será colocada as 2 linhas de código: 


this.graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;
this.graphics.GraphicsDevice.RenderState.PointSize = 50;


A 1º linha, permiti(caso seja true) ou não(caso seja false) o completo mapeamento da textura no ponto. Mesmo this.basicEffect.TextureEnabled sendo true, a textura não será aplicada se essa propriedade(PointSpriteEnable) for false.


Se tratando do Efeito provido pelo XNA(BasicEffect), tenha em mente que ao aplicar texturas a pontos, as texturas podem ser mapeadas apenas por completas – não é possível mapear parcialmente uma textura.


Na 2º linha, o tamanho do ponto, que antes era 1.0f, agora foi modificado para 50;


Abaixo, observe os 25 pontos sem estarem texturizados, porém com as suas dimensões modificadas:

Foto 9 – Pontos com dimensões 50x50(50 pixels de largura e altura)


Abaixo, observe os 25 pontos texturizados:

Foto 10 

Projeto para Download:  texturizandopontos.zip 63622 bytes 

Todas as imagens* acima, foram criadas e/ou editadas com a ferramenta Microsoft Expression Design 2 Beta.

*com exceção do grid de Imagens

Dúvidas, Críticas e Sugestões são bem-vindas. 

Obrigado!

 

 


Sobre o Autor

???
Não Definido
Não Definido
Ocorreu um erro.
Ocorreu um erro.


Clique para avaliar:

Comentários

Adicione seu Comentário
juegos gratis
PrêmiosMinimizar

Envie um artigo para o Sharpgames, colabore com a comunidade e fique famoso! Clique aqui e saiba mais.

Logos do XBox 360, XNA e Games For Windows
Copyright 2010 por SharpgamesPolítica de Privacidade  |  Termos de Uso