Português – artigo semi-técnico – fuja enquanto é capaz 🙂

A Game Engine do Blender (BGE) utiliza um sistema de filtros 2D muito interessante. Ele permite a você utilizar a linguagem GLSL para escrever seus próprios filtros, que por sua vez são aplicados à tela.

Basicamente o Blender desenha um retângulo em cima da tela da Game Engine, com um fragment shader GLSL aplicado a ele. Simples e engenhoso. Pode não ser a coisa mais rápida do mundo, mas funciona bem.

O filtro é basicamente um loop dentro da imagem aplicada ao retângulo, que para cada pixel da imagem, são feito alguns cálculos (o shader propriamente dito) e o pixel é alterado de acordo com seu filtro. Com isso pode-se obter desde efeitos simples de desfocagem, nitidez, sépia, até efeitos mais avançados como DoF (profundidade visual) e SSAO (iluminação global aproximada).

Além de contar com a imagem que se vê no jogo (o chamado color buffer, ou GL_RGBA) ainda pode-se acessar o mapa de luminância (GL_LUMINANCE) e o mapa de profundidade (GL_DEPTH).

O que ainda não dava para fazer era passar uma imagem qualquer que você quisesse para ser usada dentro do shader … e aqui começa minha diversão 🙂

English

Sometimes I wonder how many people use the 2dfilter system in the Blender Game Engine. Anyways, even though this feature demands a nice graphic card, it’s really fun to play with it.

You can even make your own custom shaders. Basically you load some textures from Blender and use them in your filter.

Originally we have three diferent textures: the color (bgl_RenderedTexture), the luminance (bgl_LuminanceTexture) and the depth (bgl_DepthTexture).

Each one of them correspond to an openGL buffer (respectively GL_RGBA, GL_LUMINANCE and GL_DEPTH).However, some GLSL shaders may need other textures as input.

As an example I can think in the effect we have in some games when we run out of the water. In games like Crysis and Turok you can see the water running through the screen, as if you were getting dryer.

Inspired by that, I started to figure out a way to pass a new, custom texture straight to the shader.

If you click in the image below you can see my fullscreenshot with the LogicBricks and the shader script.

GLSL_Screenshot_01

How can I do that?

The first step to implement something serious in Blender would be to discuss with the developers and see the better design/implementation for this feature.

However I didn’t want to bother anyone else before I had some code working.

I was already studying openGL to help solving some issues with the texcoord system of the 2d filter. It helped me to understand whatelse I would need to study, and keep reading.

11 tutorials, and delicious 400 pages later, I got what I have now 🙂

This is working in the way it’s supposed to be. However I’m still in my first steps in this level of programming. For of you can help with ideas, tips reviews, comments, it will be very helpful.

The solution so far

Right now I created a new option in the 2D Filter Actuator to select a new or existing image.

Internally, I’m passing the image as a parameter to the file that handles the filters. There I’m reading the parameter bindcode from the image, which is its address in the graphic card once the texture is created for the game.

Then I’m passing a new uniform to the shader called bgl_Texture_01 which is basically the image created with the bindcode we got.

Now using the shader code below, you can access this custom texture and use it the way you want 🙂

Porquê? O quê? Como?

Uma das coisas que mais gosto no Blender é o fato de poder mexer no código-fonte. Eu demorei um bocado de tempo pra tomar coragem e ir adquirindo intimidade com as entranhas do programa. Desde o começo tive bastante ajuda dos desenvolvedores através da internet, e fui cada vez mais tomando gosto pela coisa.

Interessante é que boa parte dos programadores que ajudam no desenvolvimento do Blender são pessoas que como eu não tem formação oficial. Quando eu comecei a me dar conta de que não era só eu que estava tendo que aprender enquanto eu programava, me senti bem mais confiante e inspirado para continuar estudando e programando.

Dessa vez foi a hora de enfim estudar openGL. Arrumei bons tutoriais para iniciantes na internet, e assim que comecei a sentir o gostinho dos meus primeiros programas, eu parti para a leitura do Red Book, o melhor livro que existe para quem quer entender os fundamentos desta linguagem de programação.

Depois de algumas horas programando, copiando e colando código que nem prova no colégio, consegui criar uma nova opção para o 2DFilter Actuator para se selecionar uma imagem existente.

Com isso armado e funcionando minimanente, eu parti pra finalizar meu código de teste.

No final eu consegui passar uma nova textura para o shader. Você pode acessá-la pelo nome bgl_Texture_01, e se usar o código abaixo você obtém o resultado da imagem acima 🙂

uniform sampler2D bgl_Texture_01;
uniform sampler2D bgl_RenderedTexture;
uniform sampler2D bgl_DepthTexture;
void main()
{vec2 texcoord = gl_TexCoord[0].st;
vec2 cancoord = gl_TexCoord[3].st;

vec4 foreground = texture2D(bgl_Texture_01, cancoord);
vec4 foreground2 = texture2D(bgl_RenderedTexture, texcoord);

float m_depth = texture2D(bgl_DepthTexture, texcoord).s;
if (cancoord.s < cancoord.t){
if (m_depth > 0.99995) {
foreground2 = foreground;
}
}

gl_FragColor = foreground2;

}

Português

Fiquei tão contente que tenha dado certo, que achei que valia perder umas 3 horas de sono escrevendo este artigo 😉 Eu ainda tenho que corrigir um tanto de coisa, mas para quem quiser testar o patch que eu fiz, fique ciente de que:

