<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Blog do H]]></title><description><![CDATA[Blog do H]]></description><link>https://henriquereis.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 15 Oct 2026 13:52:26 GMT</lastBuildDate><atom:link href="https://henriquereis.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Como Criar a Textura de Xadrez Perfeita Com Unity ShaderGraph]]></title><description><![CDATA[O Começo da Jornada
Durante a fase de prototipagem de um jogo, é comum usar uma textura xadrez para os objetos do mundo. Essa textura ajuda a dar uma noção de profundidade, escala e outras coisas. Por esses motivos, decidi implementar esse padrão no ...]]></description><link>https://henriquereis.hashnode.dev/como-criar-a-textura-de-xadrez-perfeita-com-unity-shadergraph</link><guid isPermaLink="true">https://henriquereis.hashnode.dev/como-criar-a-textura-de-xadrez-perfeita-com-unity-shadergraph</guid><category><![CDATA[unity]]></category><category><![CDATA[texture]]></category><category><![CDATA[Procedural Generation]]></category><category><![CDATA[checkerboard]]></category><category><![CDATA[checker]]></category><dc:creator><![CDATA[Henrique Reis]]></dc:creator><pubDate>Tue, 03 Feb 2026 12:28:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769810223683/34f0baf9-bba3-4b5b-a594-b575e155b737.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-o-comeco-da-jornada">O Começo da Jornada</h2>
<p>Durante a fase de prototipagem de um jogo, é comum usar uma textura xadrez para os objetos do mundo. Essa textura ajuda a dar uma noção de profundidade, escala e outras coisas. Por esses motivos, decidi implementar esse padrão no meu projeto. No entanto, essa tarefa acabou sendo muito mais trabalhosa do que eu pensava.</p>
<h3 id="heading-por-que-nao-usar-apenas-um-png">Por que não usar apenas um .png?</h3>
<p>Criar um padrão de xadrez na Unity parecia uma tarefa simples para mim, até perceber que a maioria dos tutoriais sobre o assunto se limita a aplicar uma textura a um objeto ou usar apenas o nó <strong>Checkerboard</strong> puro do Shader Graph. O problema dessas abordagens, se você deseja uma textura de xadrez bem feita, é que, <mark>ao aplicar isso a um objeto e depois alterar a escala dele em apenas um dos eixos, a textura acaba se distorcendo</mark>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769822215187/121bfdca-a799-49b1-9258-0af4dc65290c.gif" alt="Textura esticando ao alterar a escala apenas no eixo Y do objeto." class="image--center mx-auto" /></p>
<h3 id="heading-o-problema-do-no-triplanar-nativo-do-shader-graph-para-este-tipo-de-textura">O problema do nó Triplanar nativo do Shader Graph para este tipo de textura</h3>
<p>Tentei resolver o problema do esticamento da textura usando o nó <strong>Triplanar</strong>, e funcionou bem para objetos como um plano ou um cubo. O problema surgiu quando apliquei isso a objetos curvados, como uma esfera.</p>
<p>foi então que percebi que o nó <strong>Triplanar</strong> funciona bem para misturar texturas orgânicas, como terra ou grama, mas <mark>não é eficaz para padrões geométricos contrastantes, como uma textura xadrez</mark>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769828790975/164d3a76-66f0-45de-b94e-064a35c387e7.webp" alt="Comparação entre a textura aplicada em um cubo e em uma esfera." class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-o-segredo-para-implementar-o-padrao-xadrez">O segredo para implementar o padrão xadrez</h2>
<p>Minha motivação para escrever este tutorial veio da minha própria frustração. Passei semanas buscando uma solução para criar um padrão procedural que respeitasse a escala do objeto e funcionasse bem em superfícies curvas.</p>
<p>Eu sei pouco sobre shaders e, sem encontrar uma solução pronta, comecei a testar várias ideias. Uma delas foi tentar recriar o nó <strong>Triplanar</strong> manualmente no Shader Graph. Isso me ensinou algo crucial para resolver o problema: <mark>isolar as faces de um objeto</mark>.</p>
<p>Então, pensei: "Se preciso evitar que a textura do objeto estique, primeiro eu tenho que <strong>isolar as faces do objeto</strong> e depois aplicar o padrão xadrez <strong>considerando a escala do objeto</strong>."</p>
<h3 id="heading-isolando-as-faces-do-objeto">Isolando as faces do objeto</h3>
<p>Todo objeto tem faces, e essas faces sempre apontam em uma direção, que chamamos de <strong>normais</strong>. A intensidade da luz que atinge as faces de um objeto curvado é calculada com base na diferença entre a <strong>direção da luz</strong> e a <strong>direção dessas normais</strong>, por exemplo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769863789720/822700d1-a35f-42e2-9377-d0f19798bf31.gif" alt="Exibindo as normais de uma esfera." class="image--center mx-auto" /></p>
<p>Com base nesse raciocínio, as faces do objeto que estão voltadas na direção da luz serão iluminadas. À medida que as faces se curvam na direção oposta, a intensidade da luz que incide sobre o objeto diminui gradualmente.</p>
<p>É muito importante lembrar disso, pois nos mostra que podemos identificar <strong>a proximidade entre duas direções</strong> (dois vetores).</p>
<h3 id="heading-dot-product">Dot Product</h3>
<p>O <strong>Produto Escalar</strong> (ou Dot Product) é a maneira como conseguimos medir <mark>o quanto um vetor está apontado para outro</mark>, em outras palavras, funciona como um “termometro de direções”. Podemos visualizar o <strong>Produto Escalar</strong> funcionando mais ou menos da seguinte forma:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Direções das Faces (Normals)</strong></td><td><strong>Resultado do Dot Product (Número)</strong></td><td><strong>O que o Shader “vê”</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Totalmente Alinhadas</td><td>1</td><td>Completamente Branco</td></tr>
<tr>
<td>Perpendiculares</td><td>0</td><td>Cinza</td></tr>
<tr>
<td>Totalmente Opostas</td><td>-1</td><td>Completamente Preto</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769881158439/ab9fcf95-8b84-44bf-80d3-5b8d0ec27455.gif" alt="Uma representação do Dot Product." class="image--center mx-auto" /></p>
<p>Sabendo disso, podemos criar uma <strong>máscara</strong> para <strong>isolar</strong> as faces de um objeto que estão na <strong>direção</strong> de <strong>alguma coisa</strong>.</p>
<h3 id="heading-criando-as-mascaras-de-eixo">Criando as máscaras de eixo</h3>
<p>Como discutimos anteriormente, nós precisamos <strong>isolar cada face</strong> do nosso objeto antes de aplicarmos a textura. Isso significa que vamos ter que criar uma <strong>máscara</strong> para <strong>cada um dos dois eixos</strong> e essa <strong>máscara</strong> será responsavel por <strong>isolar</strong> as <strong>faces do objeto</strong> que estão <mark>apenas naquele eixo específico</mark>.</p>
<p>Para implementar isso, precisamos da <strong>direção</strong> para onde as <strong>faces do objeto</strong> estão voltadas (<strong>Normal Vector: Object</strong>) e do <strong>eixo</strong> que queremos <strong>isolar</strong>. Em seguida, usamos o <strong>Dot Product</strong> com essas duas informações para selecionar <mark>apenas as faces que apontam para esse eixo</mark>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769869625179/670775fd-62c0-4d75-9f8e-47f426f050f9.webp" alt="Nó Normal Vector: Object e Nó Vector3 (1, 0, 0) no Nó Dot Product e o resultado em um Nó Absolute." class="image--center mx-auto" /></p>
<p>Nessa configuração de nós, estamos pegando as direções das faces do objeto e comparando com a direção que o <strong>eixo X</strong> (Horizontal) está apontando. Isso retorna todas as faces do objeto que <strong>estão de frente para</strong> o eixo X.</p>
<p>Se pararmos por aqui, existirá um problema. Nós vamos ter apenas as faces que estão <strong>viradas de frente</strong> para o <strong>eixo X</strong>, porém o nosso objeto também tem faces <strong>viradas de costas</strong> para o <strong>mesmo eixo</strong>.</p>
<p>Por esse motivo eu estou passando o resultado desse nó <strong>Dot Product</strong> por um nó <strong>Absolute</strong>, isso básicamente diz para o shader que “<mark>queremos tanto as faces que estão apontadas para as </mark> <strong><mark>direções positivas</mark></strong> <mark>(</mark><strong><mark>de frente</mark></strong><mark>), como para as </mark> <strong><mark>direções negativas</mark></strong> <mark>(</mark><strong><mark>de costas</mark></strong><mark>)</mark> do <strong>eixo X”</strong>.</p>
<p>Se você repetir esses passos também para os outros dois eixos restantes (<strong>Y</strong> e <strong>Z</strong>), conseguirá obter <strong>3 máscaras</strong>, cada uma dessas máscaras é capaz de isolar as faces do objeto que estão apenas em um eixo específico.</p>
<p>Nesse passo, usamos o eixo <strong>X</strong> como exemplo mas caso esteja com dúvida, esses são os vetores que representam cada eixo:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Vetor</strong></td><td><strong>Eixo</strong></td></tr>
</thead>
<tbody>
<tr>
<td>(1, 0, 0)</td><td>X</td></tr>
<tr>
<td>(0, 1, 0)</td><td>Y</td></tr>
<tr>
<td>(0, 0, 1)</td><td>Z</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769972842480/2479bd3e-fbd4-46f5-abca-c6cc5358f50b.webp" alt="As 3 máscaras de eixo, cada uma isolando as faces de seu próprio eixo." class="image--center mx-auto" /></p>
<h3 id="heading-configurando-o-no-checkerboard">Configurando o nó Checkerboard</h3>
<p>Agora que temos as <strong>3 máscaras</strong> <strong>de eixo</strong>, utilizaremos um <strong>nó Checkerboard</strong> para gerarmos a nossa textura de xadrez <strong>proceduralmente</strong>. No entanto, precisamos garantir que a nossa textura de xadrez não se estique para nenhum dos <strong>3 eixos</strong>.</p>
<p><mark>A grande sacada aqui é </mark> <strong><mark>ajustar</mark></strong> <mark>o número de quadrados de acordo com a </mark> <strong><mark>escala do nosso objeto</mark></strong>. Isso faz com que a textura <strong>se ajuste</strong>, <strong>aumentando ou diminuindo</strong> o número de quadrados ao invés de esticar enquanto a <strong>escala do objeto</strong> muda.</p>
<p>O nó <strong>Checkerboard</strong> nativo do <strong>Shadergraph</strong> tem uma entrada chamada <strong>Frequency</strong>, essa entrada controla a <strong>quantidade de quadrados</strong> que a textura vai ter. A nossa missão é apenas fazer com que o <strong>Frequency</strong> “saiba” a <strong>escala do objeto</strong> e ajuste a <strong>quantidade de quadrados</strong> <mark>sempre se baseando nessa escala</mark>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769883310632/5f88d49d-1a67-4359-9487-c6cff3b09f92.webp" alt="Um Nó Object com o Scale Passando por um Nó Split, O G do Split indo para o Y de Um Vetor 2 e o B do Split indo para o X, o resultado do Vetor 2 é Multiplicado por uma propriedade Tilling e o resultado é ligado a um Nó Checkerboard." class="image--center mx-auto" /></p>
<p>Nessa configuração, usamos a saída <strong>Scale</strong> de um nó <strong>Object,</strong> essa saída retorna exatamente um <strong>Vector3</strong> com a <strong>escala do nosso objeto</strong>. Ao passar essa saída por um nó <strong>Split</strong>, nós separamos os <strong>3 valores</strong> que compõem esse <strong>Vector3</strong> da <strong>escala</strong> do nosso objeto, dessa maneira podemos acessar esses valores individualmente.</p>
<p>O nó Split separa os eixos da escala do nosso objeto da seguinte maneira:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Saída</td><td>Eixo</td></tr>
</thead>
<tbody>
<tr>
<td>R</td><td>X</td></tr>
<tr>
<td>G</td><td>Y</td></tr>
<tr>
<td>B</td><td>Z</td></tr>
</tbody>
</table>
</div><p>Essa textura será aplicada apenas nas faces do nosso objeto que estão no eixo X. Sabendo disso, para garantir que a textura não estique nas faces que estão no eixo X, precisamos utilizar as escalas corretas como referência para a entrada do <strong>Frequency</strong>.</p>
<p>Pense nisso da seguinte maneira: O <strong>Frequency</strong> recebe apenas um <strong>Vector2</strong>. Isso acontece porque você está trabalhando com a escala de uma <strong>textura 2D</strong>, como essa textura vai ser aplicada <strong>apenas nas faces do objeto que estão no eixo X do mundo</strong> nós podemos <mark>ignorar a escala do objeto para esse eixo</mark>. por isso estamos pegando apenas os <strong>eixos Y</strong> e <strong>Z</strong> do <strong>Split</strong> nesse exemplo.</p>
<p>Para montar esse <strong>Vector2</strong>, certifique-se sempre de ignorar o <strong>valor de escala</strong> do <strong>eixo para qual a textura será aplicada</strong>, assim como no exemplo acima que <strong>estamos ignorando o eixo X do Split</strong>. <mark>Como a textura já vai ser aplicada no eixo X, o valor da escala desse eixo não vai ser útil em nada para o ajuste da nossa textura</mark>.</p>
<p>Agora nós temos o <strong>Vector2</strong> que vai servir para “dizer” ao nosso <strong>Frequency</strong> em qual eixo que a nossa textura deve <strong>ajustar o tamanho</strong>, evitando o esticamento. Depois disso eu multiplico esse <strong>Vector2</strong> por uma <strong>propriedade</strong>, para poder controlar a <strong>quantidade de quarados na textura</strong> pelo próprio <strong>inspetor da unity</strong>.</p>
<p>Se você repetir essa <strong>configuração de nós</strong> para que a textura se ajuste também nos <strong>outros eixos</strong> (<strong>Y</strong> e <strong>Z</strong>), o resultado final será <strong>3 texturas</strong>, cada uma configurada para <strong>ajustar</strong> a quantidade de quadrados <strong>em um eixo específico</strong> de acordo com a <strong>escala do objeto</strong>.</p>
<h3 id="heading-aplicando-as-textura-nas-mascaras">Aplicando as textura nas máscaras</h3>
<p>Temos tudo o que precisamos para finalizar a nossa textura procedural de xadrez, basta ligarmos as texuras nas máscaras e conectarmos tudo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769975267542/ba3c7df7-41a3-4a0c-8fc7-04f0724caf8b.webp" alt="Aplicação da textura na máscara do eixo X." class="image--center mx-auto" /></p>
<p>Depois disso, basta somar os 3 nós Lerp com as texturas de cada eixo e ligar o resultado no base color. caso tenha alguma dúvida, veja o <a target="_blank" href="https://drive.google.com/drive/folders/1fEK8cWXebW4PJkSBL80uyawM5cfYi6KE?usp=sharing">gráfico completo aqui</a>.</p>
<p>Agora não importa o quão grande ou pequeno seja o objeto em um único eixo, a textura nunca vai ficar esticada e você pode aplicar essa ela em objetos curvos também sem que a mesclagem deixe a cor do objeto distorcida.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769978126380/83b7b087-4e61-47bb-aa8a-a3e9a5bfcf36.webp" alt class="image--center mx-auto" /></p>
]]></content:encoded></item></channel></rss>