Realidade Virtual Aula 6 Remis Balaniuk Conteúdo • Nessa aula estudaremos como definir propriedades das luzes e dos materiais. • O render gráfico das cores e outros efeitos nos objetos depende da combinação de características das fontes de luz e dos materiais que compõem os objetos. Cores • Basearemos nosso estudo no modelo de cores RGB (red green blue), que define a proporção entre as 3 cores básicas para definir a cor desejada. • Cores no OpenGL e no Chai são definidos por 4 valores numéricos reais, RGBA, sendo que o último, chamado Alpha, controla a opacidade do objeto. Luzes • Como visto na aula 3, para que a cena virtual seja visível é necessário que pelo seja definida menos uma fonte de luz. • Uma luz é definida por uma série de parâmetros: – – – – Ser posicional ou direcional Posição Direção Cores: • • • • Ambiente Difusa Refletida Emitida Luzes • Definindo o tipo: posicional ou direcional – Uma luz pode ser definida como estando numa posição no infinito ou próxima à cena. – O efeito de ter uma luz no infinito é que seus raios são considerados como sendo paralelos. – Esse tipo de luz é chamado de “direcional”, uma vez que só importa a direção de onde vem. – Equivalente à luz do sol. – Uma luz próxima à cena é chamada de “posicional”. – Sua posição e direção fazem diferença no efeito de iluminação. – Equivalente à luz de uma lâmpada. Luzes • No Chai o tipo de fonte de luz é definido pelo método: //! Set this light to be purely directional (true) or purely positional (false) void setDirectionalLight(bool a_directionalLight) { m_directionalLight = a_directionalLight; } Luzes • Para a luz direcional só é necessário definir o parâmetro de posição: light->setPos(cVector3d(2,1,1)); • Embora soe contraditório, é em função da posição que a direção de onde vem a luz é definida. Luzes • Para a luz posicional é necessário definir além posição, a direção da luz. light2->setPos(cVector3d(-2,1,1)); light2->setDirectionalLight(true); light2->setDir(cVector3d(2,-1,-1)); • A luz direcional é como uma lanterna, que forma um cone de luz. • Para definir o cone é preciso definir um ângulo: light2->setCutOffAngle(30); • um ângulo de 180 equivale a uma luz emitindo em todas as direções. Luzes • Para a luz posicional é possível ainda definir como o luz dentro do cone é distribuída. – A atenuação define como a intensidade da luz diminui com a distância entre a fonte e os objetos iluminados. – O fator de atenuação é calculado usando a seguinte equação: 1 att k c kl d k q d 2 • onde d é a distância entre a luz e o vértice, kc é a constante de atenuação, kl é a atenuação linear e kq a atenuação quadrática. Luzes • No Chai a definição da atenuação se faz pelos métodos: //! Set my constant attenuation parameter void setAttConstant(const GLfloat& a_value) { m_attConstant = cClamp(a_value, 0.0f, 1.0f); } //! Read my constant attenuation parameter GLfloat getAttConstant() const { return (m_attConstant); } //! Set my linear attenuation parameter void setAttLinear(const GLfloat& a_value) { m_attLinear = cClamp(a_value, 0.0f, 1.0f); } //! Read my linear attenuation parameter GLfloat getAttLinear() const { return (m_attLinear); } //! Set my quadratic attenuation parameter void setAttQuadratic(const GLfloat& a_value) { m_attQuadratic = cClamp(a_value, 0.0f, 1.0f); } //! Read my quadratic attenuation parameter GLfloat getAttQuadratic() const { return (m_attQuadratic); } Cores x Luzes • O modelo de iluminação do OpenGL considera a luz emanada de uma cena como vindo de diferentes fontes: – Luz vinda diretamente de uma fonte (dirigida diffuse) – Luz vinda do reflexo da luz em um objeto (refletida specular) – Luz vinda do reflexo em múltiplos objetos e superfícies (ambiente - ambient) – Luz vinda da emissão de um objeto (emitida emissive) • Não adiciona luz à cena no OpenGL, só na intensidade da cor do objeto. Cores x Luzes • O modelo de iluminação do OpenGL considera que tanto uma fontes de luz quanto o material de que é feito um objeto que a reflete podem ser descritos definindo a cor que cada tipo de luz (da classificação do slide anterior) tem. Cores x Luzes • No Chai tanto as luzes (cLight) como os materiais (cMaterial) possuem as propriedades abaixo: //! Ambient light component. cColorf m_ambient; //! Diffuse light component. cColorf m_diffuse; //! Specular light component. cColorf m_specular; Definindo cores das luzes • A cor de uma luz indica qual frequência de luz ela emite. • Por exemplo, um quarto iluminado por uma luz branca mas com paredes predominantemente vermelhas poderia ter a seguinte configuração de cores: light->m_ambient.set( 1.0, 0.0, 0.0, 1.0); light-> m_diffuse.set( 1.0, 1.0, 1.0, 1.0); • Normalmente a luz refletida (specular) e a luz dirigida (diffuse) tem a mesma cor Materiais • Definindo um material: – Classe cMaterial – Um objeto qualquer pode estar associado a um material através da propriedade m_material: cMaterial material2; bola2->m_material = material2; – Configuração de um material: • • • • Cores Brilho Fricção Dureza Materiais • As cores são definidas como dito anteriormente: material2.m_ambient.set( 0.0, 0.9, 0.2, 1.0 ); material2.m_diffuse.set( 0.8, 0.6, 0.6, 1.0 ); material2.m_specular.set( 0.9, 0.9, 0.9, 1.0 ); • No caso de um objeto a definição dessas cores diz quais frequências de luz (cores) ele reflete. – Um objeto de cor vermelha ao receber luz branca absorve as cores verde e azul e reflete a vermelha. – Se um objeto vermelho recebe só luz verde ele não reflete nada (parece preto). – Os valores dos parâmetros RGB nesse caso não indicam uma proporção. – Cada valor indica quanto de cada cor é refletida (1 para reflexão total, 0 para nenhuma reflexão). – Assim a sequência (1,1,1) indica branco e (0.1,0.1,0.1) indica um cinza escuro). Materiais • Normalmente num material as cores diffuse (dirigida) e ambient (ambiente) são idênticas (para ser coerente com relação à sua cor). • Já a luz specular (refletida) é normalmente branca (para um material com brilho) ou cinza (para um material opaco). Materiais x luzes • Combinando cores das luzes e dos materiais para definir a aparência do objeto: – O OpenGL calcula a cor de um objeto combinando os componentes specular, diffuse e ambient das luzes e do objeto. – Por exemplo, se uma luz tem um componente da cor (LR,LG,LB) e o objeto tem o mesmo componente como (OR,OG,OB) o calculo da cor desse componente é obtido com (LR.OR, LG.OG, LB.OB). Brilho • O Chai permite a definição do brilho de um objeto usando o método abaixo: //! Set shininess (the exponent used for specular lighting) void setShininess(GLuint a_shininess); //! Get shininess GLuint getShininess() { return (m_shininess); } Transparências • É possível configurar um objeto para que pareça transparente. • Isso se faz no OpenGL usando uma opção chamada “blending”, que ao mostrar um objeto na tela leva em consideração não só a superfície mais próxima da câmera, mas também as ocultas e também os objetos atrás dele. • O controle no OpenGL da transparência se faz através do parâmetro alpha, que é o último da definição RGBA da cor. Transparências no Chai • No Chai um objeto transparente é definido usando os métodos abaixo: cubo1->enableTransparency(true); cubo1->setTransparencyLevel(0.6); • o método setTransparencyLevel define quanto o objeto é transparente, sendo 0 totalmente transparente e 1 totalmente opcao. Texturas • A textura permite que se cubra a superfície de um objeto 3D com um padrão ou imagem. • Uma textura é normalmente uma imagem bidimensional. • Existem texturas tridimensionais, mas que só fazem sentido para objetos cujo volume interno do objeto é preenchido por elementos geométricos (voxels). • Nesses objetos é possível traçar cortes e ver o seu interior, o que num objeto cujo modelo se limita à superfície externa resultaria num objeto oco. Texturas • As texturas permitem enriquecer o realismo de uma cena e simplificar a sua modelagem geométrica. • Uma parede de tijolos aparentes, por exemplo, precisaria de um grande número de polígonos para descrever cada tijolo, sendo que usando textura com a foto de uma parede é possível definir a parede com dois triângulos ter os detalhes dos tijolos como simples efeito gráfico. • Esse recurso é largamente utilizado em aplicações gráficas para criar o efeito de paisagens e outros fotorealismos. • Reflexos do ambiente em objetos brilhantes também são conseguidos por texturas. Texturas • A textura é normalmente um bitmap como da figura ao lado. • Ela pode ser “colada” à superfície do objeto ou combinada com as propriedades do material associado ao objeto. • A definição de texturas bidimensionais exige um trabalho quase manual de definir para cada vértice da superfície poligonal onde esse se encontra dentro do bitmap. • Para criar uma textura realista é preciso buscar uma continuidade do padrão de um triângulo ao próximo. • Isso exige um cálculo cuidadoso do posicionamento dos vértices dentro do y bitmap, principalmente nos cantos e partes não planas do objeto. x Texturas no Chai • O Chai possui a classe cTexture2D que permite a definição de texturas bidimensionais. cTexture2D *textura = new cTexture2D(); bool sim=textura->loadFromFile("teste.bmp"); object->setTexture(textura); • o método “loadFromFile” permite a carga do bitmap no objeto textura. • O método setTexture permite associar um objeto cTexture2D a um cMesh. Texturas no Chai • A definição das coordenadas dos vértices dentro da textura se faz pelo método setTexCoord da classe cVertex: int p1 = object->newVertex(-0.5*largura+dx, 0.5*largura+dy, 0.5*largura+dz); object->getVertex(p1)->setTexCoord(0,0); • As coordenadas na textura devem variar entre 0 e 1, sendo (0,0) o extremo superior esquerdo do bitmap e (1,1) o extremos inferior direito. • Note que as coordenadas são relativas ao bitmap e não absolutas. • Dessa forma não importa o tamanho do bitmap carregado. Texturas no Chai • Se tiver sido definido a cor dos vértices ou o material do objeto, a textura é combinada a essas propriedades para gerar a imagem. Exercícios 1) Experimentar variações de materiais e fontes de iluminação no projeto da mesa giratória. 2) Aplicar a textura bricks.bmp aos pilares da mesa giratória.