1) Eu não consigo gravar a informação da textura selecionada no Actuator quando se salva o arquivo. Portanto salve o arquivo ANTES de selecionar a imagem que você queira usar, selecione a imagem, se diverta, e se quiser testar de novo abra o arquivo original.

2) A imagem selecionada tem que estar aplicada a algum objeto.

3) Eu ainda preciso corrigir a interface. O que eu tenho agora é uma adaptação acochambrada do sistema de seleção de imagens para Background Image.

4) Só dá pra usar com uma textura de cada vez, eu ainda tenho que transformar isso num código de verdade 🙂

Agora é mais pra testes mesmo.

The END ainda é só o começo …

Enfim, como eu disse no começo eu não sei o quão útil este tipo de função é.

Pra mim é super útil. Não necessariamente como uma ferramenta em si, mas como um caminho de aprendizado.

Esta é mais uma grande vantagem do código aberto. Com um pouco de tempo, algum material de referência (tutoriais, livros) e ajuda, todos têm à disposição um enorme repositório para se estudar.

Imagina ter que fazer sua própria Game Engine pra entender como GLSL funciona?

Ou então mesmo para começar, ter que configurar um projeto, compilador, bibliotecas, dependências … é tanta coisa junta que se eu não tivesse a minha disposição um programa prontinho, rodando, não sei se teria tempo de aprender a COMEÇAR a mexer no código.

Enfim, obrigado pela visita ao site. Sei que o blog tem visitantes dos mais diversos possíveis (de gente procurando por desenho de moda a caranguejos – coisas do google) então espero que se divirta navegando por aqui.

Um grande abraço,

Dalai

PS.: Se você quiser mais alguns detalhes técnicos dá uma lida na parte em inglês também que eu acabei sendo mais técnico lá.

PS.2: Chora cavaco 🙂

English

I was so happy that it was working, that here I am writing about it 🙂

However there are still a lot of things to do and the main problems so far are:

1) I can’t store the image information with the actuator in a proper way. It beats me. It’s not the first time I customize actuators, however now I have no clue what is going wrong.

Therefore if I save and open the file, it either crashes Blender or I need to re-select a texture to my actuator.

2) Since I’m using the bindcode as a parameter directly, it will only work if the texture has been created already. For you need to apply iy to an object first.

3) The function EnableFilter() in RAS_2DFilterManager.cpp is been called every frame instead of only once. Apparently this is a bug/problem in Blender. Since I pass the parameter through this function, I’m passing the parameter multiple times. Not a big deal though.

4) I need to fix the GUI. Right now I adapted the texture buttons creation function from the Background Image float panel. It still needs adjustments.

5) And a lot of other “details” such as: managing/passing multiple textures, creating non active textures, organizing better the code …

Forewords

So as you can see this is not likely to be released any time soon. I don’t even know if this feature would be that useful.

However it has been a great learning experience for me. Now I don’t have more troubles managing CMakeLists.txt, structs, pointers, and a few other crazy elements of C++ and Blender code.

I hope to get it done any time soon, and I would appreciate any feedback in this matter.

Thank you for reading, I hope you find it interesting. One more day in my coder-to-be journey 🙂

And I also would like to thank Hamed Zaghaghi for all his hard-work in the implementation of the 2dfilter, thanks Davide Vercelli for the NeHe tutorial link (it really helped my first steps) and special thanks to Mike Pan for the support, incentives and the shaders he will code using this (you can wait to finish your exams, don’t worry =D )

Cheers,

Dalai Felinto

Links

Artigos relacionados:

5 Thoughts on “2D Filters, GLSL e Custom Textures

  1. Wow, I am speechless. This is amazing.

  2. This feature would be immensely useful for things like costume switching, swapping terrain textures depending on weather, and a number of other purposes. Thanks for working on it and proving that it’s possible! I hope that – one way or another – something like this gets integrated into Blender someday. 🙂

  3. @Mike: thanks 😉 looking forward for your feedback in terms of interaction, GUI, …

    @Clean3d:
    Thanks for reading, and I’m glad you liked.
    Right now texture changing is already possible in BGE.
    You need a Blender build more recent than Blender 2.48a and the VideoTexture (a new built-in feature) (eg):
    http://vimeo.com/2170430

  4. Mandoragon on April 10, 2009 at 10:23 am said:

    Hi, you mentioned some 11 tutorials that you read that helped you with this, I’m hoping to do my dissertation with blender next year at Newcastle University in UK which means that the summer is going to have me reading a lot.

    Were you at York University, I’m sure you mentioned the city somewhere cause that’s where I was born…

  5. @ Hi Mandoragon.

    The 11 tutorials I mentioned are the first 11 from NeHe website.

    There are 48 openGL lessons there, but after the 11th one I dropped them by the openGL red book. I like books better than internet pages, that’s why.

    “I’m hoping to do my dissertation with blender next year at Newcastle University in UK”

    That’s really nice. I’m glad my dissertation (or whatever name an undergrad final paper name has) is also on Blender. More specifically on using Blender Game Engine to display virtual architectural environments in a Dome. I’m glad to put school hours in Blender coding 🙂

    “Were you at York University ?”
    I WAS at York University. I’m no longer there though 🙂
    I was leaving on campus, taking some art and urban studies classes. It’s a nice city, but extremely cold. I eventually realized Vancouver will be a better place to return (not so cold after all).

    But well I loved Canada. Congratulations for your country =D

Post Navigation