int load_object(const char *path){ int objectId = glGenLists(1); glNewList(objectId, GL_COMPILE); ObjLoader obj; obj.Load(path); vector<Triangle> tr = obj.GetTriangles(); vector<Vector3f> v = obj.GetVertices(); vector<Vector3f> n = obj.GetNormals(); glBegin(GL_TRIANGLES); for(int i = 0; i < tr.size(); i++){ //printf("%i\n", i); glNormal3f(n[tr[i].n0].x, n[tr[i].n0].y, n[tr[i].n0].z); glVertex3f(v[tr[i].v0].x, v[tr[i].v0].y, v[tr[i].v0].z); //printf("%f %f %f\n", n[tr[i].n0].x, n[tr[i].n0].y, n[tr[i].n0].z); //printf("%f %f %f\n", v[tr[i].v0].x, v[tr[i].v0].y, v[tr[i].v0].z); glNormal3f(n[tr[i].n1].x, n[tr[i].n1].y, n[tr[i].n1].z); glVertex3f(v[tr[i].v1].x, v[tr[i].v1].y, v[tr[i].v1].z); //printf("%f %f %f\n", n[tr[i].n1].x, n[tr[i].n1].y, n[tr[i].n1].z); glNormal3f(n[tr[i].n2].x, n[tr[i].n2].y, n[tr[i].n2].z); glVertex3f(v[tr[i].v2].x, v[tr[i].v2].y, v[tr[i].v2].z); //printf("%f %f %f\n", n[tr[i].n2].x, n[tr[i].n2].y, n[tr[i].n2].z); //cout << tr[i].x << tr[i].y << tr[i].z << endl; } glEnd(); glEndList(); return objectId; }
//OpenGL initialization function void OnInit() { //generate the pseudorandom noise data glm::vec4 pData[64][64]; for(int j=0;j<64;j++) { for(int i=0;i<64;i++) { pData[i][j].x = (float)rand() / RAND_MAX; pData[i][j].y = (float)rand() / RAND_MAX; pData[i][j].z = (float)rand() / RAND_MAX; pData[i][j].w = (float)rand() / RAND_MAX; } } //use the pseudorandom noise data to generate a 64x64 nosie texture glGenTextures(1, &noiseTexID); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, noiseTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 64, 64, 0, GL_BGRA, GL_FLOAT, pData); //get the mesh path for loading of textures std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1); //load the obj model if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials)) { cout<<"Cannot load the Obj mesh"<<endl; exit(EXIT_FAILURE); } GL_CHECK_ERRORS //bind texture 0 as active texture unit glActiveTexture(GL_TEXTURE0); //load material textures for(size_t k=0;k<materials.size();k++) { //if the diffuse texture name is not empty if(materials[k]->map_Kd != "") { GLuint id = 0; //generate a new OpenGL texture glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); int texture_width = 0, texture_height = 0, channels=0; const string& filename = materials[k]->map_Kd; std::string full_filename = mesh_path; full_filename.append(filename); //use SOIL to load the texture GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO); if(pData == NULL) { cerr<<"Cannot load image: "<<full_filename.c_str()<<endl; exit(EXIT_FAILURE); } //Flip the image on Y axis int i,j; for( j = 0; j*2 < texture_height; ++j ) { int index1 = j * texture_width * channels; int index2 = (texture_height - 1 - j) * texture_width * channels; for( i = texture_width * channels; i > 0; --i ) { GLubyte temp = pData[index1]; pData[index1] = pData[index2]; pData[index2] = temp; ++index1; ++index2; } } //get the image format GLenum format = GL_RGBA; switch(channels) { case 2: format = GL_RG32UI; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; } //allocate the texture glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData); //release the SOIL image data SOIL_free_image_data(pData); //add the texture id to a vector textures.push_back(id); } } GL_CHECK_ERRORS //setup flat shader flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert"); flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag"); //compile and link shader flatShader.CreateAndLinkProgram(); flatShader.Use(); //add attribute and uniform flatShader.AddAttribute("vVertex"); flatShader.AddUniform("MVP"); flatShader.UnUse(); //load final shader finalShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert"); finalShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/final.frag"); //compile and link shader finalShader.CreateAndLinkProgram(); finalShader.Use(); //add attribute and uniform finalShader.AddAttribute("vVertex"); finalShader.AddUniform("MVP"); finalShader.AddUniform("textureMap"); //set values of constant uniforms as initialization glUniform1i(finalShader("textureMap"), 4); finalShader.UnUse(); //load the point light rendering shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag"); shader.CreateAndLinkProgram(); shader.Use(); //add attribute and uniform shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddAttribute("vUV"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("P"); shader.AddUniform("textureMap"); shader.AddUniform("useDefault"); shader.AddUniform("light_position"); shader.AddUniform("diffuse_color"); //set values of constant uniforms as initialization glUniform1i(shader("textureMap"), 0); shader.UnUse(); //load the horizontal Gaussian blurring shader gaussianH_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert"); gaussianH_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/GaussH.frag"); //compile and link shader gaussianH_shader.CreateAndLinkProgram(); gaussianH_shader.Use(); //add attribute and uniform gaussianH_shader.AddAttribute("vVertex"); gaussianH_shader.AddUniform("textureMap"); //set values of constant uniforms as initialization glUniform1i(gaussianH_shader("textureMap"),5); gaussianH_shader.UnUse(); //load the vertical Gaussian blurring shader gaussianV_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert"); gaussianV_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/GaussV.frag"); //compile and link shader gaussianV_shader.CreateAndLinkProgram(); gaussianV_shader.Use(); //add attribute and uniform gaussianV_shader.AddAttribute("vVertex"); gaussianV_shader.AddUniform("textureMap"); //set values of constant uniforms as initialization glUniform1i(gaussianV_shader("textureMap"),4); gaussianV_shader.UnUse(); //load the first step SSAO shader ssaoFirstShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/SSAO_FirstStep.vert"); ssaoFirstShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/SSAO_FirstStep.frag"); //compile and link shader ssaoFirstShader.CreateAndLinkProgram(); ssaoFirstShader.Use(); //add attribute and uniform ssaoFirstShader.AddAttribute("vVertex"); ssaoFirstShader.AddAttribute("vNormal"); ssaoFirstShader.AddUniform("MVP"); ssaoFirstShader.AddUniform("N"); ssaoFirstShader.UnUse(); //load the second step SSAO shader ssaoSecondShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert"); ssaoSecondShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/SSAO_SecondStep.frag"); //compile and link shader ssaoSecondShader.CreateAndLinkProgram(); ssaoSecondShader.Use(); //add attribute and uniform ssaoSecondShader.AddAttribute("vVertex"); ssaoSecondShader.AddUniform("samples"); ssaoSecondShader.AddUniform("invP"); ssaoSecondShader.AddUniform("normalTex"); ssaoSecondShader.AddUniform("depthTex"); ssaoSecondShader.AddUniform("noiseTex"); ssaoSecondShader.AddUniform("radius"); ssaoSecondShader.AddUniform("viewportSize"); ssaoSecondShader.AddUniform("invViewportSize"); //set values of constant uniforms as initialization glUniform2f(ssaoSecondShader("viewportSize"), float(RTT_WIDTH), float(RTT_HEIGHT)); glUniform2f(ssaoSecondShader("invViewportSize"), 1.0f/float(RTT_WIDTH), 1.0f/float(RTT_HEIGHT)); glUniform1i(ssaoSecondShader("normalTex"),1); glUniform1i(ssaoSecondShader("noiseTex"),2); glUniform1i(ssaoSecondShader("depthTex"),3); glm::mat4 biasMat; biasMat = glm::translate(glm::mat4(1),glm::vec3(0.5,0.5,0.5)); biasMat = glm::scale(biasMat, glm::vec3(0.5,0.5,0.5)); glm::mat4 invP = biasMat*glm::inverse(P); glUniformMatrix4fv(ssaoSecondShader("invP"), 1, GL_FALSE, glm::value_ptr(invP)); glm::vec2 samples[16]; float angle = (float)M_PI_4; for(int i=0;i<16;i++) { samples[i].x = cos(angle) * (float)(i+1)/16.0f; samples[i].y = sin(angle) * (float)(i+1)/16.0f; angle += (float)M_PI_2; if(((i + 1) % 4) == 0) angle += (float)M_PI_4; } glUniform2fv(ssaoSecondShader("samples"), 16, &(samples[0].x)); ssaoSecondShader.UnUse(); GL_CHECK_ERRORS //setup the vertex array object and vertex buffer object for the mesh //geometry handling glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass mesh vertices glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for vertex normal glEnableVertexAttribArray(shader["vNormal"]); glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) ); GL_CHECK_ERRORS //enable vertex attribute array for vertex texture coordinates glEnableVertexAttribArray(shader["vUV"]); glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) ); //if we have a single material, it means the 3ds model contains one mesh //we therefore load it into an element array buffer if(materials.size()==1) { //pass indices to the element array buffer if there is a single material glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW); } GL_CHECK_ERRORS //setup fullscreen quad vertices glm::vec2 quadVerts[4]; quadVerts[0] = glm::vec2(0,0); quadVerts[1] = glm::vec2(1,0); quadVerts[2] = glm::vec2(1,1); quadVerts[3] = glm::vec2(0,1); //setup quad indices GLushort quadIndices[]={ 0,1,2,0,2,3}; //setup quad vertex array and vertex buffer objects glGenVertexArrays(1, &quadVAOID); glGenBuffers(1, &quadVBOID); glGenBuffers(1, &quadIndicesID); glBindVertexArray(quadVAOID); glBindBuffer (GL_ARRAY_BUFFER, quadVBOID); //pass quad vertices to vertex buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0); //pass quad indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW); //glBindVertexArray(0); //setup vao and vbo stuff for the light position crosshair glm::vec3 crossHairVertices[6]; crossHairVertices[0] = glm::vec3(-0.5f,0,0); crossHairVertices[1] = glm::vec3(0.5f,0,0); crossHairVertices[2] = glm::vec3(0, -0.5f,0); crossHairVertices[3] = glm::vec3(0, 0.5f,0); crossHairVertices[4] = glm::vec3(0,0, -0.5f); crossHairVertices[5] = glm::vec3(0,0, 0.5f); //setup light gizmo vertex array and vertex buffer object IDs glGenVertexArrays(1, &lightVAOID); glGenBuffers(1, &lightVerticesVBO); glBindVertexArray(lightVAOID); glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO); //pass crosshair vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); GL_CHECK_ERRORS //use spherical coordinates to get the light position lightPosOS.x = radius * cos(theta)*sin(phi); lightPosOS.y = radius * cos(phi); lightPosOS.z = radius * sin(theta)*sin(phi); //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //set clear colour to corn blue glClearColor(0.5,0.5,1,1); //initializa FBO InitFBO(); cout<<"Initialization successfull"<<endl; }
//OpenGL initialization function void OnInit() { //get the mesh path for loading of textures std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1); //load the obj model if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials)) { cout<<"Cannot load the 3ds mesh"<<endl; exit(EXIT_FAILURE); } GL_CHECK_ERRORS //load material textures for(size_t k=0;k<materials.size();k++) { //if the diffuse texture name is not empty if(materials[k]->map_Kd != "") { //generate a new OpenGL array texture GLuint id = 0; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); int texture_width = 0, texture_height = 0, channels=0; const string& filename = materials[k]->map_Kd; std::string full_filename = mesh_path; full_filename.append(filename); //use SOIL to load the texture GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO); if(pData == NULL) { cerr<<"Cannot load image: "<<full_filename.c_str()<<endl; exit(EXIT_FAILURE); } //Flip the image on Y axis int i,j; for( j = 0; j*2 < texture_height; ++j ) { int index1 = j * texture_width * channels; int index2 = (texture_height - 1 - j) * texture_width * channels; for( i = texture_width * channels; i > 0; --i ) { GLubyte temp = pData[index1]; pData[index1] = pData[index2]; pData[index2] = temp; ++index1; ++index2; } } //get the image format GLenum format = GL_RGBA; switch(channels) { case 2: format = GL_RG32UI; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; } //allocate texture glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData); //release the SOIL image data SOIL_free_image_data(pData); //add loaded texture ID to vector textures.push_back(id); } } GL_CHECK_ERRORS //load flat shader flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert"); flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag"); //compile and link shader flatShader.CreateAndLinkProgram(); flatShader.Use(); //add attribute and uniform flatShader.AddAttribute("vVertex"); flatShader.AddUniform("MVP"); flatShader.UnUse(); //load mesh rendering shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag"); //compile and link shader shader.CreateAndLinkProgram(); shader.Use(); //add attribute and uniform shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddAttribute("vUV"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("P"); shader.AddUniform("textureMap"); shader.AddUniform("useDefault"); shader.AddUniform("light_position"); shader.AddUniform("diffuse_color"); //set values of constant uniforms as initialization glUniform1i(shader("textureMap"), 0); shader.UnUse(); GL_CHECK_ERRORS //setup the vertex array object and vertex buffer object for the mesh //geometry handling glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); //here we are using interleaved attributes so we can just push data to one //buffer object and then assign different atribute pointer to identofy the //different attributes glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass mesh vertices glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for vertex normal glEnableVertexAttribArray(shader["vNormal"]); glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) ); GL_CHECK_ERRORS //enable vertex attribute array for vertex texture coordinates glEnableVertexAttribArray(shader["vUV"]); glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) ); GL_CHECK_ERRORS //if we have a single material, it means the 3ds model contains one mesh //we therefore load it into an element array buffer if(materials.size()==1) { //pass indices to the element array buffer if there is a single material glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW); } GL_CHECK_ERRORS glBindVertexArray(0); //setup vao and vbo stuff for the light position crosshair glm::vec3 crossHairVertices[6]; crossHairVertices[0] = glm::vec3(-0.5f,0,0); crossHairVertices[1] = glm::vec3(0.5f,0,0); crossHairVertices[2] = glm::vec3(0, -0.5f,0); crossHairVertices[3] = glm::vec3(0, 0.5f,0); crossHairVertices[4] = glm::vec3(0,0, -0.5f); crossHairVertices[5] = glm::vec3(0,0, 0.5f); //setup light gizmo vertex array and vertex buffer object IDs glGenVertexArrays(1, &lightVAOID); glGenBuffers(1, &lightVerticesVBO); glBindVertexArray(lightVAOID); glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO); //pass crosshair vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); GL_CHECK_ERRORS //use spherical coordinates to get the light position lightPosOS.x = radius * cos(theta)*sin(phi); lightPosOS.y = radius * cos(phi); lightPosOS.z = radius * sin(theta)*sin(phi); //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //set the background colour to corn blue glClearColor(0.5,0.5,1,1); cout<<"Initialization successfull"<<endl; }
//OpenGL initialization function void OnInit() { //setup fullscreen quad geometry glm::vec2 quadVerts[4]; quadVerts[0] = glm::vec2(-1,-1); quadVerts[1] = glm::vec2(1,-1); quadVerts[2] = glm::vec2(1,1); quadVerts[3] = glm::vec2(-1,1); //setup quad indices GLushort quadIndices[]={ 0,1,2,0,2,3}; //setup quad vertex array and vertex buffer objects glGenVertexArrays(1, &quadVAOID); glGenBuffers(1, &quadVBOID); glGenBuffers(1, &quadIndicesID); glBindVertexArray(quadVAOID); glBindBuffer (GL_ARRAY_BUFFER, quadVBOID); //pass quad vertices to vertex buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0); //pass quad indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW); //get the mesh path for loading of textures std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1); //load the obj model vector<unsigned short> indices2; vector<glm::vec3> vertices2; if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials, aabb, vertices2, indices2)) { cout<<"Cannot load the 3ds mesh"<<endl; exit(EXIT_FAILURE); } GL_CHECK_ERRORS int total =0; //check the total number of non empty textures since we will use this //information to creare a single array texture to store all textures for(size_t k=0;k<materials.size();k++) { if(materials[k]->map_Kd != "") { total++; } } //load material textures for(size_t k=0;k<materials.size();k++) { //if the diffuse texture name is not empty if(materials[k]->map_Kd != "") { if(k==0) { //generate a new OpenGL array texture glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D_ARRAY, textureID); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP); } int texture_width = 0, texture_height = 0, channels=0; const string& filename = materials[k]->map_Kd; std::string full_filename = mesh_path; full_filename.append(filename); //use SOIL to load the texture GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO); if(pData == NULL) { cerr<<"Cannot load image: "<<full_filename.c_str()<<endl; exit(EXIT_FAILURE); } //Flip the image on Y axis int i,j; for( j = 0; j*2 < texture_height; ++j ) { int index1 = j * texture_width * channels; int index2 = (texture_height - 1 - j) * texture_width * channels; for( i = texture_width * channels; i > 0; --i ) { GLubyte temp = pData[index1]; pData[index1] = pData[index2]; pData[index2] = temp; ++index1; ++index2; } } //get the image format GLenum format = GL_RGBA; switch(channels) { case 2: format = GL_RG32UI; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; } //if this is the first texture, allocate the array texture if(k==0) { glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, format, texture_width, texture_height, total, 0, format, GL_UNSIGNED_BYTE, NULL); } //modify the existing texture glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0,0,0,k, texture_width, texture_height, 1, format, GL_UNSIGNED_BYTE, pData); //release the SOIL image data SOIL_free_image_data(pData); } } GL_CHECK_ERRORS //load flat shader flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert"); flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag"); //compile and link shader flatShader.CreateAndLinkProgram(); flatShader.Use(); //add attribute and uniform flatShader.AddAttribute("vVertex"); flatShader.AddUniform("MVP"); flatShader.UnUse(); //load raytracing shader raytraceShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/raytracer.vert"); raytraceShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/raytracer.frag"); //compile and link shader raytraceShader.CreateAndLinkProgram(); raytraceShader.Use(); //add attribute and uniform raytraceShader.AddAttribute("vVertex"); raytraceShader.AddUniform("eyePos"); raytraceShader.AddUniform("invMVP"); raytraceShader.AddUniform("light_position"); raytraceShader.AddUniform("backgroundColor"); raytraceShader.AddUniform("aabb.min"); raytraceShader.AddUniform("aabb.max"); raytraceShader.AddUniform("vertex_positions"); raytraceShader.AddUniform("triangles_list"); raytraceShader.AddUniform("VERTEX_TEXTURE_SIZE"); raytraceShader.AddUniform("TRIANGLE_TEXTURE_SIZE"); //set values of constant uniforms as initialization glUniform1f(raytraceShader("VERTEX_TEXTURE_SIZE"), (float)vertices2.size()); glUniform1f(raytraceShader("TRIANGLE_TEXTURE_SIZE"), (float)indices2.size()/4); glUniform3fv(raytraceShader("aabb.min"),1, glm::value_ptr(aabb.min)); glUniform3fv(raytraceShader("aabb.max"),1, glm::value_ptr(aabb.max)); glUniform4fv(raytraceShader("backgroundColor"),1, glm::value_ptr(bg)); glUniform1i(raytraceShader("vertex_positions"), 1); glUniform1i(raytraceShader("triangles_list"), 2); raytraceShader.UnUse(); GL_CHECK_ERRORS //load mesh rendering shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag"); //compile and link shader shader.CreateAndLinkProgram(); shader.Use(); //add attribute and uniform shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddAttribute("vUV"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("P"); shader.AddUniform("textureMap"); shader.AddUniform("textureIndex"); shader.AddUniform("useDefault"); shader.AddUniform("diffuse_color"); shader.AddUniform("light_position"); //set values of constant uniforms as initialization glUniform1i(shader("textureMap"), 0); shader.UnUse(); GL_CHECK_ERRORS //setup the vertex array object and vertex buffer object for the mesh //geometry handling glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass mesh vertices glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for vertex normal glEnableVertexAttribArray(shader["vNormal"]); glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) ); GL_CHECK_ERRORS //enable vertex attribute array for vertex texture coordinates glEnableVertexAttribArray(shader["vUV"]); glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) ); GL_CHECK_ERRORS //if we have a single material, it means the 3ds model contains one mesh //we therefore load it into an element array buffer if(materials.size()==1) { //pass indices to the element array buffer if there is a single material glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW); } GL_CHECK_ERRORS glBindVertexArray(0); //setup vao and vbo stuff for the light position crosshair glm::vec3 crossHairVertices[6]; crossHairVertices[0] = glm::vec3(-0.5f,0,0); crossHairVertices[1] = glm::vec3(0.5f,0,0); crossHairVertices[2] = glm::vec3(0, -0.5f,0); crossHairVertices[3] = glm::vec3(0, 0.5f,0); crossHairVertices[4] = glm::vec3(0,0, -0.5f); crossHairVertices[5] = glm::vec3(0,0, 0.5f); //setup light gizmo vertex array and vertex buffer object IDs glGenVertexArrays(1, &lightVAOID); glGenBuffers(1, &lightVerticesVBO); glBindVertexArray(lightVAOID); glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO); //pass crosshair vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for vertex position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); GL_CHECK_ERRORS //use spherical coordinates to get the light position lightPosOS.x = radius * cos(theta)*sin(phi); lightPosOS.y = radius * cos(phi); lightPosOS.z = radius * sin(theta)*sin(phi); //pass position to 1D texture bound to texture unit 1 glGenTextures(1, &texVerticesID); glActiveTexture(GL_TEXTURE1); glBindTexture( GL_TEXTURE_2D, texVerticesID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLfloat* pData = new GLfloat[vertices2.size()*4]; int count = 0; for(size_t i=0;i<vertices2.size();i++) { pData[count++] = vertices2[i].x; pData[count++] = vertices2[i].y; pData[count++] = vertices2[i].z; pData[count++] = 0; } //allocate a floating point texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, vertices2.size(),1, 0, GL_RGBA, GL_FLOAT, pData); //delete the data pointer delete [] pData; GL_CHECK_ERRORS //store the mesh topology in another texture bound to texture unit 2 glGenTextures(1, &texTrianglesID); glActiveTexture(GL_TEXTURE2); glBindTexture( GL_TEXTURE_2D, texTrianglesID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLushort* pData2 = new GLushort[indices2.size()]; count = 0; for(size_t i=0;i<indices2.size();i+=4) { pData2[count++] = (indices2[i]); pData2[count++] = (indices2[i+1]); pData2[count++] = (indices2[i+2]); pData2[count++] = (indices2[i+3]); } //allocate an integer format texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16I, indices2.size()/4,1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, pData2); //delete heap allocated buffer delete [] pData2; GL_CHECK_ERRORS //set texture unit 0 as active texture unit glActiveTexture(GL_TEXTURE0); //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //set the background colour glClearColor(bg.x, bg.y, bg.z, bg.w); cout<<"Initialization successfull"<<endl; //get the initial time lastTime = (float)glutGet(GLUT_ELAPSED_TIME); }