Browse Source

Initial commit

OpenGL boilerplate by Benoit Ozell
Packets code taken from https://github.com/jeschke/water-wave-packets
master
lhark 6 years ago
commit
b57310b38c
  1. 1264
      Packets.cpp
  2. 147
      Packets.h
  3. 44
      constants.h
  4. 3070
      inf2705.h
  5. 33
      makefile
  6. 141
      nuanceurFragmentsSolution.glsl
  7. 73
      nuanceurGeometrieSolution.glsl
  8. 130
      nuanceurSommetsSolution.glsl
  9. 954
      ripple.cpp
  10. BIN
      textures/TestIsland.bmp

1264
Packets.cpp

File diff suppressed because it is too large

147
Packets.h

@ -0,0 +1,147 @@
// Taken from https://github.com/jeschke/water-wave-packets
#pragma once
#include "constants.h"
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
// simulation parameters
#define PACKET_SPLIT_ANGLE 0.95105f // direction angle variation threshold: 0.95105=18 degree
#define PACKET_SPLIT_DISPERSION 0.3f // if the fastest wave in a packet traveled PACKET_SPLIT_DISPERSION*Envelopesize ahead, or the slowest by the same amount behind, subdivide this packet into two wavelength intervals
#define PACKET_KILL_AMPLITUDE_DERIV 0.0001f // waves below this maximum amplitude derivative gets killed
#define PACKET_BLEND_TRAVEL_FACTOR 1.0f // in order to be fully blended (appear or disappear), any wave must travel PACKET_BLEND_TRAVEL_FACTOR times "envelope size" in space (1.0 is standard)
#define PACKET_ENVELOPE_SIZE_FACTOR 3.0f // size of the envelope relative to wavelength (determines how many "bumps" appear)
#define PACKET_ENVELOPE_MINSIZE 0.02f // minimum envelope size in meters (smallest expected feature)
#define PACKET_ENVELOPE_MAXSIZE 10.0f // maximum envelope size in meters (largest expected feature)
#define PACKET_BOUNCE_FREQSPLIT true // (boolean) should a wave packet produce smaller waves at a bounce/reflection (->widen the wavelength interval of this packet)?
#define PACKET_BOUNCE_FREQSPLIT_K 31.4f // if k_L is smaller than this value (lambda = 20cm), the wave is (potentially) split after a bounce
#define MAX_SPEEDNESS 0.07f // all wave amplitudes a are limited to a <= MAX_SPEEDNESS*2.0*M_PI/k
// physical parameters
#define SIGMA 0.074f // surface tension N/m at 20 grad celsius
#define GRAVITY 9.81f // GRAVITY m/s^2
#define DENSITY 998.2071f // water density at 20 degree celsius
#define KINEMATIC_VISCOSITY 0.0000089f // kinematic viscosity
#define PACKET_SLOWAVE_K 143.1405792f // k of the slowest possible wave packet
#define PACKET_SLOWAVE_W0 40.2646141f // w_0 of the slowest possible wave packet
// memory management
#define PACKET_BUFFER_DELTA 500000 // initial number of vertices, packet memory will be increased on demand by this stepsize
struct WAVE_PACKET
{
// positions, directions, speed of the tracked vertices
Vector2f pos1,pos2,pos3; // 2D position
Vector2f dir1,dir2,dir3; // current movement direction
float speed1,speed2,speed3; // speed of the particle
Vector2f pOld1,pOld2,pOld3; // position in last timestep (needed to handle bouncing)
Vector2f dOld1,dOld2,dOld3; // direction in last timestep (needed to handle bouncing)
float sOld1,sOld2,sOld3; // speed in last timestep (needed to handle bouncing)
Vector2f midPos; // middle position (tracked each timestep, used for rendering)
Vector2f travelDir; // travel direction (tracked each timestep, used for rendering)
float bending; // point used for circular arc bending of the wave function inside envelope
// bouncing and sliding
bool bounced1, bounced2, bounced3; // indicates if this vertex bounced in this timestep
bool sliding3; // indicates if the 3rd vertex is "sliding" (used for diffraction)
bool use3rd; // indicates if the third vertex is present (it marks a (potential) sliding point)
// wave function related
float phase; // phase of the representative wave inside the envelope, phase speed vs. group speed
float phOld; // old phase
float E; // wave energy flux for this packet (determines amplitude)
float envelope; // envelope size for this packet
float k,w0; // w0 = angular frequency, k = current wavenumber
float k_L,w0_L,k_H,w0_H; // w0 = angular frequency, k = current wavenumber, L/H are for lower/upper boundary
float d_L,d_H; // d = travel distance to reference wave (gets accumulated over time), L/H are for lower/upper boundary
float ampOld; // amplitude from last timestep, will be smoothly adjusted in each timestep to meet current desired amplitude
float dAmp; // amplitude change in each timestep (depends on desired waveheight so all waves (dis)appear with same speed)
// serial deletion step variable
bool toDelete; // used internally for parallel deletion criterion computation
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
struct GHOST_PACKET
{
Vector2f pos; // 2D position
Vector2f dir; // current movement direction
float speed; // speed of the packet
float envelope; // envelope size for this packet
float bending; // point used for circular arc bending of the wave function inside envelope
float k; // k = current (representative) wavenumber(s)
float phase; // phase of the representative wave inside the envelope
float dPhase; // phase speed relative to group speed inside the envelope
float ampOld; // amplitude from last timestep, will be smoothly adjusted in each timestep to meet current desired amplitude
float dAmp; // change in amplitude in each timestep (waves travel PACKET_BLEND_TRAVEL_FACTOR*envelopesize in space until they disappear)
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
class Packets
{
public:
// scene
int m_groundSizeX, m_groundSizeY; // pixel size of the ground texture
float *m_ground; // texture containing the water depth and land (0.95)
float *m_distMap; // distance map of the boundary map
Vector2f *m_gndDeriv;
Vector2f *m_bndDeriv;
// packet managing
WAVE_PACKET *m_packet; // wave packet data
GHOST_PACKET*m_ghostPacket; // ghost packet data
int m_packetBudget; // this can be changed any time (soft budget)
int m_packetNum; // current size of the buffer used for packets / ghosts
float m_softDampFactor;
int *m_usedPacket;
int m_usedPackets;
int *m_freePacket;
int m_freePackets;
int *m_usedGhost;
int m_usedGhosts;
int *m_freeGhost;
int m_freeGhosts;
// simulation
float m_time;
float m_oldTime;
float m_elapsedTime;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Packets(int packetBudget);
~Packets(void);
void Reset();
float GetBoundaryDist(Vector2f &p);
Vector2f GetBoundaryNormal(Vector2f &p);
float GetGroundVal(Vector2f &p);
Vector2f GetGroundNormal(Vector2f &p);
float GetWaterDepth(Vector2f &p);
void UpdateTime(float dTime);
void ExpandWavePacketMemory(int targetNum);
int GetFreePackedID();
void DeletePacket(int id);
int GetFreeGhostID();
void DeleteGhost(int id);
void CreatePacket(float pos1x, float pos1y, float pos2x, float pos2y, float dir1x, float dir1y, float dir2x, float dir2y, float k_L, float k_H, float E);
void CreateLinearWavefront(float xPos, float yPos, float dirx, float diry, float crestlength, float lambda_L, float lambda_H, float E);
void CreateSpreadingPacket(float xPos, float yPos, float dirx, float diry, float spreadFactor, float crestlength, float lambda_L, float lambda_H, float E);
void CreateCircularWavefront(float xPos, float yPos, float radius, float lambda_L, float lambda_H, float E);
void GetWaveParameters(float waterDepth, float w0, float kIn, float &k_out, float &speed_out);
float GetPhaseSpeed(float w_0, float kIn);
float GetWaveAmplitude(float area, float E, float k);
float GetIntersectionDistance(Vector2f pos1, Vector2f dir1, Vector2f pos2, Vector2f dir2);
bool AdvectPacketVertex(float elapsedTime, Vector2f &posIn, Vector2f &dirIn, float w0, float &kIn, float &speedIn, Vector2f &posOut, Vector2f &dirOut, float &speedOut);
void AdvectWavePackets(float dTime);
};

44
constants.h

@ -0,0 +1,44 @@
// Taken from https://github.com/jeschke/water-wave-packets
// Originally GlobalDefs.h
// Global definitions needed for packet simulation and rendering
// scene parameters
#define SCENE_EXTENT 100.0f // extent of the entire scene (packets traveling outside are removed)
#define MIN_WATER_DEPTH 0.1f // minimum water depth (meters)
#define MAX_WATER_DEPTH 5.0f // maximum water depth (meters)
#define WATER_TERRAIN_FILE "TestIsland.bmp"// Contains water depth and land height in different channels
// rendering parameters
#define PACKET_GPU_BUFFER_SIZE 1000000 // maximum number of wave packets to be displayed in one draw call
/*
// Fast rendering setup
#define WAVETEX_WIDTH_FACTOR 0.5 // the wavemesh texture compared to screen resolution
#define WAVETEX_HEIGHT_FACTOR 1 // the wavemesh texture compared to screen resolution
#define WAVEMESH_WIDTH_FACTOR 0.1 // the fine wave mesh compared to screen resolution
#define WAVEMESH_HEIGHT_FACTOR 0.25 // the fine wave mesh compared to screen resolution
#define AA_OVERSAMPLE_FACTOR 2 // anti aliasing applied in BOTH X and Y directions {1,2,4,8}
*/
/*
// Balanced rendering setup
#define WAVETEX_WIDTH_FACTOR 1 // the wavemesh texture compared to screen resolution
#define WAVETEX_HEIGHT_FACTOR 2 // the wavemesh texture compared to screen resolution
#define WAVEMESH_WIDTH_FACTOR 1 // the fine wave mesh compared to screen resolution
#define WAVEMESH_HEIGHT_FACTOR 2 // the fine wave mesh compared to screen resolution
#define AA_OVERSAMPLE_FACTOR 2 // anti aliasing applied in BOTH X and Y directions {1,2,4,8}
*/
// High quality rendering setup
#define WAVETEX_WIDTH_FACTOR 2 // the wavemesh texture compared to screen resolution
#define WAVETEX_HEIGHT_FACTOR 4 // the wavemesh texture compared to screen resolution
#define WAVEMESH_WIDTH_FACTOR 2 // the fine wave mesh compared to screen resolution
#define WAVEMESH_HEIGHT_FACTOR 4 // the fine wave mesh compared to screen resolution
#define AA_OVERSAMPLE_FACTOR 4 // anti aliasing applied in BOTH X and Y directions {1,2,4,8}

3070
inf2705.h

File diff suppressed because it is too large

33
makefile

@ -0,0 +1,33 @@
CONTEXT=sdl2
ifeq "$(shell uname)" "Darwin"
CONTEXT=glfw3
LDFLAGS += -lobjc -framework Foundation -framework OpenGL -framework Cocoa
endif
CXXFLAGS += -g -W -Wall -Wno-unused-parameter -Wno-deprecated-declarations
CXXFLAGS += $(shell pkg-config --cflags glew)
CXXFLAGS += $(shell pkg-config --cflags $(CONTEXT))
LDFLAGS += -g
LDFLAGS += $(shell pkg-config --libs glew)
LDFLAGS += $(shell pkg-config --libs $(CONTEXT))
TP="tp3"
SRC=ripple
exe : $(SRC).exe
run : exe
optirun ./$(SRC).exe
$(SRC).exe : $(SRC).cpp *.h
$(CXX) $(CXXFLAGS) -o$@ $(SRC).cpp $(LDFLAGS)
sol : ; make SRC=$(SRC)Solution exe
runs : ; make SRC=$(SRC)Solution run
clean :
rm -rf *.o *.exe *.exe.dSYM
remise zip :
make clean
rm -f remise_$(TP).zip
zip -r remise_$(TP).zip *.cpp *.h *.glsl makefile *.txt textures

141
nuanceurFragmentsSolution.glsl

@ -0,0 +1,141 @@
#version 410
// Définition des paramètres des sources de lumière
layout (std140) uniform LightSourceParameters
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
vec3 spotDirection;
float spotExponent;
float spotCutoff; // ([0.0,90.0] ou 180.0)
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
} LightSource[1];
// Définition des paramètres des matériaux
layout (std140) uniform MaterialParameters
{
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
} FrontMaterial;
// Définition des paramètres globaux du modèle de lumière
layout (std140) uniform LightModelParameters
{
vec4 ambient; // couleur ambiante
bool localViewer; // observateur local ou à l'infini?
bool twoSide; // éclairage sur les deux côtés ou un seul?
} LightModel;
layout (std140) uniform varsUnif
{
// partie 1: illumination
int typeIllumination; // 0:Lambert, 1:Gouraud, 2:Phong
bool utiliseBlinn; // indique si on veut utiliser modèle spéculaire de Blinn ou Phong
bool utiliseDirect; // indique si on utilise un spot style Direct3D ou OpenGL
bool afficheNormales; // indique si on utilise les normales comme couleurs (utile pour le débogage)
// partie 3: texture
int texnumero; // numéro de la texture appliquée
bool utiliseCouleur; // doit-on utiliser la couleur de base de l'objet en plus de celle de la texture?
int afficheTexelNoir; // un texel noir doit-il être affiché 0:noir, 1:mi-coloré, 2:transparent?
};
uniform sampler2D laTexture;
/////////////////////////////////////////////////////////////////
in Attribs {
vec3 lumiDir, spotDir;
vec3 normale, obsVec;
vec2 texCoord;
vec4 couleur;
} AttribsIn;
out vec4 FragColor;
float calculerSpot( in vec3 spotDir, in vec3 L )
{
float spotFacteur;
float spotDot = dot( L, normalize( spotDir ) );
if ( utiliseDirect ) // modèle Direct3D
{
float cosAngleInterne = cos(radians(LightSource[0].spotCutoff));
float exposant = 1.01 + LightSource[0].spotExponent / 2.0;
float cosAngleExterne = pow( cos(radians(LightSource[0].spotCutoff)), exposant );
// calculer le facteur spot avec la fonction smoothstep()
spotFacteur = smoothstep( cosAngleExterne, cosAngleInterne, spotDot );
}
else // modèle OpenGL
{
spotFacteur = ( spotDot > cos(radians(LightSource[0].spotCutoff)) ) ? pow( spotDot, LightSource[0].spotExponent ) : 0.0;
}
return( spotFacteur );
}
vec4 calculerReflexion( in vec3 L, in vec3 N, in vec3 O )
{
vec4 coul = FrontMaterial.emission + FrontMaterial.ambient * LightModel.ambient;
// calcul de la composante ambiante
coul += FrontMaterial.ambient * LightSource[0].ambient;
// calcul de l'éclairage seulement si le produit scalaire est positif
float NdotL = max( 0.0, dot( N, L ) );
if ( NdotL > 0.0 )
{
// calcul de la composante diffuse
//coul += ( utiliseCouleur ? FrontMaterial.diffuse : vec4(1.0) ) * LightSource[0].diffuse * NdotL;
coul += FrontMaterial.diffuse * LightSource[0].diffuse * NdotL;
// calcul de la composante spéculaire (Blinn ou Phong)
float NdotHV = max( 0.0, ( utiliseBlinn ) ? dot( normalize( L + O ), N ) : dot( reflect( -L, N ), O ) );
coul += FrontMaterial.specular * LightSource[0].specular * ( ( NdotHV == 0.0 ) ? 0.0 : pow( NdotHV, FrontMaterial.shininess ) );
}
return( coul );
}
void main( void )
{
vec3 L = normalize( AttribsIn.lumiDir ); // vecteur vers la source lumineuse
vec3 N = normalize( AttribsIn.normale ); // vecteur normal
//vec3 N = normalize( gl_FrontFacing ? AttribsIn.normale : -AttribsIn.normale );
vec3 O = normalize( AttribsIn.obsVec ); // position de l'observateur
// calculer la réflexion:
// si illumination de 1:Gouraud, prendre la couleur interpolée qui a été reçue
// si illumination de 2:Phong, le faire!
// si illumination de 0:Lambert, faire comme Phong, même si les normales sont les mêmes pour tous les fragments
vec4 coul = ( typeIllumination == 1 ) ? AttribsIn.couleur : calculerReflexion( L, N, O );
// calculer l'influence du spot
float spotFacteur = calculerSpot( AttribsIn.spotDir, L );
coul *= spotFacteur;
//if ( spotFacteur <= 0.0 ) discard; // pour éliminer tout ce qui n'est pas dans le cône
// calcul de la composante ambiante
//coul += FrontMaterial.ambient * LightSource[0].ambient;
// appliquer la texture s'il y a lieu
if ( texnumero != 0 )
{
vec4 couleurTexture = texture( laTexture, AttribsIn.texCoord );
// comment afficher un texel noir?
if ( couleurTexture.r < 0.1 && couleurTexture.g < 0.1 && couleurTexture.b < 0.1 &&
spotFacteur > 0.0 )
if ( afficheTexelNoir == 1 )
couleurTexture = coul / 2.0;
else if ( afficheTexelNoir == 2 )
discard;
coul *= couleurTexture;
}
// assigner la couleur finale
FragColor = clamp( coul, 0.0, 1.0 );
if ( afficheNormales ) FragColor = vec4(N,1.0);
}

73
nuanceurGeometrieSolution.glsl

@ -0,0 +1,73 @@
#version 410
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
uniform mat4 matrModel;
uniform mat4 matrVisu;
uniform mat4 matrProj;
uniform mat3 matrNormale;
layout (std140) uniform varsUnif
{
// partie 1: illumination
int typeIllumination; // 0:Lambert, 1:Gouraud, 2:Phong
bool utiliseBlinn; // indique si on veut utiliser modèle spéculaire de Blinn ou Phong
bool utiliseDirect; // indique si on utilise un spot style Direct3D ou OpenGL
bool afficheNormales; // indique si on utilise les normales comme couleurs (utile pour le débogage)
// partie 3: texture
int texnumero; // numéro de la texture appliquée
bool utiliseCouleur; // doit-on utiliser la couleur de base de l'objet en plus de celle de la texture?
int afficheTexelNoir; // un texel noir doit-il être affiché 0:noir, 1:mi-coloré, 2:transparent?
};
in Attribs {
vec3 lumiDir, spotDir;
vec3 normale, obsVec;
vec2 texCoord;
vec4 couleur;
} AttribsIn[];
out Attribs {
vec3 lumiDir, spotDir;
vec3 normale, obsVec;
vec2 texCoord;
vec4 couleur;
} AttribsOut;
void main()
{
// si illumination est Lambert, calculer une nouvelle normale
vec3 n = vec3(0.0);
if ( typeIllumination == 0 )
{
vec3 p0 = gl_in[0].gl_Position.xyz;
vec3 p1 = gl_in[1].gl_Position.xyz;
vec3 p2 = gl_in[2].gl_Position.xyz;
n = cross( p1-p0, p2-p0 ); // cette nouvelle normale est déjà dans le repère de la caméra
// il n'est pas nécessaire de la multiplier par matrNormale
}
// ou faire une moyenne, MAIS CE N'EST PAS CE QU'ON VEUT!
// if ( typeIllumination == 0 )
// {
// // calculer le centre
// for ( int i = 0 ; i < gl_in.length() ; ++i )
// {
// n += AttribsIn[i].normale;
// }
// n /= gl_in.length();
// }
// émettre les sommets
for ( int i = 0 ; i < gl_in.length() ; ++i )
{
gl_Position = matrProj * gl_in[i].gl_Position; // on termine la transformation débutée dans le nuanceur de sommets
AttribsOut.lumiDir = AttribsIn[i].lumiDir;
AttribsOut.spotDir = AttribsIn[i].spotDir;
AttribsOut.normale = ( typeIllumination == 0 ) ? n : AttribsIn[i].normale;
AttribsOut.obsVec = AttribsIn[i].obsVec;
AttribsOut.texCoord = AttribsIn[i].texCoord;
AttribsOut.couleur = AttribsIn[i].couleur;
EmitVertex();
}
}

130
nuanceurSommetsSolution.glsl

@ -0,0 +1,130 @@
#version 410
// Définition des paramètres des sources de lumière
layout (std140) uniform LightSourceParameters
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
vec3 spotDirection;
float spotExponent;
float spotCutoff; // ([0.0,90.0] ou 180.0)
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
} LightSource[1];
// Définition des paramètres des matériaux
layout (std140) uniform MaterialParameters
{
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
} FrontMaterial;
// Définition des paramètres globaux du modèle de lumière
layout (std140) uniform LightModelParameters
{
vec4 ambient; // couleur ambiante
bool localViewer; // observateur local ou à l'infini?
bool twoSide; // éclairage sur les deux côtés ou un seul?
} LightModel;
layout (std140) uniform varsUnif
{
// partie 1: illumination
int typeIllumination; // 0:Lambert, 1:Gouraud, 2:Phong
bool utiliseBlinn; // indique si on veut utiliser modèle spéculaire de Blinn ou Phong
bool utiliseDirect; // indique si on utilise un spot style Direct3D ou OpenGL
bool afficheNormales; // indique si on utilise les normales comme couleurs (utile pour le débogage)
// partie 3: texture
int texnumero; // numéro de la texture appliquée
bool utiliseCouleur; // doit-on utiliser la couleur de base de l'objet en plus de celle de la texture?
int afficheTexelNoir; // un texel noir doit-il être affiché 0:noir, 1:mi-coloré, 2:transparent?
};
uniform mat4 matrModel;
uniform mat4 matrVisu;
uniform mat4 matrProj;
uniform mat3 matrNormale;
/////////////////////////////////////////////////////////////////
layout(location=0) in vec4 Vertex;
layout(location=2) in vec3 Normal;
layout(location=3) in vec4 Color;
layout(location=8) in vec4 TexCoord;
out Attribs {
vec3 lumiDir, spotDir;
vec3 normale, obsVec;
vec2 texCoord;
vec4 couleur;
} AttribsOut;
vec4 calculerReflexion( in vec3 L, in vec3 N, in vec3 O )
{
vec4 coul = FrontMaterial.emission + FrontMaterial.ambient * LightModel.ambient;
// calcul de la composante ambiante
coul += FrontMaterial.ambient * LightSource[0].ambient;
// calcul de l'éclairage seulement si le produit scalaire est positif
float NdotL = max( 0.0, dot( N, L ) );
if ( NdotL > 0.0 )
{
// calcul de la composante diffuse
//coul += ( utiliseCouleur ? FrontMaterial.diffuse : vec4(1.0) ) * LightSource[0].diffuse * NdotL;
coul += FrontMaterial.diffuse * LightSource[0].diffuse * NdotL;
// calcul de la composante spéculaire (Blinn ou Phong)
float NdotHV = max( 0.0, ( utiliseBlinn ) ? dot( normalize( L + O ), N ) : dot( reflect( -L, N ), O ) );
coul += FrontMaterial.specular * LightSource[0].specular * ( ( NdotHV == 0.0 ) ? 0.0 : pow( NdotHV, FrontMaterial.shininess ) );
}
return( coul );
}
void main( void )
{
// transformation standard du sommet, ** sans la projection **
gl_Position = matrVisu * matrModel * Vertex;
// calculer la normale qui sera interpolée pour le nuanceur de fragment
AttribsOut.normale = matrNormale * Normal;
// calculer la position du sommet (dans le repère de la caméra)
vec3 pos = vec3( matrVisu * matrModel * Vertex );
// vecteur de la direction de la lumière (dans le repère de la caméra)
AttribsOut.lumiDir = vec3( ( matrVisu * LightSource[0].position ).xyz - pos );
// vecteur de la direction vers l'observateur (dans le repère de la caméra)
AttribsOut.obsVec = ( LightModel.localViewer ?
normalize(-pos) : // =(0-pos) un vecteur qui pointe vers le (0,0,0), c'est-à-dire vers la caméra
vec3( 0.0, 0.0, 1.0 ) ); // on considère que l'observateur (la caméra) est à l'infini dans la direction (0,0,1)
// vecteur de la direction du spot (en tenant compte seulement des rotations de la caméra)
AttribsOut.spotDir = inverse(mat3(matrVisu)) * -LightSource[0].spotDirection;
// On accepte aussi: (si on suppose que .spotDirection est déjà dans le repère de la caméra)
//AttribsOut.spotDir = -LightSource[0].spotDirection;
// On accepte aussi: (car matrVisu a seulement une translation et pas de rotation => "mat3(matrVisu) == I" )
//AttribsOut.spotDir = -LightSource[0].spotDirection;
// On accepte aussi: (car c'était le calcul qui était dans la solution précédente présentée dans le lab!)
//AttribsOut.spotDir = -( matrVisu * vec4(LightSource[0].spotDirection,1.0) ).xyz;
// si illumination est 1:Gouraud, calculer la réflexion ici, sinon ne rien faire de plus
if ( typeIllumination == 1 )
{
vec3 L = normalize( AttribsOut.lumiDir ); // calcul du vecteur de la surface vers la source lumineuse
vec3 N = normalize( AttribsOut.normale ); // vecteur normal
vec3 O = normalize( AttribsOut.obsVec ); // position de l'observateur
AttribsOut.couleur = calculerReflexion( L, N, O );
}
//else
// couleur = vec4(0.0); // inutile
// assigner les coordonnées de texture
AttribsOut.texCoord = TexCoord.st;
}

