UA-60303699-2 P2 | Computação Gráfica e Interfaces 2016-2017

Aula Prática 2 (26-30 / Set)

Objetivos

  • Estudo de algumas aplicações dos shaders
  • Tipos de variáveis: constantes (uniform), atributos (attribute) e interpoladas (varying)

Guião

Na aula primeira aula prática necessitámos de usar 2 fragment shaders para podermos pintar quer o interior quer a fronteira dum polígono de cores diferentes. Por causa disso, fomos também obrigados a usar dois programas GLSL e o código tornou-se mais verboso e complicado. Felizmente, há outra forma para alcançar o mesmo objetivo. O que seria útil mesmo era termos a possibilidade de enviar para o programa GLSL, a partir da nossa aplicação javascript, a cor com que pretendemos pintar o polígono.

Exercício 2.1

Pegue no exemplo do triângulo, disponível aqui, e modifique-o por forma a que o fragment shader aceite uma variável uniform do tipo vec4 e com o nome color:

uniform vec4 color;

As alterações no código da aplicação passam por:

  • Obter a localização da variável uniform usando gl.getUniformLocation()
  • Adaptar a função render() para pintar o triângulo e desenhar a sua fronteira
  • Usar a função gl.uniform4fv() para enviar para o programa GLSL a cor que o fragment shader irá usar

Revisão

A solução do exercício 1.7 da aula prática 1 passava por usar também uma variável uniform. Por exemplo, a variável poderia conter informação acerca do deslocamento em x:

uniform float dx;

O vertex shader poderia assim mudar a coordenada dos vértices de acordo:

attribute vec4 vPosition;
uniform float dx;
void main(){
    gl_Position = vPosition;
    gl_Position.x += dx;
}

Já na função render()da nossa aplicação webgl/javascript, necessitaríamos de duas coisas:

  • implementar um ciclo de animação
  • passar para o programa GLSL o valor do deslocamento em x (dx)

Para o primeiro bastaria colocar no final da função render() a seguinte linha de código:

function render() {
    ...
    requestAnimFrame(render);
}
    

A função requestAnimFrame pede ao browser para invocar a função passada por argumento da próxima vez que o browser atualizar o conteúdo da página (tipicamente a cada 1/60 segundos).

A segunda alteração à função render(), para passar a informação acerca do deslocamento, poderia ser qualquer coisa do tipo:

    ...
    gl.uniform1f(..., 0.5*Math.sin(frame));
    ...

sendo frame variável global incrementada a cada passagem pela função render().

Exercício 2.2

Os atributos associados a cada vértice não se limitam à posição dos mesmos no espaço. Neste exercício queremos passar ao programa, não apenas uma posição 2D por cada vértice, mas também uma cor RGB a ele associada. O objetivo é pintarmos um triâgulo com uma cor que varia gradualmente no seu interior, por interpolação das cores associadas a cada vértice.

Passos necessários: - Criar um buffer adicional para conter as cores de cada vértice - Declarar um novo atributo no vertex shader, de nome vColor - Declarar uma variável varying no vertex shader, de nome fColor - Declarar a mesma variável fColor no fragment shader - Adaptar o código de ambos os shaders de acordo com o pretendido.

Eis um possível output do programa:

Smooth colored triangle
Smooth colored triangle

Exercício 2.3

Adapte o exemplo do exercício 2.2 de forma a usar apenas um buffer.

TPC

Exercício 2.4 TPC

Escreva um programa que faça morphing dum polígono noutro. Hint: necessita associar a cada vértice duas posições: a inicial e a final e misturá-las no shader com a função mix().