#include #include #include "inf2705.h" #include "constants.h" #include "FBO.h" #include "Packets.h" #include "util.h" #define SOL 1 enum {LocAttrib, LocUniform}; /* Shader location type */ enum { RWMP_SHADER, APD_SHADER, DPO_SHADER, DMM_SHADER, DT_SHADER, RAA_SHADER, NB_SHADERS }; /* Shaders stages */ // variables pour l'utilisation des nuanceurs GLuint prog; // votre programme de nuanceurs GLuint progRasterizeWaveMeshPosition; GLuint progAddPacketDisplacement; GLuint progDisplayPacketOutlined; GLuint progDisplayMicroMesh; GLuint progDisplayTerrain; GLuint progRenderAA; GLint locVertex = -1; GLint locNormal = -1; GLint locTexCoord = -1; GLint locmatrModel = -1; GLint locmatrVisu = -1; GLint locmatrProj = -1; GLint locmatrNormale = -1; GLint loclaTexture = -1; // Locations for RasterizeWaveMeshPosition shader GLint locVertexRWMP = -1; GLint locTexCoordRWMP = -1; GLint locmatrModelRWMP = -1; GLint locmatrVisuRWMP = -1; GLint locmatrProjRWMP = -1; GLint locmatrNormaleRWMP = -1; GLint locTexRWMP = -1; // Locations for AddPacketDisplacement shader GLuint locPosAPD = -1; GLuint locAtt1APD = -1; GLuint locAtt2APD = -1; GLuint locmatrModelAPD = -1; GLuint locmatrVisuAPD = -1; GLuint locmatrProjAPD = -1; GLuint locTexAPD = -1; // Locations for DisplayPacketOutlined shader GLuint locPosDPO = -1; GLuint locAtt1DPO = -1; GLuint locAtt2DPO = -1; GLuint locmatrModelDPO = -1; GLuint locmatrVisuDPO = -1; GLuint locmatrProjDPO = -1; GLuint locTexDPO = -1; // Locations for DisplayMicroMesh shader GLuint locVertexDMM = -1; GLuint locTexCoordDMM = -1; GLuint locmatrModelDMM = -1; GLuint locmatrVisuDMM = -1; GLuint locmatrProjDMM = -1; GLuint locTexDMM = -1; // Locationss for DisplayTerrain shader GLuint locVertexDT = -1; GLuint locTexCoordDT = -1; GLuint locmatrModelDT = -1; GLuint locmatrVisuDT = -1; GLuint locmatrProjDT = -1; GLuint locTexDT = -1; // Locations for RenderAA shader GLuint locVertexRAA = -1; GLuint locTexCoordRAA = -1; GLuint locmatrModelRAA = -1; GLuint locmatrVisuRAA = -1; GLuint locmatrProjRAA = -1; GLuint locTexRAA = -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[NB_SHADERS]; GLuint vbo[5]; GLuint ubo[4]; GLuint vbosQuad[2]; GLuint vboPacket; // 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 // FBOs FBO *posFBO; FBO *heightFBO; FBO *aaFBO; // Wave Packets Packets *packets; int packetBudget = 10000; /* Wave packets: * vec4: xy = position, zw = direction * vec4: x = amplitude, y = wavelength, z = phase offset, w = enveloppe size * vec4: for rendering x = center of wave bending circle*/ GLfloat packetData[PACKET_GPU_BUFFER_SIZE * 3 * 4]; //////////////////////////////////////// // déclaration des variables globales // //////////////////////////////////////// // partie 1: illumination int modele = 1; // le modèle à afficher // partie 3: texture GLuint texTerrain = 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'. ) /* Forward declarations */ void displayPacketOutlined(int count); void addPacketDisplacement(int count); 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; // 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 updatePackets() { // Compute wave packets packets->AdvectWavePackets(INIT_WAVE_SPEED); // TODO Setup wide projection for InitiateWaveField (RasterizeWaveMeshPosition) int displayedPackets = 0; int packetChunk =0; /* Standard wave packets */ for (int i = 0; i < packets->m_usedPackets; ++i) { int pk = packets->m_usedPacket[i]; /* Test for 3rd vertex (sliding point) */ if (!packets->m_packet[pk].use3rd) { /* Position */ packetData[packetChunk++] = packets->m_packet[pk].midPos.x(); packetData[packetChunk++] = packets->m_packet[pk].midPos.y(); /* Direction */ packetData[packetChunk++] = packets->m_packet[pk].travelDir.x(); packetData[packetChunk++] = packets->m_packet[pk].travelDir.y(); /* Att1 */ packetData[packetChunk++] = packets->m_packet[pk].ampOld; packetData[packetChunk++] = 2.0f * M_PI / packets->m_packet[pk].k; packetData[packetChunk++] = packets->m_packet[pk].phase; packetData[packetChunk++] = packets->m_packet[pk].envelope; /* Att2 */ packetData[packetChunk++] = packets->m_packet[pk].bending; packetChunk += 3; /* The last 3 elements aren't needed */ displayedPackets++; if (packetChunk >= PACKET_GPU_BUFFER_SIZE * 3 * 4) { glBindBuffer(GL_ARRAY_BUFFER, vboPacket); /* TODO Use Buffer mapping for better performance */ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(packetData), packetData); glBindBuffer(GL_ARRAY_BUFFER, 0); //displayPacketOutlined(packetChunk / 12); /* TODO EvaluatePackets(packetChunk) */ addPacketDisplacement(packetChunk / 12); packetChunk = 0; } } } // printf("PacketData[0] = %f , %f\n", packetData[0], packetData[1]); /* Ghost packets */ for (int i = 0; i < packets->m_usedGhosts; ++i) { int pk = packets->m_usedGhost[i]; /* Position */ packetData[packetChunk++] = packets->m_ghostPacket[pk].pos.x(); packetData[packetChunk++] = packets->m_ghostPacket[pk].pos.y(); /* Direction */ packetData[packetChunk++] = packets->m_ghostPacket[pk].dir.x(); packetData[packetChunk++] = packets->m_ghostPacket[pk].dir.y(); /* Att1 */ packetData[packetChunk++] = packets->m_ghostPacket[pk].ampOld; packetData[packetChunk++] = 2.0f * M_PI / packets->m_ghostPacket[pk].k; packetData[packetChunk++] = packets->m_ghostPacket[pk].phase; packetData[packetChunk++] = packets->m_ghostPacket[pk].envelope; /* Att2 */ packetData[packetChunk++] = packets->m_ghostPacket[pk].bending; packetChunk += 3; /* The last 3 elements aren't needed */ displayedPackets++; if (packetChunk >= PACKET_GPU_BUFFER_SIZE * 3 * 4) { glBindBuffer(GL_ARRAY_BUFFER, vboPacket); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(packetData), packetData); glBindBuffer(GL_ARRAY_BUFFER, 0); //displayPacketOutlined(); /* TODO EvaluatePackets(packetChunk) */ addPacketDisplacement(packetChunk / 12); packetChunk = 0; } } glBindBuffer(GL_ARRAY_BUFFER, vboPacket); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(packetData), packetData); glBindBuffer(GL_ARRAY_BUFFER, 0); //displayPacketOutlined(packetChunk / 12); /* TODO EvaluatePackets(packetChunk) */ addPacketDisplacement(packetChunk / 12); /* TODO DisplayScene */ /* TODO Get camera center */ } void chargerTextures() { unsigned char *pixels; GLsizei largeur, hauteur; if ( ( pixels = ChargerImage( WATER_TERRAIN_FILE, largeur, hauteur ) ) != NULL ) { glGenTextures( 1, &texTerrain ); glBindTexture( GL_TEXTURE_2D, texTerrain ); 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_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); } /* Create program and link it * Input : filenames for vertex, geometry and fragment shader, or NULL*/ GLuint createShader(const GLchar *shaders[3]) { GLuint prog; GLenum shaderType[3] = { GL_VERTEX_SHADER, GL_GEOMETRY_SHADER, GL_FRAGMENT_SHADER }; prog = glCreateProgram(); for (int i = 0; i < 3; ++i) { if (shaders[i] != NULL) { printf("Compiling %s ...\n", shaders[i]); const GLchar *shaderStr = ProgNuanceur::lireNuanceur(shaders[i]); if (shaderStr == NULL) break; GLuint s = glCreateShader(shaderType[i]); glShaderSource( s, 1, &shaderStr, NULL ); glCompileShader( s ); glAttachShader( prog, s ); ProgNuanceur::afficherLogCompile( s ); delete [] shaderStr; } } glLinkProgram(prog); ProgNuanceur::afficherLogLink(prog); return prog; } GLuint getloc(GLuint prog, const GLchar *name, const int type) { GLuint loc; switch (type) { case LocAttrib: loc = glGetAttribLocation(prog, name); break; case LocUniform: loc = glGetUniformLocation(prog, name); break; } if (loc == -1) fprintf(stderr, "Cannot find location for %s\n", name); return loc; } 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 locVertexBase = getloc( progBase, "Vertex", LocAttrib ); locColorBase = getloc( progBase, "Color", LocAttrib ); locmatrModelBase = getloc( progBase, "matrModel", LocUniform ); locmatrVisuBase = getloc( progBase, "matrVisu", LocUniform ); locmatrProjBase = getloc( progBase, "matrProj", LocUniform ); } // Load RasterizeWaveMeshPosition shader { // créer le programme const GLchar *shaders[3] = {"rasterizeWaveMeshPosition.vert", NULL, "rasterizeWaveMeshPosition.frag"}; progRasterizeWaveMeshPosition = createShader(shaders); // demander la "Location" des variables locVertexRWMP = getloc( progRasterizeWaveMeshPosition, "Vertex" , LocAttrib); locTexCoordRWMP = getloc( progRasterizeWaveMeshPosition, "TexCoord" , LocAttrib); locmatrModelRWMP = getloc( progRasterizeWaveMeshPosition, "matrModel" , LocUniform); locmatrVisuRWMP = getloc( progRasterizeWaveMeshPosition, "matrVisu" , LocUniform); locmatrProjRWMP = getloc( progRasterizeWaveMeshPosition, "matrProj" , LocUniform); locTexRWMP = getloc( progRasterizeWaveMeshPosition, "tex" , LocUniform); } // Load AddPacketDisplacement shader { // créer le programme const GLchar *shaders[3] = {"addPacketDisplacement.vert", "addPacketDisplacement.geom", "addPacketDisplacement.frag"}; progAddPacketDisplacement = createShader(shaders); // demander la "Location" des variables locPosAPD = getloc( progAddPacketDisplacement, "Pos" , LocAttrib); locAtt1APD = getloc( progAddPacketDisplacement, "Att1" , LocAttrib); locAtt2APD = getloc( progAddPacketDisplacement, "Att2" , LocAttrib); locmatrModelAPD = getloc( progAddPacketDisplacement, "matrModel" , LocUniform); locmatrVisuAPD = getloc( progAddPacketDisplacement, "matrVisu" , LocUniform); locmatrProjAPD = getloc( progAddPacketDisplacement, "matrProj" , LocUniform); locTexAPD = getloc( progAddPacketDisplacement, "tex" , LocUniform); } // Load DisplayPacketOutlined shader { const GLchar *shaders[3] = {"displayPacketOutlined.vert", "displayPacketOutlined.geom", "displayPacketOutlined.frag"}; progDisplayPacketOutlined = createShader(shaders); locPosDPO = getloc( progDisplayPacketOutlined, "Pos" , LocAttrib); locAtt1DPO = getloc( progDisplayPacketOutlined, "Att1" , LocAttrib); locAtt2DPO = getloc( progDisplayPacketOutlined, "Att2" , LocAttrib); locmatrModelDPO = getloc( progDisplayPacketOutlined, "matrModel" , LocUniform); locmatrVisuDPO = getloc( progDisplayPacketOutlined, "matrVisu" , LocUniform); locmatrProjDPO = getloc( progDisplayPacketOutlined, "matrProj" , LocUniform); locTexDPO = getloc( progDisplayPacketOutlined, "tex" , LocUniform); } // Load DisplayMicroMesh shader { const GLchar *shaders[3] = {"displayMicroMesh.vert", "displayMicroMesh.geom", "displayMicroMesh.frag"}; progDisplayMicroMesh = createShader(shaders); locVertexDMM = getloc( progDisplayMicroMesh, "Vertex" , LocAttrib); locTexCoordDMM = getloc( progDisplayMicroMesh, "TexCoord" , LocAttrib); locmatrModelDMM = getloc( progDisplayMicroMesh, "matrModel" , LocUniform); locmatrVisuDMM = getloc( progDisplayMicroMesh, "matrVisu" , LocUniform); locmatrProjDMM = getloc( progDisplayMicroMesh, "matrProj" , LocUniform); locTexDMM = getloc( progDisplayMicroMesh, "tex" , LocUniform); } // Load DisplayTerrain shader { const GLchar *shaders[3] = {"displayTerrain.vert", NULL, "displayTerrain.frag"}; progDisplayTerrain = createShader(shaders); locVertexDT = getloc( progDisplayTerrain, "Vertex" , LocAttrib); locTexCoordDT = getloc( progDisplayTerrain, "TexCoord" , LocAttrib); locmatrModelDT = getloc( progDisplayTerrain, "matrModel" , LocUniform); locmatrVisuDT = getloc( progDisplayTerrain, "matrVisu" , LocUniform); locmatrProjDT = getloc( progDisplayTerrain, "matrProj" , LocUniform); locTexDT = getloc( progDisplayTerrain, "tex" , LocUniform); } // Load RenderAA shader { const GLchar *shaders[3] = {"renderAA.vert", NULL, "RenderAA.frag"}; progRenderAA = createShader(shaders); locVertexRAA = getloc( progRenderAA, "Vertex" , LocAttrib); locTexCoordRAA = getloc( progRenderAA, "TexCoord" , LocAttrib); locmatrModelRAA = getloc( progRenderAA, "matrModel" , LocUniform); locmatrVisuRAA = getloc( progRenderAA, "matrVisu" , LocUniform); locmatrProjRAA = getloc( progRenderAA, "matrProj" , LocUniform); locTexRAA = getloc( progRenderAA, "tex" , LocUniform); } } // Create a screen space quad void initQuad() { GLfloat vertices[3*2*2] = { -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0 }; GLfloat texcoords[3*2*2] = { 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 }; // allouer les objets OpenGL /* TODO Add support for RenderAA shader */ glGenBuffers( 2, vbosQuad ); /* Prepare VAO for RasterizeWaveMeshPosition shader */ glBindVertexArray(vao[RWMP_SHADER]); // Bind vertices VBO glBindBuffer( GL_ARRAY_BUFFER, vbosQuad[0] ); glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW ); glVertexAttribPointer( locVertexRWMP, 2, GL_FLOAT, GL_FALSE, 0, 0 ); glEnableVertexAttribArray(locVertexRWMP); // Bind texture coord VBO glBindBuffer( GL_ARRAY_BUFFER, vbosQuad[1] ); glBufferData( GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW ); glVertexAttribPointer( locTexCoordRWMP, 2, GL_FLOAT, GL_FALSE, 0, 0 ); glEnableVertexAttribArray(locTexCoordRWMP); /* Prepare VAO for RenderAA shader */ glBindVertexArray(vao[RAA_SHADER]); // Bind vertices VBO glBindBuffer( GL_ARRAY_BUFFER, vbosQuad[0] ); glVertexAttribPointer( locVertexRAA, 2, GL_FLOAT, GL_FALSE, 0, 0 ); glEnableVertexAttribArray(locVertexRAA); // Bind texture coord VBO glBindBuffer( GL_ARRAY_BUFFER, vbosQuad[1] ); glVertexAttribPointer( locTexCoordRAA, 2, GL_FLOAT, GL_FALSE, 0, 0 ); glEnableVertexAttribArray(locTexCoordRAA); } // Create the buffer to store wave packets void initPacketMesh() { glGenBuffers(1, &vboPacket); glBindVertexArray(vao[APD_SHADER]); glBindBuffer(GL_ARRAY_BUFFER, vboPacket); glBufferData(GL_ARRAY_BUFFER, sizeof(packetData), NULL, GL_DYNAMIC_DRAW); glVertexAttribPointer(locPosAPD, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)0); glVertexAttribPointer(locAtt1APD, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)4); glVertexAttribPointer(locAtt2APD, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)8); glEnableVertexAttribArray(locPosAPD); glEnableVertexAttribArray(locAtt1APD); glEnableVertexAttribArray(locAtt2APD); glBindVertexArray(vao[DPO_SHADER]); glBindBuffer(GL_ARRAY_BUFFER, vboPacket); /* No need to initialize the buffer a second time */ glVertexAttribPointer(locPosDPO, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)0); glVertexAttribPointer(locAtt1DPO, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)4); glVertexAttribPointer(locAtt2DPO, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (void*)8); glEnableVertexAttribArray(locPosDPO); glEnableVertexAttribArray(locAtt1DPO); glEnableVertexAttribArray(locAtt2DPO); glBindVertexArray(0); } // initialisation d'openGL void initialiser() { // donner l'orientation du modèle thetaCam = 0.0; phiCam = 0.0; distCam = 90.0; // Create FBOs posFBO = new FBO(); heightFBO = new FBO(); aaFBO = new FBO(); // Create Packets packets = new Packets(packetBudget); // 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 ); glGenVertexArrays(NB_SHADERS, vao); // charger les nuanceurs chargerNuanceurs(); // Initialize VBOs initQuad(); initPacketMesh(); // 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 ); // Update display mesh and FBOs // redimensionner(); } void conclure() { glUseProgram( 0 ); glDeleteVertexArrays( NB_SHADERS, vao ); glDeleteBuffers( 4, vbo ); glDeleteBuffers( 4, ubo ); delete sphere; delete sphereLumi; delete theiere; delete tore; delete cylindre; delete cone; delete posFBO; delete heightFBO; delete aaFBO; delete packets; } void drawQuad() { glUseProgram(progRasterizeWaveMeshPosition); glUniformMatrix4fv( locmatrProjRWMP, 1, GL_FALSE, matrProj ); glUniformMatrix4fv( locmatrVisuRWMP, 1, GL_FALSE, matrVisu ); glUniformMatrix4fv( locmatrModelRWMP, 1, GL_FALSE, matrModel ); glBindVertexArray(vao[RWMP_SHADER]); glDrawArrays(GL_TRIANGLES, 0, 6); } void displayPacketOutlined(int count) { glUseProgram(progDisplayPacketOutlined); glBindVertexArray(vao[DPO_SHADER]); glUniformMatrix4fv(locmatrModelDPO, 1, GL_FALSE, matrModel); glUniformMatrix4fv(locmatrVisuDPO, 1, GL_FALSE, matrVisu); glUniformMatrix4fv(locmatrProjDPO, 1, GL_FALSE, matrProj); glDrawArrays(GL_POINTS, 0, count); glBindVertexArray(0); glUseProgram(0); } void addPacketDisplacement(int count) { glUseProgram(progAddPacketDisplacement); glBindVertexArray(vao[APD_SHADER]); glUniformMatrix4fv(locmatrModelAPD, 1, GL_FALSE, matrModel); glUniformMatrix4fv(locmatrVisuAPD, 1, GL_FALSE, matrVisu); glUniformMatrix4fv(locmatrProjAPD, 1, GL_FALSE, matrProj); glDrawArrays(GL_POINTS, 0, count); glBindVertexArray(0); glUseProgram(0); } void afficherModele() { // 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 ); updatePackets(); } matrModel.PopMatrix(); } 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, 300.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, 300.0 ); } else { matrProj.Ortho( -d*(GLdouble)largeur_ / (GLdouble)hauteur_, d*(GLdouble)largeur_ / (GLdouble)hauteur_, -d, d, 0.1, 300.0 ); } } glUniformMatrix4fv( locmatrProjBase, 1, GL_FALSE, matrProj ); matrVisu.LookAt( 0.0, 3.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 //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 ) { std::cout << "Resizing to " << w << "×" << h << std::endl; /* FIXME Is this function called on program start ? */ glViewport( 0, 0, w, h ); /* TODO Create/resize display mesh */ posFBO->Liberer(); posFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h); heightFBO->Liberer(); heightFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h); aaFBO->Liberer(); aaFBO->Init(AA_OVERSAMPLE_FACTOR * w, AA_OVERSAMPLE_FACTOR * 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 // Send one wave front packets->CreateCircularWavefront(0.0, 0.0, 2.0, 0.2, 1.0, 10000); printf("Sending a circular wavefront...\n"); 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; }