954
ripple.cpp

@ -0,0 +1,954 @@
// Prénoms, noms et matricule des membres de l'équipe:
// - Prénom1 NOM1 (matricule1)
// - Prénom2 NOM2 (matricule2)
#include <stdlib.h>
#include <iostream>
#include "inf2705.h"
#define SOL 1
// variables pour l'utilisation des nuanceurs
GLuint prog; // votre programme de nuanceurs
GLint locVertex = -1;
GLint locNormal = -1;
GLint locTexCoord = -1;
GLint locmatrModel = -1;
GLint locmatrVisu = -1;
GLint locmatrProj = -1;
GLint locmatrNormale = -1;
GLint loclaTexture = -1;
GLuint indLightSource;
GLuint indFrontMaterial;
GLuint indLightModel;
GLuint indvarsUnif;
GLuint progBase; // le programme de nuanceurs de base
GLint locVertexBase = -1;
GLint locColorBase = -1;
GLint locmatrModelBase = -1;
GLint locmatrVisuBase = -1;
GLint locmatrProjBase = -1;
GLuint vao[2];
GLuint vbo[5];
GLuint ubo[4];
// matrices de du pipeline graphique
MatricePipeline matrModel;
MatricePipeline matrVisu;
MatricePipeline matrProj;
// les formes
FormeSphere *sphere = NULL, *sphereLumi = NULL;
FormeTheiere *theiere = NULL;
FormeTore *tore = NULL;
FormeCylindre *cylindre = NULL;
FormeCylindre *cone = NULL;
// variables pour définir le point de vue
double thetaCam = 0.0; // angle de rotation de la caméra (coord. sphériques)
double phiCam = 0.0; // angle de rotation de la caméra (coord. sphériques)
double distCam = 0.0; // distance (coord. sphériques)
// variables d'état
bool enPerspective = false; // indique si on est en mode Perspective (true) ou Ortho (false)
bool enmouvement = false; // le modèle est en mouvement/rotation automatique ou non
bool afficheAxes = true; // indique si on affiche les axes
GLenum modePolygone = GL_FILL; // comment afficher les polygones
////////////////////////////////////////
// déclaration des variables globales //
////////////////////////////////////////
// partie 1: illumination
int modele = 1; // le modèle à afficher
// partie 3: texture
GLuint textureDE = 0;
GLuint textureECHIQUIER = 0;
// définition des lumières
struct LightSourceParameters
{
glm::vec4 ambient;
glm::vec4 diffuse;
glm::vec4 specular;
glm::vec4 position;
glm::vec3 spotDirection;
float spotExposant;
float spotAngle; // ([0.0,90.0] ou 180.0)
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
} LightSource[1] = { { glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 4, 1, 15, 1.0 ),
glm::vec3( -5.0, -2.0, -10.0 ),
1.0, // l'exposant du cône
15.0, // l'angle du cône du spot
1., 0., 0. } };
// définition du matériau
struct MaterialParameters
{
glm::vec4 emission;
glm::vec4 ambient;
glm::vec4 diffuse;
glm::vec4 specular;
float shininess;
} FrontMaterial = { glm::vec4( 0.0, 0.0, 0.0, 1.0 ),
glm::vec4( 0.1, 0.1, 0.1, 1.0 ),
glm::vec4( 1.0, 0.1, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
100.0 };
struct LightModelParameters
{
glm::vec4 ambient; // couleur ambiante
int localViewer; // doit-on prendre en compte la position de l'observateur? (local ou à l'infini)
int twoSide; // éclairage sur les deux côtés ou un seul?
} LightModel = { glm::vec4(0,0,0,1), false, false };
struct
{
// partie 1: illumination
int typeIllumination; // 0:Lambert, 1:Gouraud, 2:Phong
int utiliseBlinn; // indique si on veut utiliser modèle spéculaire de Blinn ou Phong
int utiliseDirect; // indique si on utilise un spot style Direct3D ou OpenGL
int afficheNormales; // indique si on utilise les normales comme couleurs (utile pour le débogage)
// partie 3: texture
int texnumero; // numéro de la texture appliquée
int utiliseCouleur; // doit-on utiliser la couleur de base de l'objet en plus de celle de la texture?
int afficheTexelNoir; // un texel noir doit-il être affiché 0:noir, 1:mi-coloré, 2:transparent?
} varsUnif = { 2, false, false, false,
0, true, 0 };
// ( En glsl, les types 'bool' et 'int' sont de la même taille, ce qui n'est pas le cas en C++.
// Ci-dessus, on triche donc un peu en déclarant les 'bool' comme des 'int', mais ça facilite la
// copie directe vers le nuanceur où les variables seront bien de type 'bool'. )
void verifierAngles()
{
if ( thetaCam > 360.0 )
thetaCam -= 360.0;
else if ( thetaCam < 0.0 )
thetaCam += 360.0;
const GLdouble MINPHI = -90.0, MAXPHI = 90.0;
if ( phiCam > MAXPHI )
phiCam = MAXPHI;
else if ( phiCam < MINPHI )
phiCam = MINPHI;
}
void calculerPhysique( )
{
if ( enmouvement )
{
static int sensTheta = 1;
static int sensPhi = 1;
thetaCam += 0.3 * sensTheta;
phiCam += 0.5 * sensPhi;
//if ( thetaCam <= 0. || thetaCam >= 360.0 ) sensTheta = -sensTheta;
if ( phiCam < -90.0 || phiCam > 90.0 ) sensPhi = -sensPhi;
static int sensAngle = 1;
LightSource[0].spotAngle += sensAngle * 0.3;
if ( LightSource[0].spotAngle < 5.0 ) sensAngle = -sensAngle;
if ( LightSource[0].spotAngle > 60.0 ) sensAngle = -sensAngle;
#if 0
static int sensExposant = 1;
LightSource[0].spotExposant += sensExposant * 0.3;
if ( LightSource[0].spotExposant < 1.0 ) sensExposant = -sensExposant;
if ( LightSource[0].spotExposant > 10.0 ) sensExposant = -sensExposant;
#endif
// De temps à autre, alterner entre le modèle d'illumination: Lambert, Gouraud, Phong
static float type = 0;
type += 0.005;
varsUnif.typeIllumination = fmod(type,3);
}
verifierAngles();
}
void chargerTextures()
{
unsigned char *pixels;
GLsizei largeur, hauteur;
if ( ( pixels = ChargerImage( "textures/de.bmp", largeur, hauteur ) ) != NULL )
{
glGenTextures( 1, &textureDE );
glBindTexture( GL_TEXTURE_2D, textureDE );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, largeur, hauteur, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, 0 );
delete[] pixels;
}
if ( ( pixels = ChargerImage( "textures/echiquier.bmp", largeur, hauteur ) ) != NULL )
{
glGenTextures( 1, &textureECHIQUIER );
glBindTexture( GL_TEXTURE_2D, textureECHIQUIER );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, largeur, hauteur, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, 0 );
delete[] pixels;
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
}
void chargerNuanceurs()
{
// charger le nuanceur de base
{
// créer le programme
progBase = glCreateProgram();
// attacher le nuanceur de sommets
{
GLuint nuanceurObj = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( nuanceurObj, 1, &ProgNuanceur::chainesSommetsMinimal, NULL );
glCompileShader( nuanceurObj );
glAttachShader( progBase, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
}
// attacher le nuanceur de fragments
{
GLuint nuanceurObj = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( nuanceurObj, 1, &ProgNuanceur::chainesFragmentsMinimal, NULL );
glCompileShader( nuanceurObj );
glAttachShader( progBase, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
}
// faire l'édition des liens du programme
glLinkProgram( progBase );
ProgNuanceur::afficherLogLink( progBase );
// demander la "Location" des variables
if ( ( locVertexBase = glGetAttribLocation( progBase, "Vertex" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Vertex" << std::endl;
if ( ( locColorBase = glGetAttribLocation( progBase, "Color" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Color" << std::endl;
if ( ( locmatrModelBase = glGetUniformLocation( progBase, "matrModel" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrModel" << std::endl;
if ( ( locmatrVisuBase = glGetUniformLocation( progBase, "matrVisu" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrVisu" << std::endl;
if ( ( locmatrProjBase = glGetUniformLocation( progBase, "matrProj" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrProj" << std::endl;
}
// charger le nuanceur de ce TP
{
// créer le programme
prog = glCreateProgram();
// attacher le nuanceur de sommets
#if !defined(SOL)
const GLchar *chainesSommets = ProgNuanceur::lireNuanceur( "nuanceurSommets.glsl" );
#else
const GLchar *chainesSommets = ProgNuanceur::lireNuanceur( "nuanceurSommetsSolution.glsl" );
#endif
if ( chainesSommets != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( nuanceurObj, 1, &chainesSommets, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesSommets;
}
#if !defined(SOL)
const GLchar *chainesGeometrie = ProgNuanceur::lireNuanceur( "nuanceurGeometrie.glsl" );
#else
const GLchar *chainesGeometrie = ProgNuanceur::lireNuanceur( "nuanceurGeometrieSolution.glsl" );
#endif
if ( chainesGeometrie != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_GEOMETRY_SHADER );
glShaderSource( nuanceurObj, 1, &chainesGeometrie, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesGeometrie;
}
// attacher le nuanceur de fragments
#if !defined(SOL)
const GLchar *chainesFragments = ProgNuanceur::lireNuanceur( "nuanceurFragments.glsl" );
#else
const GLchar *chainesFragments = ProgNuanceur::lireNuanceur( "nuanceurFragmentsSolution.glsl" );
#endif
if ( chainesFragments != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( nuanceurObj, 1, &chainesFragments, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesFragments;
}
// faire l'édition des liens du programme
glLinkProgram( prog );
ProgNuanceur::afficherLogLink( prog );
// demander la "Location" des variables
if ( ( locVertex = glGetAttribLocation( prog, "Vertex" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Vertex" << std::endl;
if ( ( locNormal = glGetAttribLocation( prog, "Normal" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Normal (partie 1)" << std::endl;
if ( ( locTexCoord = glGetAttribLocation( prog, "TexCoord" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de TexCoord (partie 3)" << std::endl;
if ( ( locmatrModel = glGetUniformLocation( prog, "matrModel" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrModel" << std::endl;
if ( ( locmatrVisu = glGetUniformLocation( prog, "matrVisu" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrVisu" << std::endl;
if ( ( locmatrProj = glGetUniformLocation( prog, "matrProj" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrProj" << std::endl;
if ( ( locmatrNormale = glGetUniformLocation( prog, "matrNormale" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrNormale (partie 1)" << std::endl;
if ( ( loclaTexture = glGetUniformLocation( prog, "laTexture" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de laTexture (partie 3)" << std::endl;
if ( ( indLightSource = glGetUniformBlockIndex( prog, "LightSourceParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de LightSource" << std::endl;
if ( ( indFrontMaterial = glGetUniformBlockIndex( prog, "MaterialParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de FrontMaterial" << std::endl;
if ( ( indLightModel = glGetUniformBlockIndex( prog, "LightModelParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de LightModel" << std::endl;
if ( ( indvarsUnif = glGetUniformBlockIndex( prog, "varsUnif" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de varsUnif" << std::endl;
// charger les ubo
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[0] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(LightSource), &LightSource, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 0;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[0] );
glUniformBlockBinding( prog, indLightSource, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[1] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(FrontMaterial), &FrontMaterial, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 1;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[1] );
glUniformBlockBinding( prog, indFrontMaterial, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[2] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(LightModel), &LightModel, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 2;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[2] );
glUniformBlockBinding( prog, indLightModel, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[3] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(varsUnif), &varsUnif, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 3;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[3] );
glUniformBlockBinding( prog, indvarsUnif, bindingIndex );
}
}
}
// initialisation d'openGL
void initialiser()
{
// donner l'orientation du modèle
thetaCam = 0.0;
phiCam = 0.0;
distCam = 30.0;
// couleur de l'arrière-plan
glClearColor( 0.4, 0.2, 0.0, 1.0 );
// activer les etats openGL
glEnable( GL_DEPTH_TEST );
// charger les textures
chargerTextures();
// allouer les UBO pour les variables uniformes
glGenBuffers( 4, ubo );
// charger les nuanceurs
chargerNuanceurs();
glUseProgram( prog );
// (partie 1) créer le cube
/* +Y */
/* 3+-----------+2 */
/* |\ |\ */
/* | \ | \ */
/* | \ | \ */
/* | 7+-----------+6 */
/* | | | | */
/* | | | | */
/* 0+---|-------+1 | */
/* \ | \ | +X */
/* \ | \ | */
/* \| \| */
/* 4+-----------+5 */
/* +Z */
GLfloat sommets[3*4*6] =
{
-1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, // P3,P2,P0,P1
1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // P5,P4,P1,P0
1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // P6,P5,P2,P1
-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, // P7,P6,P3,P2
-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, // P4,P7,P0,P3
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0 // P4,P5,P7,P6
};
GLfloat normales[3*4*6] =
{
0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0,
0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
};
GLfloat texcoordsDe[2*4*6] =
{
1.000000,0.000000, 0.666666,0.000000, 1.000000,0.333333, 0.666666,0.333333,
0.000000,0.666666, 0.333333,0.666666, 0.000000,0.333333, 0.333333,0.333333,
0.666666,1.000000, 0.666666,0.666666, 0.333333,1.000000, 0.333333,0.666666,
1.000000,0.333333, 0.666666,0.333333, 1.000000,0.666666, 0.666666,0.666666,
0.333333,0.000000, 0.333333,0.333333, 0.666666,0.000000, 0.666666,0.333333,
0.666666,0.333333, 0.333333,0.333333, 0.666666,0.666666, 0.333333,0.666666
};
GLfloat texcoordsEchiquier[2*4*6] =
{
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0,
2.0, -1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0,
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0,
-1.0, 2.0, 2.0, 2.0, -1.0, -1.0, 2.0, -1.0,
2.0, 2.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0,
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0
};
// allouer les objets OpenGL
glGenVertexArrays( 2, vao );
glGenBuffers( 5, vbo );
// initialiser le VAO
glBindVertexArray( vao[0] );
// charger le VBO pour les sommets
glBindBuffer( GL_ARRAY_BUFFER, vbo[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof(sommets), sommets, GL_STATIC_DRAW );
glVertexAttribPointer( locVertex, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locVertex);
// (partie 1) charger le VBO pour les normales
glBindBuffer( GL_ARRAY_BUFFER, vbo[1] );
glBufferData( GL_ARRAY_BUFFER, sizeof(normales), normales, GL_STATIC_DRAW );
glVertexAttribPointer( locNormal, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locNormal);
// (partie 3) charger le VBO pour les coordonnées de texture du dé
glBindBuffer( GL_ARRAY_BUFFER, vbo[2] );
glBufferData( GL_ARRAY_BUFFER, sizeof(texcoordsDe), texcoordsDe, GL_STATIC_DRAW );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locTexCoord);
// (partie 3) charger le VBO pour les coordonnées de texture de l'échiquier
glBindBuffer( GL_ARRAY_BUFFER, vbo[3] );
glBufferData( GL_ARRAY_BUFFER, sizeof(texcoordsEchiquier), texcoordsEchiquier, GL_STATIC_DRAW );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locTexCoord);
glBindVertexArray(0);
// initialiser le VAO pour une ligne (montrant la direction du spot)
glBindVertexArray( vao[1] );
GLfloat coords[] = { 0., 0., 0., 0., 0., 1. };
glBindBuffer( GL_ARRAY_BUFFER, vbo[4] );
glBufferData( GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW );
glVertexAttribPointer( locVertexBase, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locVertexBase);
glBindVertexArray(0);
// créer quelques autres formes
sphere = new FormeSphere( 1.0, 32, 32 );
sphereLumi = new FormeSphere( 0.5, 10, 10 );
theiere = new FormeTheiere( );
tore = new FormeTore( 0.4, 0.8, 32, 32 );
cylindre = new FormeCylindre( 0.3, 0.3, 3.0, 32, 32 );
cone = new FormeCylindre( 0.0, 0.5, 3.0, 32, 32 );
}
void conclure()
{
glUseProgram( 0 );
glDeleteVertexArrays( 2, vao );
glDeleteBuffers( 4, vbo );
glDeleteBuffers( 4, ubo );
delete sphere;
delete sphereLumi;
delete theiere;
delete tore;
delete cylindre;
delete cone;
}
void afficherModele()
{
// partie 3: paramètres de texture
switch ( varsUnif.texnumero )
{
default:
//std::cout << "Sans texture" << std::endl;
glBindTexture( GL_TEXTURE_2D, 0 );
break;
case 1:
//std::cout << "Texture DE" << std::endl;
glBindTexture( GL_TEXTURE_2D, textureDE );
break;
case 2:
//std::cout << "Texture ECHIQUIER" << std::endl;
glBindTexture( GL_TEXTURE_2D, textureECHIQUIER );
break;
}
// Dessiner le modèle
matrModel.PushMatrix(); {
// appliquer les rotations
matrModel.Rotate( phiCam, -1.0, 0.0, 0.0 );
matrModel.Rotate( thetaCam, 0.0, -1.0, 0.0 );
// mise à l'échelle
matrModel.Scale( 5.0, 5.0, 5.0 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
// (partie 1: ne pas oublier de calculer et donner une matrice pour les transformations des normales)
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
switch ( modele )
{
default:
case 1:
// afficher le cube
glBindVertexArray( vao[0] );
glBindBuffer( GL_ARRAY_BUFFER, varsUnif.texnumero == 1 ? vbo[2] : vbo[3] );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 4, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 8, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 12, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 16, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 20, 4 );
glBindVertexArray( 0 );
break;
case 2:
tore->afficher();
break;
case 3:
sphere->afficher();
break;
case 4:
matrModel.Rotate( -90.0, 1.0, 0.0, 0.0 );
matrModel.Translate( 0.0, 0.0, -0.5 );
matrModel.Scale( 0.5, 0.5, 0.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
theiere->afficher( );
break;
case 5:
matrModel.PushMatrix(); {
matrModel.Translate( 0.0, 0.0, -1.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
cylindre->afficher();
} matrModel.PopMatrix();
break;
case 6:
matrModel.PushMatrix(); {
matrModel.Translate( 0.0, 0.0, -1.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
cone->afficher();
} matrModel.PopMatrix();
break;
}
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
}
void afficherLumiere()
{
// Dessiner la lumiere
// tracer une ligne vers la source lumineuse
const GLfloat fact = 5.;
GLfloat coords[] =
{
LightSource[0].position.x , LightSource[0].position.y , LightSource[0].position.z,
LightSource[0].position.x+LightSource[0].spotDirection.x/fact, LightSource[0].position.y+LightSource[0].spotDirection.y/fact, LightSource[0].position.z+LightSource[0].spotDirection.z/fact
};
glLineWidth( 3.0 );
glVertexAttrib3f( locColorBase, 1.0, 1.0, 0.5 ); // jaune
glBindVertexArray( vao[1] );
matrModel.PushMatrix(); {
glBindBuffer( GL_ARRAY_BUFFER, vbo[4] );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(coords), coords );
glDrawArrays( GL_LINES, 0, 2 );
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
glBindVertexArray( 0 );
glLineWidth( 1.0 );
// tracer la source lumineuse
matrModel.PushMatrix(); {
matrModel.Translate( LightSource[0].position.x, LightSource[0].position.y, LightSource[0].position.z );
glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
sphereLumi->afficher();
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
}
// fonction d'affichage
void FenetreTP::afficherScene()
{
// effacer l'ecran et le tampon de profondeur
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( progBase );
// définir le pipeline graphique
if ( enPerspective )
{
matrProj.Perspective( 35.0, (GLdouble)largeur_ / (GLdouble)hauteur_,
0.1, 60.0 );
}
else
{
const GLfloat d = 8.0;
if ( largeur_ <= hauteur_ )
{
matrProj.Ortho( -d, d,
-d*(GLdouble)hauteur_ / (GLdouble)largeur_,
d*(GLdouble)hauteur_ / (GLdouble)largeur_,
0.1, 60.0 );
}
else
{
matrProj.Ortho( -d*(GLdouble)largeur_ / (GLdouble)hauteur_,
d*(GLdouble)largeur_ / (GLdouble)hauteur_,
-d, d,
0.1, 60.0 );
}
}
glUniformMatrix4fv( locmatrProjBase, 1, GL_FALSE, matrProj );
matrVisu.LookAt( 0.0, 0.0, distCam, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
glUniformMatrix4fv( locmatrVisuBase, 1, GL_FALSE, matrVisu );
matrModel.LoadIdentity();
glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
// afficher les axes
if ( afficheAxes ) FenetreTP::afficherAxes( 8.0 );
// dessiner la scène
afficherLumiere();
glUseProgram( prog );
// mettre à jour les blocs de variables uniformes
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[0] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &LightSource, sizeof(LightSource) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[1] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &FrontMaterial, sizeof(FrontMaterial) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[2] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &LightModel, sizeof(LightModel) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[3] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &varsUnif, sizeof(varsUnif) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
// mettre à jour les matrices et autres uniformes
glUniformMatrix4fv( locmatrProj, 1, GL_FALSE, matrProj );
glUniformMatrix4fv( locmatrVisu, 1, GL_FALSE, matrVisu );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
//glActiveTexture( GL_TEXTURE0 ); // activer la texture '0' (valeur de défaut)
glUniform1i( loclaTexture, 0 ); // '0' => utilisation de GL_TEXTURE0
afficherModele();
}
// fonction de redimensionnement de la fenêtre graphique
void FenetreTP::redimensionner( GLsizei w, GLsizei h )
{
glViewport( 0, 0, w, h );
}
static void echoEtats( )
{
static std::string illuminationStr[] = { "0:Lambert", "1:Gouraud", "2:Phong" };
static std::string reflexionStr[] = { "0:Phong", "1:Blinn" };
static std::string spotStr[] = { "0:OpenGL", "1:Direct3D" };
std::cout << " modèle d'illumination= " << illuminationStr[varsUnif.typeIllumination]
<< ", refléxion spéculaire= " << reflexionStr[varsUnif.utiliseBlinn]
<< ", spot= " << spotStr[varsUnif.utiliseDirect]
<< std::endl;
}
// fonction de gestion du clavier
void FenetreTP::clavier( TP_touche touche )
{
// traitement des touches q et echap
switch ( touche )
{
case TP_ECHAP:
case TP_q: // Quitter l'application
quit();
break;
case TP_x: // Activer/désactiver l'affichage des axes
afficheAxes = !afficheAxes;
std::cout << "// Affichage des axes ? " << ( afficheAxes ? "OUI" : "NON" ) << std::endl;
break;
case TP_v: // Recharger les fichiers des nuanceurs et recréer le programme
chargerNuanceurs();
std::cout << "// Recharger nuanceurs" << std::endl;
break;
case TP_p: // Permuter la projection: perspective ou orthogonale
enPerspective = !enPerspective;
break;
case TP_i: // Alterner entre le modèle d'illumination: Lambert, Gouraud, Phong
if ( ++varsUnif.typeIllumination > 2 ) varsUnif.typeIllumination = 0;
echoEtats( );
break;
case TP_r: // Alterner entre le modèle de réflexion spéculaire: Phong, Blinn
varsUnif.utiliseBlinn = !varsUnif.utiliseBlinn;
echoEtats( );
break;
case TP_s: // Alterner entre le modèle de spot: OpenGL, Direct3D
varsUnif.utiliseDirect = !varsUnif.utiliseDirect;
echoEtats( );
break;
//case TP_l: // Alterner entre une caméra locale à la scène ou distante (localViewer)
// LightModel.localViewer = !LightModel.localViewer;
// std::cout << " localViewer=" << LightModel.localViewer << std::endl;
// break;
case TP_a: // Incrémenter l'angle du cône du spot
case TP_EGAL:
case TP_PLUS:
LightSource[0].spotAngle += 2.0;
if ( LightSource[0].spotAngle > 90.0 ) LightSource[0].spotAngle = 90.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
break;
case TP_z: // Décrémenter l'angle du cône du spot
case TP_MOINS:
case TP_SOULIGNE:
LightSource[0].spotAngle -= 2.0;
if ( LightSource[0].spotAngle < 0.0 ) LightSource[0].spotAngle = 0.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
break;
case TP_d: // Incrémenter l'exposant du spot
case TP_BARREOBLIQUE:
LightSource[0].spotExposant += 0.3;
if ( LightSource[0].spotExposant > 89.0 ) LightSource[0].spotExposant = 89.0;
std::cout << " spotExposant=" << LightSource[0].spotExposant << std::endl;
break;
case TP_e: // Décrémenter l'exposant du spot
case TP_POINT:
LightSource[0].spotExposant -= 0.3;
if ( LightSource[0].spotExposant < 0.0 ) LightSource[0].spotExposant = 0.0;
std::cout << " spotExposant=" << LightSource[0].spotExposant << std::endl;
break;
case TP_j: // Incrémenter le coefficient de brillance
case TP_CROCHETDROIT:
FrontMaterial.shininess *= 1.1;
std::cout << " FrontMaterial.shininess=" << FrontMaterial.shininess << std::endl;
break;
case TP_u: // Décrémenter le coefficient de brillance
case TP_CROCHETGAUCHE:
FrontMaterial.shininess /= 1.1; if ( FrontMaterial.shininess < 0.0 ) FrontMaterial.shininess = 0.0;
std::cout << " FrontMaterial.shininess=" << FrontMaterial.shininess << std::endl;
break;
case TP_DROITE:
LightSource[0].position.x += 0.3;
break;
case TP_GAUCHE:
LightSource[0].position.x -= 0.3;
break;
case TP_BAS:
LightSource[0].position.y += 0.3;
break;
case TP_HAUT:
LightSource[0].position.y -= 0.3;
break;
case TP_FIN:
LightSource[0].spotDirection.x += 0.6;
break;
case TP_DEBUT:
LightSource[0].spotDirection.x -= 0.6;
break;
case TP_PAGEPREC:
LightSource[0].spotDirection.y += 0.6;
break;
case TP_PAGESUIV:
LightSource[0].spotDirection.y -= 0.6;
break;
case TP_m: // Choisir le modèle affiché: cube, tore, sphère, théière, cylindre, cône
if ( ++modele > 6 ) modele = 1;
std::cout << " modele=" << modele << std::endl;
break;
case TP_0:
thetaCam = 0.0; phiCam = 0.0; distCam = 30.0; // placer les choses afin d'avoir une belle vue
break;
case TP_t: // Choisir la texture utilisée: aucune, dé, échiquier
varsUnif.texnumero++;
if ( varsUnif.texnumero > 2 ) varsUnif.texnumero = 0;
std::cout << " varsUnif.texnumero=" << varsUnif.texnumero << std::endl;
break;
// case TP_c: // Changer l'affichage de l'objet texturé avec couleurs ou sans couleur
// varsUnif.utiliseCouleur = !varsUnif.utiliseCouleur;
// std::cout << " utiliseCouleur=" << varsUnif.utiliseCouleur << std::endl;
// break;
case TP_o: // Changer l'affichage des texels noirs (noir, mi-coloré, transparent)
varsUnif.afficheTexelNoir++;
if ( varsUnif.afficheTexelNoir > 2 ) varsUnif.afficheTexelNoir = 0;
std::cout << " afficheTexelNoir=" << varsUnif.afficheTexelNoir << std::endl;
break;
case TP_g: // Permuter l'affichage en fil de fer ou plein
modePolygone = ( modePolygone == GL_FILL ) ? GL_LINE : GL_FILL;
glPolygonMode( GL_FRONT_AND_BACK, modePolygone );
break;
case TP_n: // Utiliser ou non les normales calculées comme couleur (pour le débogage)
varsUnif.afficheNormales = !varsUnif.afficheNormales;
break;
case TP_ESPACE: // Permuter la rotation automatique du modèle
enmouvement = !enmouvement;
break;
default:
std::cout << " touche inconnue : " << (char) touche << std::endl;
imprimerTouches();
break;
}
}
// fonction callback pour un clic de souris
int dernierX = 0; // la dernière valeur en X de position de la souris
int dernierY = 0; // la derniere valeur en Y de position de la souris
static enum { deplaceCam, deplaceSpotDirection, deplaceSpotPosition } deplace = deplaceCam;
static bool pressed = false;
void FenetreTP::sourisClic( int button, int state, int x, int y )
{
pressed = ( state == TP_PRESSE );
if ( pressed )
{
// on vient de presser la souris
dernierX = x;
dernierY = y;
switch ( button )
{
case TP_BOUTON_GAUCHE: // Tourner l'objet
deplace = deplaceCam;
break;
case TP_BOUTON_MILIEU: // Modifier l'orientation du spot
deplace = deplaceSpotDirection;
break;
case TP_BOUTON_DROIT: // Déplacer la lumière
deplace = deplaceSpotPosition;
break;
}
}
else
{
// on vient de relâcher la souris
}
}
void FenetreTP::sourisWheel( int x, int y ) // Changer la taille du spot
{
const int sens = +1;
LightSource[0].spotAngle += sens*y;
if ( LightSource[0].spotAngle > 90.0 ) LightSource[0].spotAngle = 90.0;
if ( LightSource[0].spotAngle < 0.0 ) LightSource[0].spotAngle = 0.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
}
// fonction de mouvement de la souris
void FenetreTP::sourisMouvement( int x, int y )
{
if ( pressed )
{
int dx = x - dernierX;
int dy = y - dernierY;
switch ( deplace )
{
case deplaceCam:
thetaCam -= dx / 3.0;
phiCam -= dy / 3.0;
break;
case deplaceSpotDirection:
LightSource[0].spotDirection.x += 0.06 * dx;
LightSource[0].spotDirection.y -= 0.06 * dy;
// std::cout << " LightSource[0].spotDirection=" << glm::to_string(LightSource[0].spotDirection) << std::endl;
break;
case deplaceSpotPosition:
LightSource[0].position.x += 0.03 * dx;
LightSource[0].position.y -= 0.03 * dy;
// std::cout << " LightSource[0].position=" << glm::to_string(LightSource[0].position) << std::endl;
//glm::vec3 ecranPos( x, hauteur_-y, ecranLumi[2] );
//LightSource[0].position = glm::vec4(glm::unProject( ecranPos, VM, P, cloture ), 1.0);
break;
}
dernierX = x;
dernierY = y;
verifierAngles();
}
}
int main( int argc, char *argv[] )
{
// créer une fenêtre
FenetreTP fenetre( "INF2705 TP" );
// allouer des ressources et définir le contexte OpenGL
initialiser();
bool boucler = true;
while ( boucler )
{
// mettre à jour la physique
calculerPhysique( );
// affichage
fenetre.afficherScene();
fenetre.swap();
// récupérer les événements et appeler la fonction de rappel
boucler = fenetre.gererEvenement();
}
// détruire les ressources OpenGL allouées
conclure();
return 0;
}

BIN
textures/TestIsland.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Loading…
Cancel
Save