//scene rendering function void DrawScene(const glm::mat4& View, const glm::mat4& Proj ) { GL_CHECK_ERRORS //bind the current shader shader.Use(); //bind the cube vertex array object glBindVertexArray(cubeVAOID); { //set the cube's transform glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(-1,1,0)); glm::mat4 M = T; //Model matrix glm::mat4 MV = View*M; //ModelView matrix glm::mat4 MVP = Proj*MV; //combined ModelView Projection matrix //pass shader uniforms glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniform3f(shader("diffuse_color"), 1.0f,0.0f,0.0f); glUniform3fv(shader("light_position"),1, &(lightPosOS.x)); //draw triangles glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); } //bind the sphere vertex array object glBindVertexArray(sphereVAOID); { //set the sphere's transform glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(1,1,0)); glm::mat4 M = T; glm::mat4 MV = View*M; glm::mat4 MVP = Proj*MV; //pass shader uniforms glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniform3f(shader("diffuse_color"), 0.0f, 0.0f, 1.0f); //draw triangles glDrawElements(GL_TRIANGLES, totalSphereTriangles, GL_UNSIGNED_SHORT, 0); } //unbind shader shader.UnUse(); GL_CHECK_ERRORS //bind light gizmo vertex array object glBindVertexArray(lightVAOID); { //set light's transform glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS); //bind shader and draw 3 lines pFlatShader->Use(); glUniformMatrix4fv((*pFlatShader)("MVP"), 1, GL_FALSE, glm::value_ptr(Proj*View*T)); glDrawArrays(GL_LINES, 0, 6); //unbind shader pFlatShader->UnUse(); } //unbind the vertex array object glBindVertexArray(0); //render grid object grid->Render(glm::value_ptr(Proj*View)); }
//OpenGL initialization void OnInit() { //init high performance timer QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&last); //get mesh path std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("//")+1); glm::vec3 min, max; //load the EZmesh file if(!ezm.Load(mesh_filename.c_str(), skeleton, animations, submeshes, vertices, indices, material2ImageMap, min, max)) { cout<<"Cannot load the EZMesh file"<<endl; exit(EXIT_FAILURE); } //check the absolute value y and z dimensions of the bounding box float dy = fabs(max.y-min.y); float dz = fabs(max.z-min.z); bYup = (dy>dz); //get the combined bone transform UpdateCombinedMatrices(); //resize bind pose, inverse bind pose, animatedXform and dualQuaternion vectors bindPose.resize(skeleton.size()); invBindPose.resize(skeleton.size()); animatedXform.resize(skeleton.size()); dualQuaternions.resize(skeleton.size()); //store the bind pose matrices which are the absolute transform of //each bone. Also store their inverse which is used in skinning for(size_t i=0;i<skeleton.size();i++) { bindPose[i] = (skeleton[i].comb); invBindPose[i] = glm::inverse(bindPose[i]); } GL_CHECK_ERRORS //store the loaded material names into a vector for(iter i = material2ImageMap.begin();i!=material2ImageMap.end();++i) { materialNames.push_back(i->second); } //calculate the distance the camera has to be moved to properly view the EZMesh model center = (max + min) * 0.5f; glm::vec3 diagonal = (max-min); radius = glm::length(center- diagonal * 0.5f); dist = -glm::length(diagonal); //generate OpenGL textures from the loaded material names for(size_t k=0;k<materialNames.size();k++) { if(materialNames[k].length()==0) continue; //get the full image name int texture_width = 0, texture_height = 0, channels=0; const string& filename = materialNames[k]; std::string full_filename = mesh_path; full_filename.append(filename); //pass the full image name including the path and use SOIL library to load the image 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; } } //determine 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; } GLuint id = 0; //generate new texture id glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); //set texture parameters 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); //allocate the texture glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData); //delete the SOIL image data SOIL_free_image_data(pData); //store the texture id into the material map. Refer to the texture by name //will give us its OpenGL texture id materialMap[filename] = id ; } GL_CHECK_ERRORS //setup shaders flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert"); flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag"); //compile and link flat shader flatShader.CreateAndLinkProgram(); flatShader.Use(); //add shader attributes and uniforms flatShader.AddAttribute("vVertex"); flatShader.AddUniform("MVP"); flatShader.UnUse(); //For the skinning vertex shader, we pass the Bones array dynamcially //since we may not know the total number of bones in the model at compile //time. Since the GLSL arrays have to be a compile time constant, we //dynamically generate the shader string to add the uniform in the shader. //To achieve this, we overload the GLSLShader::LoadFromFile function with //a thid parameter, the string we want to add before the shader main function. stringstream str( ios_base::app | ios_base::out); str<<"\nconst int NUM_BONES="<<skeleton.size()*2<<";"<<endl; str<<"uniform vec4 Bones[NUM_BONES];"<<endl; shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert", str.str()); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag"); //compile and link shader shader.CreateAndLinkProgram(); shader.Use(); //add shader attributes and uniforms shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddAttribute("vUV"); shader.AddAttribute("vBlendWeights"); shader.AddAttribute("viBlendIndices"); shader.AddUniform("Bones"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("P"); shader.AddUniform("textureMap"); shader.AddUniform("useDefault"); shader.AddUniform("light_position"); shader.AddUniform("diffuse_color"); glUniform1i(shader("textureMap"), 0); //pass values to uniforms at initialization, since we have a dual quaternion we pass //it as 2 vec4 variables hence the multiplication by 2 glUniform4fv(shader("Bones"), skeleton.size()*2, &(dualQuaternions[0].ordinary.x)); shader.UnUse(); GL_CHECK_ERRORS //setup geometry //setup vao and vbo stuff glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass vertices to buffer object memory glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_DYNAMIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable normal attribute glEnableVertexAttribArray(shader["vNormal"]); glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) ); GL_CHECK_ERRORS //enable texture coordinate attribute glEnableVertexAttribArray(shader["vUV"]); glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) ); GL_CHECK_ERRORS //enable blend weights attribute array glEnableVertexAttribArray(shader["vBlendWeights"]); glVertexAttribPointer(shader["vBlendWeights"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, blendWeights)) ); GL_CHECK_ERRORS //enable blend indices attribute array glEnableVertexAttribArray(shader["viBlendIndices"]); glVertexAttribIPointer(shader["viBlendIndices"], 4, GL_INT, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, blendIndices)) ); GL_CHECK_ERRORS //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); //generate light vertex array and buffer object glGenVertexArrays(1, &lightVAOID); glGenBuffers(1, &lightVerticesVBO); glBindVertexArray(lightVAOID); //pass the cross hair data to the buffer object memory glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO); glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_DYNAMIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); GL_CHECK_ERRORS //get the light position using the center and the spherical coordinates lightPosOS.x = center.x + radius * cos(theta)*sin(phi); lightPosOS.y = center.y + radius * cos(phi); lightPosOS.z = center.z + radius * sin(theta)*sin(phi); //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //set clear color to corn blue glClearColor(0.5,0.5,1,1); cout<<"Initialization successfull"<<endl; }
//OpenGL initialization void OnInit() { GL_CHECK_ERRORS //load heightmap 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 attributes and uniforms shader.AddAttribute("vVertex"); shader.AddUniform("heightMapTexture"); shader.AddUniform("scale"); shader.AddUniform("half_scale"); shader.AddUniform("HALF_TERRAIN_SIZE"); shader.AddUniform("MVP"); //set values of constant uniforms as initialization glUniform1i(shader("heightMapTexture"), 0); glUniform2i(shader("HALF_TERRAIN_SIZE"), TERRAIN_WIDTH>>1, TERRAIN_DEPTH>>1); glUniform1f(shader("scale"), scale); glUniform1f(shader("half_scale"), half_scale); shader.UnUse(); GL_CHECK_ERRORS //fill indices array GLuint* id=&indices[0]; int i=0, j=0; //setup vertices int count = 0; //fill terrain vertices for( j=0;j<TERRAIN_DEPTH;j++) { for( i=0;i<TERRAIN_WIDTH;i++) { vertices[count] = glm::vec3( (float(i)/(TERRAIN_WIDTH-1)), 0, (float(j)/(TERRAIN_DEPTH-1))); count++; } } //fill terrain indices for (i = 0; i < TERRAIN_DEPTH-1; i++) { for (j = 0; j < TERRAIN_WIDTH-1; j++) { int i0 = j+ i*TERRAIN_WIDTH; int i1 = i0+1; int i2 = i0+TERRAIN_WIDTH; int i3 = i2+1; *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } } GL_CHECK_ERRORS //setup terrain vertex array and vertex buffer objects glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass terrain vertices to buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0); GL_CHECK_ERRORS //pass the terrain indices array to element array buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //load the heightmap texture using SOIL int texture_width = 0, texture_height = 0, channels=0; GLubyte* pData = SOIL_load_image(filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_L); //vertically flip the heightmap image on Y axis since it is inverted for( j = 0; j*2 < texture_height; ++j ) { int index1 = j * texture_width ; int index2 = (texture_height - 1 - j) * texture_width ; for( i = texture_width ; i > 0; --i ) { GLubyte temp = pData[index1]; pData[index1] = pData[index2]; pData[index2] = temp; ++index1; ++index2; } } //setup OpenGL texture glGenTextures(1, &heightMapTextureID); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, heightMapTextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture_width, texture_height, 0, GL_RED, GL_UNSIGNED_BYTE, pData); //free SOIL image data SOIL_free_image_data(pData); GL_CHECK_ERRORS //set polygon mode to draw lines glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); GL_CHECK_ERRORS cout<<"Initialization successfull"<<endl; }
//OpenGL initialization void OnInit() { //load the per-fragment point light shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/PointLight.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/PointLight.frag"); //compile and link shader shader.CreateAndLinkProgram(); shader.Use(); //add attributes and uniforms shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddUniform("MVP"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("light_position"); shader.AddUniform("diffuse_color"); shader.UnUse(); GL_CHECK_ERRORS //setup sphere geometry CreateSphere(1.0f,10,10, vertices, indices); //setup sphere vao and vbo stuff glGenVertexArrays(1, &sphereVAOID); glGenBuffers(1, &sphereVerticesVBO); glGenBuffers(1, &sphereIndicesVBO); glBindVertexArray(sphereVAOID); glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO); //pass vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal))); GL_CHECK_ERRORS //pass sphere indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO); glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW); //store the total number of sphere triangles totalSphereTriangles = indices.size(); //clear the vertices and indices vectors as we will reuse them //for cubes vertices.clear(); indices.clear(); //setup cube geometry CreateCube(2,vertices, indices); //setup cube vao and vbo stuff glGenVertexArrays(1, &cubeVAOID); glGenBuffers(1, &cubeVerticesVBO); glGenBuffers(1, &cubeIndicesVBO); glBindVertexArray(cubeVAOID); glBindBuffer (GL_ARRAY_BUFFER, cubeVerticesVBO); //pass vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal))); GL_CHECK_ERRORS //pass cube indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO); glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //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 buffer object glGenVertexArrays(1, &lightVAOID); glGenBuffers(1, &lightVerticesVBO); glBindVertexArray(lightVAOID); glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO); //pass light crosshair gizmo vertices to buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); GL_CHECK_ERRORS //enable depth testing and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); GL_CHECK_ERRORS //create a grid of 10x10 size in XZ plane grid = new CGrid(); GL_CHECK_ERRORS //get the grid shader for rendering of the light's crosshair gizmo pFlatShader = grid->GetShader(); //get the light position using the spherical coordinates lightPosOS.x = radius * cos(theta)*sin(phi); lightPosOS.y = radius * cos(phi); lightPosOS.z = radius * sin(theta)*sin(phi); 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); }
//update and rendering of cloth particles void RenderGPU_TF() { CHECK_GL_ERRORS //set the cloth vertex shader massSpringShader.Use(); CHECK_GL_ERRORS //pass shader uniforms glUniformMatrix4fv(massSpringShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP)); CHECK_GL_ERRORS //run the iteration loop for(int i=0;i<NUM_ITER;i++) { //set the buffer texture for current position glActiveTexture( GL_TEXTURE0); glBindTexture( GL_TEXTURE_BUFFER, texPosID[writeID]); //set the buffer texture for previous position glActiveTexture( GL_TEXTURE1); glBindTexture( GL_TEXTURE_BUFFER, texPrePosID[writeID]); //set the update vertex array object glBindVertexArray( vaoUpdateID[writeID]); //bind transform feedback buffers //index 0 -> current position //index 1 -> previous position glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vboID_Pos[readID]); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, vboID_PrePos[readID]); // disable rasterization glEnable(GL_RASTERIZER_DISCARD); //run hardware timer query glBeginQuery(GL_TIME_ELAPSED,t_query); //initiate transform feedback glBeginTransformFeedback(GL_POINTS); //render points, this call pushes all attributes to GPU glDrawArrays(GL_POINTS, 0, total_points); //end transform feedback glEndTransformFeedback(); //end timer query glEndQuery(GL_TIME_ELAPSED); glFlush(); //enable rasterizer glDisable(GL_RASTERIZER_DISCARD); //swap read/write pathways int tmp = readID; readID=writeID; writeID = tmp; } CHECK_GL_ERRORS // get the query result glGetQueryObjectui64v(t_query, GL_QUERY_RESULT, &elapsed_time); //get the transform feedback time delta_time = elapsed_time / 1000000.0f; //remove the cloth vertex shader massSpringShader.UnUse(); CHECK_GL_ERRORS; //bind the render vertex array object glBindVertexArray(vaoRenderID[writeID]); //disable depth test glDisable(GL_DEPTH_TEST); //set the render shader renderShader.Use(); //set the shader uniform glUniformMatrix4fv(renderShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP)); //draw the cloth geometry glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT,0); //remove render shader renderShader.UnUse(); //enable depth test glEnable(GL_DEPTH_TEST); //if we want to display masses if(bDisplayMasses) { //set the particle shader particleShader.Use(); //set shader uniforms glUniform1i(particleShader("selected_index"), selected_index); glUniformMatrix4fv(particleShader("MV"), 1, GL_FALSE, glm::value_ptr(mMV)); glUniformMatrix4fv(particleShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP)); //draw the masses last glDrawArrays(GL_POINTS, 0, total_points); //this also renders particles //glDrawTransformFeedbackStream(GL_POINTS, tfID, 0); //remove the particle shader particleShader.UnUse(); } //remove the currently bound vertex array object glBindVertexArray( 0); CHECK_GL_ERRORS }
//OpenGL initialization void OnInit() { //set the polygon mode to render lines glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); GL_CHECK_ERRORS //load 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 shader attribute and uniforms shader.AddAttribute("vVertex"); shader.AddUniform("MVP"); shader.AddUniform("time"); shader.UnUse(); GL_CHECK_ERRORS //setup plane geometry //setup plane vertices int count = 0; int i=0, j=0; for( j=0;j<=NUM_Z;j++) { for( i=0;i<=NUM_X;i++) { vertices[count++] = glm::vec3( ((float(i)/(NUM_X-1)) *2-1)* HALF_SIZE_X, 0, ((float(j)/(NUM_Z-1))*2-1)*HALF_SIZE_Z); } } //fill plane indices array GLushort* id=&indices[0]; for (i = 0; i < NUM_Z; i++) { for (j = 0; j < NUM_X; j++) { int i0 = i * (NUM_X+1) + j; int i1 = i0 + 1; int i2 = i0 + (NUM_X+1); int i3 = i2 + 1; if ((j+i)%2) { *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } else { *id++ = i0; *id++ = i2; *id++ = i3; *id++ = i0; *id++ = i3; *id++ = i1; } } } GL_CHECK_ERRORS //setup plane vao and vbo stuff glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); //pass plane vertices to array buffer object glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attrib array for position glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0); GL_CHECK_ERRORS //pass the plane indices to element array buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS cout<<"Initialization successfull"<<endl; }
void OnInit() { GL_CHECK_ERRORS //setup shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert"); shader.LoadFromFile(GL_GEOMETRY_SHADER, "shaders/shader.geom"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag"); shader.CreateAndLinkProgram(); shader.Use(); shader.AddAttribute("vVertex"); shader.AddUniform("heightMapTexture"); shader.AddUniform("scale"); shader.AddUniform("half_scale"); shader.AddUniform("HALF_TERRAIN_SIZE"); shader.AddUniform("MVP"); glUniform1i(shader("heightMapTexture"), 0); glUniform2i(shader("HALF_TERRAIN_SIZE"), TERRAIN_WIDTH>>1, TERRAIN_DEPTH>>1); glUniform1f(shader("scale"), scale); glUniform1f(shader("half_scale"), half_scale); shader.UnUse(); GL_CHECK_ERRORS //setup geometry //fill indices array GLuint* id=&indices[0]; int i=0, j=0; //setup vertices int count = 0; for( j=0;j<TERRAIN_DEPTH;j++) { for( i=0;i<TERRAIN_WIDTH;i++) { /* vertices[count] = glm::vec3( ( (float(i)/(TERRAIN_WIDTH-1))*2.0f-1)*TERRAIN_HALF_WIDTH, (pData[count]/255.0f)*scale-half_scale, ( (float(j)/(TERRAIN_DEPTH-1))*2.0-1)*TERRAIN_HALF_DEPTH); */ vertices[count] = glm::vec3( (float(i)/(TERRAIN_WIDTH-1)), 0, (float(j)/(TERRAIN_DEPTH-1))); count++; } } for (i = 0; i < TERRAIN_DEPTH-1; i++) { for (j = 0; j < TERRAIN_WIDTH-1; j++) { int i0 = j+ i*TERRAIN_WIDTH; int i1 = i0+1; int i2 = i0+TERRAIN_WIDTH; int i3 = i2+1; *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } } GL_CHECK_ERRORS //setup vao and vbo stuff glGenVertexArrays(1, &vaoID); glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &vboIndicesID); glBindVertexArray(vaoID); glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID); glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS glEnableVertexAttribArray(shader["vVertex"]); glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0); GL_CHECK_ERRORS glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //load the heightmap texture using SOIL int texture_width = 0, texture_height = 0, format=0; GLubyte* pData = SOIL_load_image(filename.c_str(), &texture_width, &texture_height, &format, SOIL_LOAD_L); //setup OpenGL texture glGenTextures(1, &heightMapTextureID); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, heightMapTextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture_width, texture_height, 0, GL_RED, GL_UNSIGNED_BYTE, pData); free(pData); GL_CHECK_ERRORS glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); GL_CHECK_ERRORS cout<<"Initialization successfull"<<endl; }
//OpenGL initialization void OnInit() { //get the OBJ mesh path 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 //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 //load the 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 spherical harmonics shader sh_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/sh_shader.vert"); sh_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/sh_shader.frag"); //compile and link shader sh_shader.CreateAndLinkProgram(); sh_shader.Use(); //add attribute and uniform sh_shader.AddAttribute("vVertex"); sh_shader.AddAttribute("vNormal"); sh_shader.AddAttribute("vUV"); sh_shader.AddUniform("MV"); sh_shader.AddUniform("N"); sh_shader.AddUniform("P"); sh_shader.AddUniform("textureMap"); sh_shader.AddUniform("light_position"); sh_shader.AddUniform("useDefault"); sh_shader.AddUniform("diffuse_color"); //set values of constant uniforms as initialization glUniform1i(sh_shader("textureMap"), 0); sh_shader.UnUse(); GL_CHECK_ERRORS //load mesh rendering shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/sh_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("light_position"); shader.AddUniform("useDefault"); 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); 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(sh_shader["vVertex"]); glVertexAttribPointer(sh_shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for vertex normal glEnableVertexAttribArray(sh_shader["vNormal"]); glVertexAttribPointer(sh_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(sh_shader["vUV"]); glVertexAttribPointer(sh_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 //set spherical harmonics as the current shader pCurrentShader = &sh_shader; //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //set the clear colour to corn blue glClearColor(0.5,0.5,1,1); //get the light position lightPosOS.x = radius * cos(theta)*sin(phi); lightPosOS.y = radius * cos(phi); lightPosOS.z = radius * sin(theta)*sin(phi); //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 cout<<"Initialization successfull"<<endl; }
//display callback function void OnRender() { //clear the colour and depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //set the viewing transformation glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist)); glm::mat4 Rx = glm::rotate(T, rX, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 MV = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f)); //bind the mesh vertex array object glBindVertexArray(vaoID); { //bind the current shader pCurrentShader->Use(); //pass the shader uniforms glUniformMatrix4fv((*pCurrentShader)("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv((*pCurrentShader)("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniformMatrix4fv((*pCurrentShader)("P"), 1, GL_FALSE, glm::value_ptr(P)); glUniform3fv((*pCurrentShader)("light_position"),1, &(lightPosOS.x)); //loop through all materials for(size_t i=0;i<materials.size();i++) { Material* pMat = materials[i]; //if material texture filename is not empty if(pMat->map_Kd !="") { glUniform1f((*pCurrentShader)("useDefault"), 0.0); //get the currently bound texture and check if the current texture ID //is not equal, if so bind the new texture GLint whichID[1]; glGetIntegerv(GL_TEXTURE_BINDING_2D, whichID); if(whichID[0] != textures[i]) glBindTexture(GL_TEXTURE_2D, textures[i]); } else //otherwise we have no texture, we use a defaul colour glUniform1f((*pCurrentShader)("useDefault"), 1.0); //if we have a single material, we render the whole mesh in a single call if(materials.size()==1) glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0); else //otherwise we render the submesh glDrawElements(GL_TRIANGLES, pMat->count, GL_UNSIGNED_SHORT, (const GLvoid*)(&indices[pMat->offset])); } //unbind the current shader pCurrentShader->UnUse(); } //draw the light gizmo glBindVertexArray(lightVAOID); { //set the modelling transform for the light crosshair gizmo glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS); //bind the shader flatShader.Use(); //set shader uniforms and draw lines glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T)); glDrawArrays(GL_LINES, 0, 6); //unbind the shader flatShader.UnUse(); } //swap front and back buffers to show the rendered result glutSwapBuffers(); }
//OpenGL initialization function void OnInit() { GL_CHECK_ERRORS //create a uniform grid of size 20x20 in XZ plane grid = new CGrid(20,20); GL_CHECK_ERRORS //create a new TetrahedraMarcher instance marcher = new TetrahedraMarcher(); //set the volume dataset dimensions marcher->SetVolumeDimensions(256,256,256); //load the volume dataset marcher->LoadVolume(volume_file); //set the isosurface value marcher->SetIsosurfaceValue(48); //set the number of sampling voxels marcher->SetNumSamplingVoxels(128,128,128); //begin tetrahedra marching marcher->MarchVolume(); //setup the volume marcher vertex array object and vertex buffer object glGenVertexArrays(1, &volumeMarcherVAO); glGenBuffers(1, &volumeMarcherVBO); glBindVertexArray(volumeMarcherVAO); glBindBuffer (GL_ARRAY_BUFFER, volumeMarcherVBO); //pass the obtained vertices from the tetrahedra marcher and pass to the //buffer object memory glBufferData (GL_ARRAY_BUFFER, marcher->GetTotalVertices()*sizeof(Vertex), marcher->GetVertexPointer(), GL_STATIC_DRAW); //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); //enable vertex attribute array for normals glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),(const GLvoid*)offsetof(Vertex, normal)); GL_CHECK_ERRORS //load the shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/marcher.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/marcher.frag"); //compile and link the shader program shader.CreateAndLinkProgram(); shader.Use(); //add attribute and uniform shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddUniform("MVP"); shader.UnUse(); GL_CHECK_ERRORS //set the background colour glClearColor(bg.r, bg.g, bg.b, bg.a); //enable depth test and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); cout<<"Initialization successfull"<<endl; }
//display callback function void OnRender() { GL_CHECK_ERRORS //camera transformation glm::mat4 Tr = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist)); glm::mat4 Rx = glm::rotate(Tr, rX, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 MV = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f)); //clear colour and depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //get the combined modelview projection matrix glm::mat4 MVP = P*MV; //if we want to use depth peeling if(bShowDepthPeeling) { //bind the colour blending FBO glBindFramebuffer(GL_FRAMEBUFFER, colorBlenderFBOID); //set the first colour attachment as the draw buffer glDrawBuffer(GL_COLOR_ATTACHMENT0); //clear the colour and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // 1. In the first pass, we render normally with depth test enabled to get the nearest surface glEnable(GL_DEPTH_TEST); DrawScene(MVP, cubeShader); // 2. Depth peeling + blending pass int numLayers = (NUM_PASSES - 1) * 2; //for each pass for (int layer = 1; bUseOQ || layer < numLayers; layer++) { int currId = layer % 2; int prevId = 1 - currId; //bind the current FBO glBindFramebuffer(GL_FRAMEBUFFER, fbo[currId]); //set the first colour attachment as draw buffer glDrawBuffer(GL_COLOR_ATTACHMENT0); //set clear colour to black glClearColor(0, 0, 0, 0); //clear the colour and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //disbale blending and depth testing glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); //if we want to use occlusion query, we initiate it if (bUseOQ) { glBeginQuery(GL_SAMPLES_PASSED_ARB, queryId); } GL_CHECK_ERRORS //bind the depth texture from the previous step glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[prevId]); //render scene with the front to back peeling shader DrawScene(MVP, frontPeelShader); //if we initiated the occlusion query, we end it if (bUseOQ) { glEndQuery(GL_SAMPLES_PASSED_ARB); } GL_CHECK_ERRORS //bind the colour blender FBO glBindFramebuffer(GL_FRAMEBUFFER, colorBlenderFBOID); //render to its first colour attachment glDrawBuffer(GL_COLOR_ATTACHMENT0); //enable blending but disable depth testing glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); //change the blending equation to add glBlendEquation(GL_FUNC_ADD); //use separate blending function glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); //bind the result from the previous iteration as texture glBindTexture(GL_TEXTURE_RECTANGLE, texID[currId]); //bind the blend shader and then draw a fullscreen quad blendShader.Use(); DrawFullScreenQuad(); blendShader.UnUse(); //disable blending glDisable(GL_BLEND); GL_CHECK_ERRORS //if we initiated the occlusion query, we get the query result //that is the total number of samples if (bUseOQ) { GLuint sample_count; glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, &sample_count); if (sample_count == 0) { break; } } } GL_CHECK_ERRORS // 3. Final render pass //remove the FBO glBindFramebuffer(GL_FRAMEBUFFER, 0); //restore the default back buffer glDrawBuffer(GL_BACK_LEFT); //disable depth testing and blending glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); //bind the colour blender texture glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID); //bind the final shader finalShader.Use(); //set shader uniforms glUniform4fv(finalShader("vBackgroundColor"), 1, &bg.x); //draw full screen quad DrawFullScreenQuad(); finalShader.UnUse(); } else {
//OpenGL initialization function void OnInit() { GL_CHECK_ERRORS //initialize FBO initFBO(); //generate hardwre query glGenQueries(1, &queryId); //create a uniform grid of size 20x20 in XZ plane grid = new CGrid(20,20); GL_CHECK_ERRORS //generate the 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); //generate quad indices GLushort quadIndices[]={ 0,1,2,0,2,3}; //generate 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 buffer object memory glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0); //pass the quad indices to the element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW); //setup unit cube vertex array and vertex buffer objects glGenVertexArrays(1, &cubeVAOID); glGenBuffers(1, &cubeVBOID); glGenBuffers(1, &cubeIndicesID); //unit cube vertices glm::vec3 vertices[8]={ glm::vec3(-0.5f,-0.5f,-0.5f), glm::vec3( 0.5f,-0.5f,-0.5f), glm::vec3( 0.5f, 0.5f,-0.5f), glm::vec3(-0.5f, 0.5f,-0.5f), glm::vec3(-0.5f,-0.5f, 0.5f), glm::vec3( 0.5f,-0.5f, 0.5f), glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3(-0.5f, 0.5f, 0.5f)}; //unit cube indices GLushort cubeIndices[36]={0,5,4, 5,0,1, 3,7,6, 3,6,2, 7,4,6, 6,4,5, 2,1,3, 3,1,0, 3,0,7, 7,0,4, 6,5,2, 2,5,1}; glBindVertexArray(cubeVAOID); glBindBuffer (GL_ARRAY_BUFFER, cubeVBOID); //pass cube vertices to buffer object memory glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &(vertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attributre array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0,0); //pass cube indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesID); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), &cubeIndices[0], GL_STATIC_DRAW); glBindVertexArray(0); //Load the cube shader cubeShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/cube_shader.vert"); cubeShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/cube_shader.frag"); //compile and link the shader cubeShader.CreateAndLinkProgram(); cubeShader.Use(); //add attributes and uniforms cubeShader.AddAttribute("vVertex"); cubeShader.AddUniform("MVP"); cubeShader.AddUniform("vColor"); cubeShader.UnUse(); //Load the front to back peeling shader frontPeelShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/front_peel.vert"); frontPeelShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/front_peel.frag"); //compile and link the shader frontPeelShader.CreateAndLinkProgram(); frontPeelShader.Use(); //add attributes and uniforms frontPeelShader.AddAttribute("vVertex"); frontPeelShader.AddUniform("MVP"); frontPeelShader.AddUniform("vColor"); frontPeelShader.AddUniform("depthTexture"); //pass constant uniforms at initialization glUniform1i(frontPeelShader("depthTexture"), 0); frontPeelShader.UnUse(); //Load the blending shader blendShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/blend.vert"); blendShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/blend.frag"); //compile and link the shader blendShader.CreateAndLinkProgram(); blendShader.Use(); //add attributes and uniforms blendShader.AddAttribute("vVertex"); blendShader.AddUniform("tempTexture"); //pass constant uniforms at initialization glUniform1i(blendShader("tempTexture"), 0); blendShader.UnUse(); //Load the final shader finalShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/blend.vert"); finalShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/final.frag"); //compile and link the shader finalShader.CreateAndLinkProgram(); finalShader.Use(); //add attributes and uniforms finalShader.AddAttribute("vVertex"); finalShader.AddUniform("colorTexture"); finalShader.AddUniform("vBackgroundColor"); //pass constant uniforms at initialization glUniform1i(finalShader("colorTexture"), 0); finalShader.UnUse(); cout<<"Initialization successfull"<<endl; }
//display function void OnRender() { //clear the color and depth buffers glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //setup the camera transform glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(-center.x, -center.y, -center.z+dist)); glm::mat4 Rx = glm::rotate(T, rX, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 MV = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f)); //bind the mesh vertex array object glBindVertexArray(vaoID); { //bind the mesh's shader shader.Use(); //pass the shader uniforms glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniformMatrix4fv(shader("P"), 1, GL_FALSE, glm::value_ptr(P)); glUniform3fv(shader("light_position"),1, &(lightPosOS.x)); //for all submeshes for(size_t i=0;i<submeshes.size();i++) { //if the material name is not empty if(strlen(submeshes[i].materialName)>0) { //get the OpenGL texture id from the material map using the material name GLuint id = materialMap[material2ImageMap[submeshes[i].materialName]]; GLint whichID[1]; glGetIntegerv(GL_TEXTURE_BINDING_2D, whichID); //if the currently bound texture id is not the same is the current texture id //if so bind the current texture if(whichID[0] != id) glBindTexture(GL_TEXTURE_2D, id); //let the shader know that we have a texture so no default colour needs to be used glUniform1f(shader("useDefault"), 0.0); } else { //there is no texture in submesh, use a default colour glUniform1f(shader("useDefault"), 1.0); } //draw the triangles using the submesh indices glDrawElements(GL_TRIANGLES, submeshes[i].indices.size(), GL_UNSIGNED_INT, &submeshes[i].indices[0]); } //end for //unbind shader shader.UnUse(); } //bind the light vertex array object to show the light crosshair gizmo glBindVertexArray(lightVAOID); { //get the modeling transform of the light gizmo glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS); //set the shader of the light crosshair gizmo flatShader.Use(); //pass uniforms to the shader and render the crosshair gizmo as lines glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T)); glDrawArrays(GL_LINES, 0, 6); //unbind the shader flatShader.UnUse(); } //swap the back buffer and front buffer to display the result on screen glutSwapBuffers(); }
/* ---- Sonnensystem wird gezeichnet ----- */ void RenderScene(void) { GLUquadricObj* pObj; /* ---- Drehwinkel ---- */ static float fMoonRot = 0.0f; static float fEarthRot = 0.0f; static float fMercuryRot = 0.0f; static float fVenusRot = 0.0f; static float fMarsRot = 0.0f; static float fJupiterRot = 0.0f; static float fSaturnRot = 0.0f; static float fUranusRot = 0.0f; static float fNeptuneRot = 0.0f; static float fPlutoRot = 0.0f; static float fSaturnRingRot = 0.0f; // Löscht das Window mit der momentanten "Clearing-Color" glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Matrix-Zustand speichern glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Bewegungssteuerung des Spaceship aus Sicht des Spaceship gluLookAt(x, 1.0f, z, // Gibt die Position des Betrachters an x + lx, 1.0f, z + lz, // Gibt die Position des Refernenzpunktes an, auf den "geblickt" wird 0.0f, 1.0f, 0.0f); // Gibt die Richtung des Vektors an, der nach oben zeigt // Verschiebt die Szene auf Basis der Sonnenposition glTranslatef(fSunX, fSunY, fSunZ); #pragma region sun /* ----- Sonne ----- */ glDisable(GL_LIGHTING); // Licht ausschalten // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Sonnen-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, sunTexture); // Rotation der Sonne glRotatef(fSunRotX, 1.0f, 0.0f, 0.0f); // Sonne rotiert um x-Achse glRotatef(fSunRotY, 0.0f, 1.0f, 0.0f); // Sonne rotiert um y-Achse glRotatef(fSunRotZ, 0.0f, 0.0f, 1.0f); // Sonne rotiert um z-Achse gluSphere(pObj, 172.8f, 30, 17); // Sonnen-Kugel zeichnen (Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); // quadObject freigeben gluDeleteQuadric(pObj); glEnable(GL_LIGHTING); // Licht einschalten // Lighting-Position auf die Sonnen-Position setzen glLightfv(GL_LIGHT0, GL_POSITION, lightPos); #pragma endregion #pragma region skybox /* ----- Weltraum-Himmel ----- */ // Speichert die aktuelle Matrix glPushMatrix(); // Matrix wird nun transformiert glPushAttrib(GL_ENABLE_BIT); glEnable(GL_TEXTURE_2D); glColor4f(1, 1, 1, 1); GLfloat val = 5000.0f; // Größe der skybox // Texturen für das fordere Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(val, -val, val); glTexCoord2f(2, 0); glVertex3f(-val,-val, val); glTexCoord2f(2, 2); glVertex3f(-val, val, val); glTexCoord2f(0, 2); glVertex3f(val, val, val); glEnd(); // Texturen für das linke Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(val, -val, -val); glTexCoord2f(2, 0); glVertex3f(val, -val, val); glTexCoord2f(2, 2); glVertex3f(val, val, val); glTexCoord2f(0, 2); glVertex3f(val, val, -val); glEnd(); // Texturen für das hintere Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-val, -val, -val); glTexCoord2f(2, 0); glVertex3f(val, -val, -val); glTexCoord2f(2, 2); glVertex3f(val, val, -val); glTexCoord2f(0, 2); glVertex3f(-val, val, -val); glEnd(); // Texturen für das rechte Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-val, val, -val); glTexCoord2f(2, 0); glVertex3f(-val, val, val); glTexCoord2f(2, 2); glVertex3f(-val, -val, val); glTexCoord2f(0, 2); glVertex3f(-val, -val, -val); glEnd(); // Texturen für das obere Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(val, val, -val); glTexCoord2f(2, 0); glVertex3f(val, val, val); glTexCoord2f(2, 2); glVertex3f(-val, val, val); glTexCoord2f(0, 2); glVertex3f(-val, val, -val); glEnd(); // Texturen für das untere Quadrat glBindTexture(GL_TEXTURE_2D, starsTexture); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-val, -val, -val); glTexCoord2f(2, 0); glVertex3f(-val, -val, val); glTexCoord2f(2, 2); glVertex3f(val, -val, val); glTexCoord2f(0, 2); glVertex3f(val, -val, -val); glEnd(); glPopAttrib(); glPopMatrix(); #pragma endregion #pragma region mercury /* ----- Merkur ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Merkur-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mercuryTexture); // Rotationskoordinaten für Merkur glRotatef(fMercuryRot, 1.0f, 2.0f, 0.0f); // Merkur zeichnen glTranslatef(200.0f, -15.0f, 0.0f); // Merkur von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fMercuryRot * 3, 0.0f, 0.0f, 1.0f); // Merkur-Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 6.4f, 30, 17); // Merkur - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Merkur (Rotationsgeschwindigkeit um die Sonne) fMercuryRot += 20.0f; // Rotation zurücksetzen bei 360 Grad if (fMercuryRot >= 360.0f) fMercuryRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region venus /* ----- Venus ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Venus-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, venusTexture); // Rotationskoordinaten für Venus glRotatef(fVenusRot, 0.0f, 1.0f, 0.0f); // Venus zeichnen glTranslatef(350.0f, 0.0f, 0.0f); // Venus von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fVenusRot * 3, 0.0f, 0.0f, 1.0f); // Venus-Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 16.0f, 30, 17); // Venus - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Venus (Rotationsgeschwindigkeit um die Sonne) fVenusRot += 10.0f; // Rotation zurücksetzen bei 360 Grad if (fVenusRot >= 360.0f) fVenusRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region mars /* ----- Mars ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Mars-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, marsTexture); // Rotationskoordinaten für Mars glRotatef(fMarsRot, 0.0f, 1.0f, 0.3f); // Mars zeichnen glTranslatef(700.0f, 0.0f, 0.0f); // Mars von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fMarsRot * 3, 0.0f, 0.0f, 1.0f); // Mars - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 8.0f, 30, 17); // Mars - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Mars (Rotationsgeschwindigkeit um die Sonne) fMarsRot += 4.0f; // Rotation zurücksetzen bei 360 Grad if (fMarsRot >= 360.0f) fMarsRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region jupiter /* ----- Jupiter ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Jupiter-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, jupiterTexture); //sets it to jupiter's texture // Rotationskoordinaten für Jupiter glRotatef(fJupiterRot, 0.0f, 1.0f, -0.3f); // Jupiter zeichnen glTranslatef(1300.0f, 0.0f, 0.0f); // Jupiter von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fJupiterRot * 3, 0.0f, 0.0f, 1.0f); // Jupiter - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 88.0f, 30, 17); // Jupiter - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Jupiter (Rotationsgeschwindigkeit um die Sonne) fJupiterRot += 2.0f; // Rotation zurücksetzen bei 360 Grad if (fJupiterRot >= 360.0f) fJupiterRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region saturn /* ----- Saturn ----- */ glPushMatrix(); //saves the view matrix // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Saturn-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, saturnTexture); //sets it to saturn's texture // Rotationskoordinaten für Saturn glRotatef(fSaturnRot, 0.0f, 0.8f, -0.2f); // Saturn zeichnen glTranslatef(2375.0f, 0.0f, 0.0f); // Saturn von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fSaturnRot * 3, 0.0f, 0.0f, 1.0f); // Saturn - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 72.0f, 30, 17); // Saturn - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Saturn (Rotationsgeschwindigkeit um die Sonne) fSaturnRot += 1.5f; // Rotation zurücksetzen bei 360 Grad if (fSaturnRot >= 360.0f) fSaturnRot = 0.0f; #pragma endregion #pragma region saturnrings /* ----- Saturnringe ----- */ // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricNormals(pObj, GLU_SMOOTH); gluQuadricTexture(pObj, GL_TRUE); // Saturnring-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, saturnRingsTexture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Rotationskoordinaten für Saturnringe glRotatef(fSaturnRingRot, 0.0f, 0.0f, 1.0f); glRotatef(270.0f, 1.0f, 0.0f, 0.0f); glRotatef(-90.0, 1.0, 0.0, 0.0); glScalef(1, 1, 0.02f); glRotatef(fSaturnRingRot * 3, 0.0f, 0.0f, 1.0f); gluSphere(pObj, 72.0f * 2, 48, 48); // Saturnringe zeichnen // neue Rotationsposition vom Saturnring fSaturnRingRot += 1.0; // Rotation zurücksetzen bei 360 Grad if (fSaturnRingRot >= 360.0f) fSaturnRingRot = 0.0f; glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); glPopMatrix(); #pragma endregion #pragma region uranus /* ----- Uranus ------ */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Uranus-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, uranusTexture); //sets texture to uranus' texture // Rotationskoordinaten für Uranus glRotatef(fUranusRot, 0.0f, 0.8f, 0.2f); // Uranus zeichnen glTranslatef(3167.0f, 0.0f, 0.0f); // Uranus von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fUranusRot * 3, 0.0f, 0.0f, 1.0f); // Uranus - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 32.0f, 30, 17); // Uranus - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Uranus (Rotationsgeschwindigkeit um die Sonne) fUranusRot += 1.0f; // Rotation zurücksetzen bei 360 Grad if (fUranusRot >= 360.0f) fUranusRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region neptune /* ----- Neptun ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Neptun-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, neptuneTexture); //sets it to neptune's texture // Rotationskoordinaten für Neptun glRotatef(fNeptuneRot, 0.0f, 0.8f, 0.2f); // Neptun zeichnen glTranslatef(4166.0f, 0.0f, 0.0f); // Neptun von der Sonne wegverschieben glRotatef(300.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fNeptuneRot * 3, 0.0f, 0.0f, 1.0f); // Neptun - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 32.0f, 30, 17); // Neptun - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Neptun (Rotationsgeschwindigkeit um die Sonne) fNeptuneRot += 0.6f; // Rotation zurücksetzen bei 360 Grad if (fNeptuneRot >= 360.0f) fNeptuneRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region pluto /* ----- Pluto ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Pluto-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, plutoTexture); //sets it to plutos texture // Rotationskoordinaten für Pluto glRotatef(fPlutoRot, 0.0f, 0.8f, 0.2f); // Pluto zeichnen glTranslatef(5000.0f, 0.0f, 0.0f); // Pluto von der Sonne wegverschieben glRotatef(300.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fPlutoRot * 3, 0.0f, 0.0f, 1.0f); // Pluto - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 3.2f, 30, 17); // Pluto - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); // neue Rotationsposition von Pluto (Rotationsgeschwindigkeit um die Sonne) fPlutoRot += 0.2f; // Rotation zurücksetzen bei 360 Grad if (fPlutoRot >= 360.0f) fPlutoRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region earth /* ----- Erde ----- */ glPushMatrix(); // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Erden-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, earthTexture); // Rotationskoordinaten für Erde (Rotation um die Sonne) glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f); // Erde zeichnen glTranslatef(500.0f, 0.0f, 0.0f); // Erde von der Sonne wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fEarthRot * 3, 0.0f, 0.0f, 1.0f); // Erde - Rotation um sich selber - simuliert Eigenrotation gluSphere(pObj, 16.0f, 30, 17); // Erde - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); #pragma endregion #pragma region earthMoon /* ----- Mond ----- */ // quadObject erstellen und Texturkoordinaten dafür spezifizieren pObj = gluNewQuadric(); gluQuadricTexture(pObj, GL_TRUE); // Mond-Textur setzen glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, moonTexture); glRotatef(fMoonRot, 0.0f, 1.0f, 0.0f); // Mond-Rotation um die Erde glTranslatef(25.0f, 0.0f, 0.0f); // Mond von der Erde wegverschieben glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur glRotatef(fMoonRot * 3, 0.0f, 0.0f, 1.0f); // Mond - Rotation um sich selber - simuliert Eigenrotation // neue Rotationsposition vom Mond fMoonRot = 2.4f; // Rotation zurücksetzen bei 360 Grad if (fMoonRot >= 360.0f) fMoonRot = 0.0f; // Mond zeichnen gluSphere(pObj, 4.3f, 30, 17); // Mond - Kugel zeichnen(Object, Radius, Slices, Stack) glDisable(GL_TEXTURE_2D); gluDeleteQuadric(pObj); glPopMatrix(); // neue Rotationsposition von der Erde fEarthRot += 5.0f; // Rotation zurücksetzen bei 360 Grad if (fEarthRot >= 360.0f) fEarthRot = 0.0f; glPopMatrix(); #pragma endregion #pragma region DreiD-Model GL_CHECK_ERRORS // Matrizen glm::mat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -100.0f, -300)); // Position des Raumschiffes in der Skybox glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f)); glm::mat4 MV = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f)); glm::mat4 MVP = P*MV; glBindVertexArray(vaoID); shader.Use(); glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); glDrawElements(GL_TRIANGLES, object.polygons_qty * 3, GL_UNSIGNED_SHORT, 0); shader.UnUse(); glBindVertexArray(0); #pragma endregion // Sonnensystem anzeigen glutSwapBuffers(); }
//idle callback which is called when there is no other processing to do void OnIdle() { //get the current timer value QueryPerformanceCounter(¤t); dt = (double)(current.QuadPart - last.QuadPart) / (double)freq.QuadPart; last = current; static double t = 0; //increment time t+=dt; //get the current mesh animation and store the frame rate //if the current time is greater than the framerate, we move //to the next frame NVSHARE::MeshAnimation* pAnim = &animations[0]; float fps = pAnim->GetFrameCount() / pAnim->GetDuration(); if( t > 1.0f/fps) { currentFrame++; t=0; } //if looped playback is on, we do a modulus operation of the current frame with //the total number of frames if(bLoop) { currentFrame = currentFrame%pAnim->mFrameCount; } else { //otherwise, we just restrict the current frame to be in range currentFrame = std::fmax(-1, std::fmin(currentFrame, pAnim->mFrameCount-1)); } //if the current frame is -1, means we are in bind pose //just use the bind pose matrix and the bones absolute //transforms to get the aniamted transform if(currentFrame == -1) { for(size_t i=0;i<skeleton.size();i++) { skeleton[i].comb = bindPose[i]; animatedXform[i] = skeleton[i].comb*invBindPose[i]; } } else { //otherwise, we loop through all tracks in the current animation //and determine the pose. for(int j=0;j<pAnim->mTrackCount;j++) { NVSHARE::MeshAnimTrack* pTrack = pAnim->mTracks[j]; NVSHARE::MeshAnimPose* pPose = pTrack->GetPose(currentFrame); //using the pose, we estimate the local transform of the current bone //in the given animation track //first get positions skeleton[j].position.x = pPose->mPos[0]; skeleton[j].position.y = pPose->mPos[1]; skeleton[j].position.z = pPose->mPos[2]; //then orientation glm::quat q; q.x = pPose->mQuat[0]; q.y = pPose->mQuat[1]; q.z = pPose->mQuat[2]; q.w = pPose->mQuat[3]; //then scale skeleton[j].scale = glm::vec3(pPose->mScale[0], pPose->mScale[1], pPose->mScale[2]); //handle the Zup case if(!bYup) { skeleton[j].position.y = pPose->mPos[2]; skeleton[j].position.z = -pPose->mPos[1]; q.y = pPose->mQuat[2]; q.z = -pPose->mQuat[1]; skeleton[j].scale.y = pPose->mScale[2]; skeleton[j].scale.z = -pPose->mScale[1]; } skeleton[j].orientation = q; //use the stored scale, orientation and translation to obtain the //local transform of bone glm::mat4 S = glm::scale(glm::mat4(1),skeleton[j].scale); glm::mat4 R = glm::toMat4(q); glm::mat4 T = glm::translate(glm::mat4(1), skeleton[j].position); skeleton[j].xform = T*R*S; //get the absolute transform of the bone Bone& b = skeleton[j]; if(b.parent==-1) b.comb = b.xform; else b.comb = skeleton[b.parent].comb * b.xform; //multiply the absolute transform of the current bone with //the inverse bind pose of the bone to get the new animated //transform animatedXform[j] = b.comb * invBindPose[j]; //in case of dual quaternion, extract the position and orientation and then use //QuatTrans2UDQ function to obtain a dual quaternion for the given animatedXform glm::vec3 t = glm::vec3( animatedXform[j][3][0], animatedXform[j][3][1], animatedXform[j][3][2]); dualQuaternions[j].QuatTrans2UDQ(glm::toQuat(animatedXform[j]), t); }//for all animation tracks } //else //pass the new dual quaternions to the shader by updating the uniform shader.Use(); //since we have a dual quaternion, we pass it as 2 vec4 variables //hence the multiplication by 2 glUniform4fv(shader("Bones"), skeleton.size()*2, &(dualQuaternions[0].ordinary.x)); shader.UnUse(); //call the display callback glutPostRedisplay(); }
//OpenGL initialization void OnInit() { //load the per-vertex lighting shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/perVertexLighting.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/perVertexLighting.frag"); //compile and link shader shader.CreateAndLinkProgram(); shader.Use(); //add attributes and uniforms shader.AddAttribute("vVertex"); shader.AddAttribute("vNormal"); shader.AddUniform("MVP"); shader.AddUniform("MV"); shader.AddUniform("N"); shader.AddUniform("light_position"); shader.AddUniform("diffuse_color"); shader.AddUniform("specular_color"); shader.AddUniform("shininess"); shader.UnUse(); GL_CHECK_ERRORS //cerate sphere geometry CreateSphere(1.0f,10,10, vertices, indices); //setup sphere vao and vbo stuff glGenVertexArrays(1, &sphereVAOID); glGenBuffers(1, &sphereVerticesVBO); glGenBuffers(1, &sphereIndicesVBO); glBindVertexArray(sphereVAOID); glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO); //pass vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribute array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribute array for normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal))); GL_CHECK_ERRORS //pass sphere indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO); glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW); //store the total number of sphere triangles totalSphereTriangles = indices.size(); //clear the vertices and indices vectors as we will reuse them //for cubes vertices.clear(); indices.clear(); //setup cube geometry CreateCube(1,vertices, indices); //setup cube vao and vbo stuff glGenVertexArrays(1, &cubeVAOID); glGenBuffers(1, &cubeVerticesVBO); glGenBuffers(1, &cubeIndicesVBO); glBindVertexArray(cubeVAOID); glBindBuffer (GL_ARRAY_BUFFER, cubeVerticesVBO); //pass vertices to the buffer object glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attribut array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0); GL_CHECK_ERRORS //enable vertex attribut array for normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal))); GL_CHECK_ERRORS //pass cube indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO); glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW); GL_CHECK_ERRORS //enable depth testing and culling glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //create a grid of 10x10 size in XZ plane grid = new CGrid(); GL_CHECK_ERRORS cout<<"Initialization successfull"<<endl; }
//OpenGL initialization void OnInit() { GL_CHECK_ERRORS //create a uniform grid of size 20x20 in XZ plane grid = new CGrid(20,20); GL_CHECK_ERRORS //Load the raycasting shader shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/raycaster.vert"); shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/raycaster.frag"); //compile and link the shader shader.CreateAndLinkProgram(); shader.Use(); //add attributes and uniforms shader.AddAttribute("vVertex"); shader.AddUniform("MVP"); shader.AddUniform("volume"); shader.AddUniform("camPos"); shader.AddUniform("step_size"); //pass constant uniforms at initialization glUniform3f(shader("step_size"), 1.0f/XDIM, 1.0f/YDIM, 1.0f/ZDIM); glUniform1i(shader("volume"),0); shader.UnUse(); GL_CHECK_ERRORS //load volume data if(LoadVolume()) { std::cout<<"Volume data loaded successfully."<<std::endl; } else { std::cout<<"Cannot load volume data."<<std::endl; exit(EXIT_FAILURE); } //set background colour glClearColor(bg.r, bg.g, bg.b, bg.a); //setup unit cube vertex array and vertex buffer objects glGenVertexArrays(1, &cubeVAOID); glGenBuffers(1, &cubeVBOID); glGenBuffers(1, &cubeIndicesID); //unit cube vertices glm::vec3 vertices[8]={ glm::vec3(-0.5f,-0.5f,-0.5f), glm::vec3( 0.5f,-0.5f,-0.5f), glm::vec3( 0.5f, 0.5f,-0.5f), glm::vec3(-0.5f, 0.5f,-0.5f), glm::vec3(-0.5f,-0.5f, 0.5f), glm::vec3( 0.5f,-0.5f, 0.5f), glm::vec3( 0.5f, 0.5f, 0.5f), glm::vec3(-0.5f, 0.5f, 0.5f)}; //unit cube indices GLushort cubeIndices[36]={0,5,4, 5,0,1, 3,7,6, 3,6,2, 7,4,6, 6,4,5, 2,1,3, 3,1,0, 3,0,7, 7,0,4, 6,5,2, 2,5,1}; glBindVertexArray(cubeVAOID); glBindBuffer (GL_ARRAY_BUFFER, cubeVBOID); //pass cube vertices to buffer object memory glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &(vertices[0].x), GL_STATIC_DRAW); GL_CHECK_ERRORS //enable vertex attributre array for position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0,0); //pass indices to element array buffer glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesID); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), &cubeIndices[0], GL_STATIC_DRAW); glBindVertexArray(0); //enable depth test glEnable(GL_DEPTH_TEST); //set the over blending function glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); cout<<"Initialization successfull"<<endl; }
//scene rendering function void DrawScene(const glm::mat4& View, const glm::mat4& Proj ) { GL_CHECK_ERRORS //bind the current shader shader.Use(); //bind the cube vertex array object glBindVertexArray(cubeVAOID); //draw the 8 cubes first for(int i=0;i<8;i++) { //set the cube's transform float theta = (float)(i/8.0f*2*M_PI); glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(radius*cos(theta),0.5,radius*sin(theta))); glm::mat4 M = T; //Model matrix glm::mat4 MV = View*M; //ModelView matrix glm::mat4 MVP = Proj*MV; //combined ModelView Projection matrix //pass shader uniforms glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniform3fv(shader("diffuse_color"),1, &(colors[i].x)); glUniform3f(shader("specular_color"), 1.0f, 1.0f, 1.0f); glUniform1f(shader("shininess"), 100); glUniform3fv(shader("light_position"),1, &(lightPosOS.x)); //draw triangles glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); GL_CHECK_ERRORS } //bind the sphere vertex array object glBindVertexArray(sphereVAOID); //set the sphere's transform glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(0,1,0)); glm::mat4 M = T; glm::mat4 MV = View*M; glm::mat4 MVP = Proj*MV; //pass shader uniforms glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniform3f(shader("diffuse_color"), 0.9f, 0.9f, 1.0f); glUniform3f(shader("specular_color"), 1.0f, 1.0f, 1.0f); glUniform1f(shader("shininess"), 300); glUniform3fv(shader("light_position"),1, &(lightPosOS.x)); //draw triangles glDrawElements(GL_TRIANGLES, totalSphereTriangles, GL_UNSIGNED_SHORT, 0); //unbind shader shader.UnUse(); //unbind vertex array object glBindVertexArray(0); GL_CHECK_ERRORS //render the grid object grid->Render(glm::value_ptr(Proj*View)); }
//display callback function void OnRender() { //FPS calculation ++total_frames; float current = (float)glutGet(GLUT_ELAPSED_TIME); if((current-lastTime)>1000) { fps = 1000.0f*total_frames/(current-lastTime); std::cout<<"FPS: "<<fps<<std::endl; lastTime= current; total_frames = 0; } //clear colour and depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //set the camera transformation glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist)); glm::mat4 Rx = glm::rotate(T, rX, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 MV = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f)); //get the eye position and inverse of MVP matrix glm::mat4 invMV = glm::inverse(MV); glm::vec3 eyePos = glm::vec3(invMV[3][0],invMV[3][1],invMV[3][2]); glm::mat4 invMVP = glm::inverse(P*MV); //if raytracing is enabled if(bRaytrace) { //set the raytracing shader raytraceShader.Use(); //pass shader uniforms glUniform3fv(raytraceShader("eyePos"), 1, glm::value_ptr(eyePos)); glUniformMatrix4fv(raytraceShader("invMVP"), 1, GL_FALSE, glm::value_ptr(invMVP)); glUniform3fv(raytraceShader("light_position"),1, &(lightPosOS.x)); //draw a fullscreen quad DrawFullScreenQuad(); //unbind raytracing shader raytraceShader.UnUse(); } else { //do rasterization //bind the mesh vertex array object glBindVertexArray(vaoID); { //bind the mesh rendering shader shader.Use(); //set the shader uniforms glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV)); glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV)))); glUniformMatrix4fv(shader("P"), 1, GL_FALSE, glm::value_ptr(P)); glUniform3fv(shader("light_position"),1, &(lightPosOS.x)); //loop through all materials for(size_t i=0;i<materials.size();i++) { Material* pMat = materials[i]; //if material texture filename is not empty //dont use the default colour if(pMat->map_Kd !="") { glUniform1f(shader("useDefault"), 0.0); glUniform1i(shader("textureIndex"), i); } else //otherwise we have no texture, we use a default colour glUniform1f(shader("useDefault"), 1.0); //if we have a single material, we render the whole mesh in a single call if(materials.size()==1) glDrawElements(GL_TRIANGLES, indices.size() , GL_UNSIGNED_SHORT, 0); else //otherwise we render the submesh glDrawElements(GL_TRIANGLES, pMat->count, GL_UNSIGNED_SHORT, (const GLvoid*)(&indices[pMat->offset])); } //unbind the shader shader.UnUse(); } } //disable depth testing glDisable(GL_DEPTH_TEST); //draw the light gizmo, set the light vertexx array object glBindVertexArray(lightVAOID); { //set the modelling transform for the light crosshair gizmo glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS); //bind the shader flatShader.Use(); //set shader uniforms and draw lines glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T)); glDrawArrays(GL_LINES, 0, 6); //unbind the shader flatShader.UnUse(); } //enable depth test glEnable(GL_DEPTH_TEST); //swap front and back buffers to show the rendered result glutSwapBuffers(); }
//initialize OpenGL void InitGL() { //set the background colour to white glClearColor(1,1,1,1); //generate hardware query objects glGenQueries(1, &query); glGenQueries(1, &t_query); //setup texture size for shaders texture_size_x = numX+1; texture_size_y = numY+1; CHECK_GL_ERRORS //get initial time startTime = (float)glutGet(GLUT_ELAPSED_TIME); // get ticks per second QueryPerformanceFrequency(&frequency); // start timer QueryPerformanceCounter(&t1); //local variables size_t i=0, j=0, count=0; int l1=0, l2=0; int v = numY+1; int u = numX+1; printf("Total triangles: %3d\n",numX*numY*2); //resize the cloth indices, position, previous position and force vectors indices.resize( numX*numY*2*3); X.resize(total_points); X_last.resize(total_points); F.resize(total_points); //fill in positions for(int j=0;j<=numY;j++) { for(int i=0;i<=numX;i++) { X[count] = glm::vec4( ((float(i)/(u-1)) *2-1)* hsize, sizeX+1, ((float(j)/(v-1) )* sizeY),1); X_last[count] = X[count]; count++; } } //fill in indices GLushort* id=&indices[0]; for (int i = 0; i < numY; i++) { for (int j = 0; j < numX; j++) { int i0 = i * (numX+1) + j; int i1 = i0 + 1; int i2 = i0 + (numX+1); int i3 = i2 + 1; if ((j+i)%2) { *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } else { *id++ = i0; *id++ = i2; *id++ = i3; *id++ = i0; *id++ = i3; *id++ = i1; } } } //set the polygon rendering to render them as lines glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //enable back face culling glEnable(GL_CULL_FACE); glCullFace(GL_BACK); //set smooth line rendering glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //enable state to use the vertex shader to reset the particle size //by writing to gl_PointSize value glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); // Setup springs // Horizontal for (l1 = 0; l1 < v; l1++) // v for (l2 = 0; l2 < (u - 1); l2++) { AddSpring((l1 * u) + l2,(l1 * u) + l2 + 1,KsStruct,KdStruct); } // Vertical for (l1 = 0; l1 < (u); l1++) for (l2 = 0; l2 < (v - 1); l2++) { AddSpring((l2 * u) + l1,((l2 + 1) * u) + l1,KsStruct,KdStruct); } // Shearing Springs for (l1 = 0; l1 < (v - 1); l1++) for (l2 = 0; l2 < (u - 1); l2++) { AddSpring((l1 * u) + l2,((l1 + 1) * u) + l2 + 1,KsShear,KdShear); AddSpring(((l1 + 1) * u) + l2,(l1 * u) + l2 + 1,KsShear,KdShear); } // Bend Springs for (l1 = 0; l1 < (v); l1++) { for (l2 = 0; l2 < (u - 2); l2++) { AddSpring((l1 * u) + l2,(l1 * u) + l2 + 2,KsBend,KdBend); } AddSpring((l1 * u) + (u - 3),(l1 * u) + (u - 1),KsBend,KdBend); } for (l1 = 0; l1 < (u); l1++) { for (l2 = 0; l2 < (v - 2); l2++) { AddSpring((l2 * u) + l1,((l2 + 2) * u) + l1,KsBend,KdBend); } AddSpring(((v - 3) * u) + l1,((v - 1) * u) + l1,KsBend,KdBend); } //setup shader loading massSpringShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Spring.vert"); particleShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Basic.vert"); particleShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Basic.frag"); renderShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Passthrough.vert"); renderShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Passthrough.frag"); //compile and link mass spring shader massSpringShader.CreateAndLinkProgram(); massSpringShader.Use(); //add attributes and uniforms massSpringShader.AddAttribute("position_mass"); massSpringShader.AddAttribute("prev_position"); massSpringShader.AddUniform("tex_position_mass"); massSpringShader.AddUniform("tex_pre_position_mass"); massSpringShader.AddUniform("MVP"); massSpringShader.AddUniform("dt"); massSpringShader.AddUniform("gravity"); massSpringShader.AddUniform("ksStr"); massSpringShader.AddUniform("ksShr"); massSpringShader.AddUniform("ksBnd"); massSpringShader.AddUniform("kdStr"); massSpringShader.AddUniform("kdShr"); massSpringShader.AddUniform("kdBnd"); massSpringShader.AddUniform("DEFAULT_DAMPING"); massSpringShader.AddUniform("texsize_x"); massSpringShader.AddUniform("texsize_y"); massSpringShader.AddUniform("step"); massSpringShader.AddUniform("inv_cloth_size"); massSpringShader.AddUniform("ellipsoid_xform"); massSpringShader.AddUniform("inv_ellipsoid"); massSpringShader.AddUniform("ellipsoid"); massSpringShader.UnUse(); CHECK_GL_ERRORS //compile and link particle shader particleShader.CreateAndLinkProgram(); particleShader.Use(); //setup attributes and uniforms particleShader.AddAttribute("position_mass"); particleShader.AddUniform("pointSize"); particleShader.AddUniform("MV"); particleShader.AddUniform("MVP"); particleShader.AddUniform("vColor"); particleShader.AddUniform("selected_index"); //pass values to contant uniforms glUniform1f(particleShader("pointSize"), pointSize); glUniform4fv(particleShader("vColor"),1, vRed); particleShader.UnUse(); //compile and link render shader renderShader.CreateAndLinkProgram(); renderShader.Use(); //setup attributes and uniforms renderShader.AddAttribute("position_mass"); renderShader.AddUniform("MVP"); renderShader.AddUniform("vColor"); //pass values to constant uniforms glUniform4fv(renderShader("vColor"),1, vGray); renderShader.UnUse(); CHECK_GL_ERRORS //create vbo createVBO(); //collision ellipsoid ellipsoid = glm::translate(glm::mat4(1),glm::vec3(0,2,0)); ellipsoid = glm::rotate(ellipsoid, 45.0f ,glm::vec3(1,0,0)); ellipsoid = glm::scale(ellipsoid, glm::vec3(fRadius,fRadius,fRadius/2)); inverse_ellipsoid = glm::inverse(ellipsoid); //setup transform feedback attributes glGenTransformFeedbacks(1, &tfID); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID); //pass the vertex shader outputs for transform feedback const char* varying_names[]={"out_position_mass", "out_prev_position"}; glTransformFeedbackVaryings(massSpringShader.GetProgram(), 2, varying_names, GL_SEPARATE_ATTRIBS); //relink the massSpringShader program glLinkProgram(massSpringShader.GetProgram()); //set the mass spring shader and pass values to constant uniforms massSpringShader.Use(); glUniform1f(massSpringShader("dt"), timeStep); glUniform3fv(massSpringShader("gravity"),1,&gravity.x); glUniform1i(massSpringShader("tex_position_mass"), 0); glUniform1i(massSpringShader("tex_pre_position_mass"), 1); glUniform1i(massSpringShader("texsize_x"),texture_size_x); glUniform1i(massSpringShader("texsize_y"),texture_size_y); glUniformMatrix4fv(massSpringShader("ellipsoid_xform"), 1, GL_FALSE, glm::value_ptr(ellipsoid)); glUniformMatrix4fv(massSpringShader("inv_ellipsoid"), 1, GL_FALSE, glm::value_ptr(inverse_ellipsoid)); glUniform4f(massSpringShader("ellipsoid"),0, 0, 0, fRadius); glUniform2f(massSpringShader("inv_cloth_size"),float(sizeX)/numX,float(sizeY)/numY); glUniform2f(massSpringShader("step"),1.0f/(texture_size_x-1.0f),1.0f/(texture_size_y-1.0f)); glUniform1f(massSpringShader("ksStr"), KsStruct); glUniform1f(massSpringShader("ksShr"), KsShear); glUniform1f(massSpringShader("ksBnd"), KsBend); glUniform1f(massSpringShader("kdStr"), KdStruct/1000.0f); glUniform1f(massSpringShader("kdShr"), KdShear/1000.0f); glUniform1f(massSpringShader("kdBnd"), KdBend/1000.0f); glUniform1f(massSpringShader("DEFAULT_DAMPING"), DEFAULT_DAMPING); massSpringShader.UnUse(); //disable vsync wglSwapIntervalEXT(0); }