Curso completo de DarkGdk
Gameprog - Escola de programação de jogos digitais
Contato: gameprog.br@gmail.com
Fase 21.1
21.1 Introdução aos Shaders
1. Visão geral
A ilustração acima traz a imagem de 3 caixas texturizadas. A terceira delas,
que está destacada em vermelho, foi texturizada pela placa de vídeo utilizando o
recurso dos shaders. Repare que a textura da terceira caixa é uma combinação
da primeira e da segunda textura exibidas nas primeiras caixas. Esse efeito foi
produzindo utilizando-se o recurso de shader da placa de vídeo.
O shader é um recurso programável da placa de vídeo que oferece serviços de textura,
iluminação, mapeamento e reposicionamento de vértices de um objeto 3d. É um recurso
poderoso que por si só demanda um novo curso para ser assimilado e aqui vamos manter
apenas essa breve introdução ao assunto.
Visto que o shader é programável, então ele se torna ideal para realizar efeitos
dinâmicos de textura, iluminação e transformação dos objetos de uma cena 3d.
O shader é programado utilizando uma linguagem própria desse recurso chamada HLSL,
high level shader language, com a nossa tradução de linguagem shader de alto nível.
Geralmente o shader é concebido em duas partes, o vertex shader que faz o
posicionamento dos objetos na cena, e o pixel shader que controla a cor final
dos pixels da imagem final renderizada.
A DarkGdk embute linguagen HLSL em um arquivo de texto com a extensão .dbs, que
depois é compilado internamente ou externamente para arquivos de efeito com a
extensão .fx; os dados compilados são enviados para a placa de vídeo junto com
as texturas e o conjunto de vértices que formam uma cena 3d.
2.Funções de shaders e efeitos especiais
-------------------------------------------------------------------------------
void dbLoadEffect ( char* pFilename, int iEffectID, int iUseDefaultTextures );
dbLoadEffect ( sArquivo_fx_dbs, nObj_fx, nUsarTexturaDefault);
Essa função carrega um arquivo de efeito que pode ter extensão .fx ou .dbs.
sArquivo_fx_dbs String que representa o nome do arquivo fx ou dbs
nObj_fx Handle numérico para o efeito ser utilizado por outras
funções
nUsarTexturaDefault Habilita (1) ou desabilita (0) o uso de texturas default
Este parâmetro está mal documentado na documentação
original da DarkGdk. Conserve o valor 1 que a função
carrega automaticamente as texturas apontadas dentro
do arquivo de efeito.
É importante destacar que as texturas usadas pelo efeito devem estar
na mesma pasta que contém o arquivo do efeito. As texturas serão
carregadas automaticamente.
Exemplo:
const int obj_fx = 1;
dbSetDir ("c:\\gameprog\\gdkmedia\\shader");
dbLoadEffect ( "DetailMapping.dbs", obj_fx, 1 );
-------------------------------------------------------------------------------
void dbSetObjectEffect( int iID, int iEffectID );
dbSetObjectEffect ( nObj, int nObj_fx);
Esta função aplica um efeito (nObj_fx) no objeto especificado (nObj).
Exemplo:
const int obj_fx = 1;
const int obj = 1;
dbSetDir ("c:\\gameprog\\gdkmedia\\shader");
dbLoadEffect ( "DetailMapping.dbs", obj_fx, 1 );
dbSetObjectEffect ( obj, obj_fx );
-------------------------------------------------------------------------------
void dbSetEffectConstantFloat ( int iEffectID, char* pConstantName, float fValue );
dbSetEffectConstantFloat ( nObj_fx , sAtributo, nValor);
Essa função configura a propriedade ou atributo (sAtributo) do efeito especificado
(nObj_fx) com o valor dado (nValor.)
Exemplo:
void tst_shader(int obj)
{
const int obj_fx = 1;
dbSetDir ("c:\\gameprog\\gdkmedia\\shader");
dbLoadEffect ( "DetailMapping.dbs", obj_fx, 1 );
dbSetObjectEffect ( obj, obj_fx );
dbSetEffectConstantFloat ( obj_fx, "detailScale", 1.0f );
}
Essa pequena função acima ilustra como carregar, aplicar e reconfigurar um
atributo de um efeito. Fica aqui agora a recomendação da pesquisa para
você descobrir mais sobre shaders e atributos modificáveis. Segue abaixo
o programa completo.
// shader01.cpp
// Esse programa mostra como utilizar shaders
#include "DarkGDK.h"
// Protótipo das funções
void initsys(); // inicializa o sistema
void tst_shader(int obj); // Testa de shader 01
// Posição do modelo 3d
float xobj_pos = 1020, yobj_pos = 300, zobj_pos = 0;
// ----------------------------------------------------------------------------
void DarkGDK ( void ) {
// Começo da aplicação DarkGdk
const int obj_caixa_01 = 1;
const int obj_caixa_02 = 2;
const int obj_caixa_03 = 3;
const int obj_caixa_04 = 4;
// Configuração inicial de exibição
initsys();
// Criação básica da matriz
dbMakeMatrix (1,2000,10000,10,50);
// Vamos fazer uma caixa e texturizar com um shader
dbMakeObjectBox (obj_caixa_01, 200,200,200);
tst_shader(obj_caixa_01);
// Posiciona a caixa no mundo
dbPositionObject (obj_caixa_01, xobj_pos, yobj_pos, zobj_pos);
// Vamos produzir objetos de apoio para mostrar os passos do shader
dbMakeObjectBox (obj_caixa_02, 200, 200, 200);
dbMakeObjectBox (obj_caixa_03, 200, 200, 200);
dbMakeObjectBox (obj_caixa_04, 200, 200, 200);
dbPositionObject (obj_caixa_02, 700, 550, 200);
dbPositionObject (obj_caixa_03, 1020, 550, 200);
dbPositionObject (obj_caixa_04, 1350, 550, 200);
dbSetDir ("c:\\gameprog\\gdkmedia\\shader");
dbLoadImage ("ground.jpg", 2); dbTextureObject (obj_caixa_02, 2);
dbLoadImage ("door1.jpg", 3); dbTextureObject (obj_caixa_03, 3);
tst_shader(obj_caixa_04);
// Posiciona a camera
dbPositionCamera (1005, 475, -500);
dbSyncOn();
// Looping principal
while ( LoopGDK ( ) )
{
// Gire a caixa_01 para a esquerda
dbTurnObjectLeft (obj_caixa_01, 1);
dbSync ( );
} // fim do while
dbDeleteMatrix (1); dbDeleteObject (1);
return;
} // fim da função: DarkGDK
// ----------------------------------------------------------------------------
void initsys() {
// Esta função inicializa o sistema
dbSyncOn( );
dbSetWindowTitle("shader01.cpp");
dbSetAmbientLight(100);
} // initsys().fim
void tst_shader(int obj)
{
// Essa função carrega um arquivo de efeito, reconfigura um atributo
// aplica o efeito no objeto especificado por obj
const int obj_fx = 1;
dbSetDir ("c:\\gameprog\\gdkmedia\\shader");
dbLoadEffect ( "DetailMapping.dbs", obj_fx, 1 );
dbSetObjectEffect ( obj, obj_fx );
dbSetEffectConstantFloat ( obj_fx, "detailScale", 1.0f );
}