void RenderScene(Shader &shader) { // Floor glm::mat4 model; glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glBindVertexArray(planeVAO); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); // Cubes model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 1.0f, 1.5f)); model = glm::rotate(model, (GLfloat)glfwGetTime() * 5.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); //Change the texture glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, rockTexture); model = glm::mat4(); model = glm::translate(model, glm::vec3(3.5f, 0.0f, -1.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(0.5)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); }
void CArea::TAmbienceInstance::Render() { float fBoxSize = 10.0f; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xff00ff00); RenderCube(fx-fBoxSize, fy-fBoxSize, fz-fBoxSize, fx+fBoxSize, fy+fBoxSize, fz+fBoxSize); STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); RenderSphere(NULL, fx, fy, fz, float(dwRange) * fMaxVolumeAreaPercentage, D3DFILL_POINT); RenderSphere(NULL, fx, fy, fz, float(dwRange), D3DFILL_POINT); RenderCircle2d(fx, fy, fz, float(dwRange) * fMaxVolumeAreaPercentage); RenderCircle2d(fx, fy, fz, float(dwRange)); for (int i = 0; i < 4; ++i) { float fxAdd = cosf(float(i) * D3DX_PI/4.0f) * float(dwRange) / 2.0f; float fyAdd = sinf(float(i) * D3DX_PI/4.0f) * float(dwRange) / 2.0f; if (i%2) { fxAdd /= 2.0f; fyAdd /= 2.0f; } RenderLine2d(fx + fxAdd, fy + fyAdd, fx - fxAdd, fy - fyAdd, fz); } }
/*! Initialize the scene, reserve shaders, compile and cache program \param[in] None. \return None */ void Cube::Render() { glEnable( GL_DEPTH_TEST ); glUseProgram( program->ProgramID ); RenderCube(); }
//-------------------------------------------------------------------------------------- // Name: RenderBlurredScene() // Desc: //-------------------------------------------------------------------------------------- VOID CSample::RenderBlurredScene() { // Clear the backbuffer and depth-buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); RenderCube(); }
//xzhs void RenderCubes(Shader &shader) { // Cubes glm::mat4 model = glm::mat4(); model = glm::mat4(); model = glm::translate(model, glm::vec3(0.2f, 0.4f, 0.5f)); model = glm::rotate(model, (GLfloat)glfwGetTime() * 5.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(0.5f, 0.4f, -0.5)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(0.3f, 0.5f, 0.5f)); model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(0.5)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); }
void LocationEditor::RenderModeLandFlat() { Vector3 mousePos3D = g_app->m_userInput->GetMousePos3d(); Landscape *land = &g_app->m_location->m_landscape; // Highlight any flatten area under our mouse cursor LList<LandscapeFlattenArea *> *areas = &g_app->m_location->m_levelFile->m_landscape.m_flattenAreas; for (int i = 0; i < areas->Size(); ++i) { if (i == m_selectionId) continue; LandscapeFlattenArea *area = areas->GetData(i); float worldX = area->m_centre.x; float worldZ = area->m_centre.z; float sizeX = area->m_size; float sizeY = area->m_centre.y; float sizeZ = area->m_size; float x = area->m_centre.x; float y = area->m_centre.y; float z = area->m_centre.z; float s = area->m_size * 2.0; Vector3 centre(x, y, z); RenderCube(centre, s, y + 20, s, RGBAColour(128,255,128,99)); } if (m_selectionId != -1) { LandscapeDef *landscapeDef = &(g_app->m_location->m_levelFile->m_landscape); LandscapeFlattenArea *areaDef = g_app->m_location->m_levelFile->m_landscape.m_flattenAreas.GetData(m_selectionId); float x = areaDef->m_centre.x; float y = areaDef->m_centre.y; float z = areaDef->m_centre.z; float s = areaDef->m_size * 2.0; Vector3 centre(x, y, z); RenderCube(centre, s, y + 20, s, RGBAColour(128,255,128,255)); } CHECK_OPENGL_STATE(); }
void init() { // 深度测试 glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); icube = glGenLists(1); glNewList(icube, GL_COMPILE); RenderCube(); glEndList(); }
void RenderScene(Shader &shader) { // Floor glm::mat4 model; glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glBindVertexArray(planeVAO); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); // Cubes model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, 2.0)); model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(0.5)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); }
VOID Render(float timeDelta) { SetupMatrix() ; g_ModelViewCamera->OnFrameMove(); // Save render target g_pd3dDevice->GetRenderTarget(0, &g_pOldRenderTarget) ; g_pd3dDevice->SetRenderTarget(0, g_pRenderSurface) ; g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0 ); // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Without this line, the teapot won't show up, what's the inner stuff of SetTexture? g_pd3dDevice->SetTexture(0, NULL) ; // Disable lighting, since we didn't specify color for vertex g_pd3dDevice->SetRenderState( D3DRS_LIGHTING , FALSE ); g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME) ; D3DXMATRIX word ; D3DXMatrixTranslation(&word, 0.0f, 0.0f, 0.0f) ; static float totalTime = 0.0f ; totalTime += timeDelta * 2 ; D3DXMATRIX rot ; D3DXMatrixRotationY(&rot, totalTime) ; word *= rot ; g_pd3dDevice->SetTransform(D3DTS_WORLD, &word) ; g_pTeapotMesh->DrawSubset(0) ; // End the scene g_pd3dDevice->EndScene(); } // Restore the back buffer g_pd3dDevice->SetRenderTarget(0, g_pOldRenderTarget) ; RenderCube(timeDelta) ; // Present the back-buffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); }
void Scene::RenderScene(GLuint program) { // Room cube glm::mat4 model; model = glm::scale(model, glm::vec3(10.0)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); glDisable(GL_CULL_FACE); // Note that we disable culling here since we render 'inside' the cube instead of the usual 'outside' which throws off the normal culling methods. glUniform1i(glGetUniformLocation(program, "reverse_normals"), 1); // A small little hack to invert normals when drawing cube from the inside so lighting still works. RenderCube(); glUniform1i(glGetUniformLocation(program, "reverse_normals"), 0); // And of course disable it glEnable(GL_CULL_FACE); // Cubes model = glm::mat4(); model = glm::translate(model, glm::vec3(4.0f, -3.5f, 0.0)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 3.0f, 1.0)); model = glm::scale(model, glm::vec3(1.5)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-3.0f, -1.0f, 0.0)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.5f, 1.0f, 1.5)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.5f, 2.0f, -3.0)); model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(1.5)); glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, &model[0][0]); RenderCube(); }
void GameRenderer::RenderGrid() { const ezVec3 vCellSize = m_pGrid->GetWorldSpaceCellSize(); const ezVec3 vCellSize2 (vCellSize.x, 0.1f, vCellSize.z); for (ezUInt32 z = 0; z < m_pGrid->GetGridHeight(); ++z) { for (ezUInt32 x = 0; x < m_pGrid->GetGridWidth(); ++x) { const GameCellData& cd = m_pGrid->GetCell(ezVec2I32(x, z)); const ezUInt32 uiVisibility = CVarVisFogOfWar ? cd.m_uiVisibility : 255; if (uiVisibility == 0) { glColor3ub(20, 20, 20); RenderCube(m_pGrid->GetCellWorldSpaceOrigin(ezVec2I32(x, z)), vCellSize2, false); continue; } bool bColor = true; float fFade = 1.0f; if (uiVisibility <= 100) fFade = uiVisibility / 100.0f; fFade = ezMath::Max(fFade, 50.0f / 255.0f); if (CVarVisThreat && cd.m_iThreat > 0) { glColor3ub(255, 0, 220); RenderCube(m_pGrid->GetCellWorldSpaceOrigin(ezVec2I32(x, z)), vCellSize2, false, fFade); } //if (!cd.m_hUnit.IsInvalidated()) //{ // glColor3ub(0, 100, 0); // RenderCube(m_pGrid->GetCellWorldSpaceOrigin(ezVec2I32(x, z)), vCellSize2, false, fFade); //} //else { if (cd.m_iCellType == 1) RenderCube(m_pGrid->GetCellWorldSpaceOrigin(ezVec2I32(x, z)), vCellSize, true, fFade); else RenderCube(m_pGrid->GetCellWorldSpaceOrigin(ezVec2I32(x, z)), vCellSize2, true, fFade); } } } if (CVarVisNavmeshCells) { ezUInt8 uiGreen = 30; for (ezUInt32 ca = 0; ca < m_pNavmesh->GetNumConvexAreas(); ++ca) { const ezRectU32& r = m_pNavmesh->GetConvexArea(ca).m_Rect; const ezVec2I32 ll(r.x, r.y); const ezVec2I32 tr(r.x + r.width, r.y + r.height); const ezVec3 vLL = m_pGrid->GetCellWorldSpaceOrigin(ll); const ezVec3 vTR = m_pGrid->GetCellWorldSpaceOrigin(tr); glColor3ub(uiGreen, 20, 20); uiGreen += 30; ezVec3 vHalfWidth = (vTR - vLL); vHalfWidth.y = 0.5f; RenderCube(vLL + ezVec3(0.1f, 0, 0.1f), vHalfWidth - ezVec3(0.2f, 0, 0.2f), false); } } if (CVarVisNavmeshEdges) { ezUInt8 uiGreen = 30; for (ezUInt32 ca = 0; ca < m_pNavmesh->GetNumAreaEdges(); ++ca) { const ezGridNavmesh::AreaEdge& r = m_pNavmesh->GetAreaEdge(ca); const ezVec2I32 ll(r.m_EdgeRect.x, r.m_EdgeRect.y); const ezVec2I32 tr(r.m_EdgeRect.x + r.m_EdgeRect.width, r.m_EdgeRect.y + r.m_EdgeRect.height); const ezVec3 vLL = m_pGrid->GetCellWorldSpaceOrigin(ll); const ezVec3 vTR = m_pGrid->GetCellWorldSpaceOrigin(tr); glColor3ub(20, 20, uiGreen); uiGreen += 30; ezVec3 vHalfWidth = (vTR - vLL); vHalfWidth.y = 0.5f; RenderCube(vLL + ezVec3(0.1f, 0, 0.1f), vHalfWidth - ezVec3(0.2f, 0, 0.2f), false); } } }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); // Define the viewport dimensions glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); // Setup and compile our shaders Shader shaderGeometryPass("g_buffer.vs", "g_buffer.frag"); Shader shaderLightingPass("deferred_shading.vs", "deferred_shading.frag"); Shader shaderLightBox("deferred_light_box.vs", "deferred_light_box.frag"); // Set samplers shaderLightingPass.Use(); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gPosition"), 0); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gNormal"), 1); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gAlbedoSpec"), 2); // Models Model cyborg(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj").c_str()); std::vector<glm::vec3> objectPositions; objectPositions.push_back(glm::vec3(-3.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, -3.0)); objectPositions.push_back(glm::vec3(-3.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, 0.0)); objectPositions.push_back(glm::vec3(-3.0, -3.0, 3.0)); objectPositions.push_back(glm::vec3(0.0, -3.0, 3.0)); objectPositions.push_back(glm::vec3(3.0, -3.0, 3.0)); // - Colors const GLuint NR_LIGHTS = 32; std::vector<glm::vec3> lightPositions; std::vector<glm::vec3> lightColors; srand(13); for (GLuint i = 0; i < NR_LIGHTS; i++) { // Calculate slightly random offsets GLfloat xPos = ((rand() % 100) / 100.0) * 6.0 - 3.0; GLfloat yPos = ((rand() % 100) / 100.0) * 6.0 - 4.0; GLfloat zPos = ((rand() % 100) / 100.0) * 6.0 - 3.0; lightPositions.push_back(glm::vec3(xPos, yPos, zPos)); // Also calculate random color GLfloat rColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 GLfloat gColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 GLfloat bColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0 lightColors.push_back(glm::vec3(rColor, gColor, bColor)); } // Set up G-Buffer // 3 textures: // 1. Positions (RGB) // 2. Color (RGB) + Specular (A) // 3. Normals (RGB) GLuint gBuffer; glGenFramebuffers(1, &gBuffer); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); GLuint gPosition, gNormal, gAlbedoSpec; // - Position color buffer glGenTextures(1, &gPosition); glBindTexture(GL_TEXTURE_2D, gPosition); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); // - Normal color buffer glGenTextures(1, &gNormal); glBindTexture(GL_TEXTURE_2D, gNormal); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); // - Color + Specular color buffer glGenTextures(1, &gAlbedoSpec); glBindTexture(GL_TEXTURE_2D, gAlbedoSpec); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedoSpec, 0); // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, attachments); // - Create and attach depth buffer (renderbuffer) GLuint rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); // - Finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Game loop while (!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); // 1. Geometry Pass: render scene's geometry/color data into gbuffer glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 model; shaderGeometryPass.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); for (GLuint i = 0; i < objectPositions.size(); i++) { model = glm::mat4(); model = glm::translate(model, objectPositions[i]); model = glm::scale(model, glm::vec3(0.25f)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); cyborg.Draw(shaderGeometryPass); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 2. Lighting Pass: calculate lighting by iterating over a screen filled quad pixel-by-pixel using the gbuffer's content. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderLightingPass.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPosition); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, gAlbedoSpec); // Also send light relevant uniforms for (GLuint i = 0; i < lightPositions.size(); i++) { glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]); glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]); // Update attenuation parameters and calculate radius const GLfloat constant = 1.0; // Note that we don't send this to the shader, we assume it is always 1.0 (in our case) const GLfloat linear = 0.7; const GLfloat quadratic = 1.8; glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Linear").c_str()), linear); glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Quadratic").c_str()), quadratic); // Then calculate radius of light volume/sphere const GLfloat lightThreshold = 5.0; // 5 / 256 const GLfloat maxBrightness = std::fmaxf(std::fmaxf(lightColors[i].r, lightColors[i].g), lightColors[i].b); GLfloat radius = (-linear + static_cast<float>(std::sqrt(linear * linear - 4 * quadratic * (constant - (256.0 / lightThreshold) * maxBrightness)))) / (2 * quadratic); glUniform1f(glGetUniformLocation(shaderLightingPass.Program, ("lights[" + std::to_string(i) + "].Radius").c_str()), radius); } glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "viewPos"), 1, &camera.Position[0]); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "draw_mode"), draw_mode); RenderQuad(); // 2.5. Copy content of geometry's depth buffer to default framebuffer's depth buffer glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Write to default framebuffer // blit to default framebuffer. Note that this may or may not work as the internal formats of both the FBO and default framebuffer have to match. // the internal formats are implementation defined. This works on all of my systems, but if it doesn't on yours you'll likely have to write to the // depth buffer in another stage (or somehow see to match the default framebuffer's internal format with the FBO's internal format). glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 3. Render lights on top of scene, by blitting shaderLightBox.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); for (GLuint i = 0; i < lightPositions.size(); i++) { model = glm::mat4(); model = glm::translate(model, lightPositions[i]); model = glm::scale(model, glm::vec3(0.25f)); glUniformMatrix4fv(glGetUniformLocation(shaderLightBox.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniform3fv(glGetUniformLocation(shaderLightBox.Program, "lightColor"), 1, &lightColors[i][0]); RenderCube(); } // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }
void LocationEditor::RenderModeLandTile() { Vector3 mousePos3D = g_app->m_userInput->GetMousePos3d(); Landscape *land = &g_app->m_location->m_landscape; // Highlight any tile under our mouse cursor LList<LandscapeTile *> *tiles = &g_app->m_location->m_levelFile->m_landscape.m_tiles; for (int i = 0; i < tiles->Size(); ++i) { if (i == m_selectionId) continue; LandscapeTile *tile = tiles->GetData(i); float worldX = tile->m_posX - tile->m_heightMap->m_cellSizeX; float worldZ = tile->m_posZ - tile->m_heightMap->m_cellSizeY; float sizeX = tile->m_size; float sizeY = tile->m_desiredHeight - tile->m_outsideHeight; float sizeZ = tile->m_size; if (mousePos3D.x > worldX && mousePos3D.x < worldX + sizeX && mousePos3D.z > worldZ && mousePos3D.z < worldZ + sizeZ) { Vector3 centre(worldX, tile->m_outsideHeight, worldZ); centre.x += sizeX * 0.5; centre.y += sizeY * 0.5; centre.z += sizeZ * 0.5; RenderCube(centre, sizeX, sizeY, sizeZ, RGBAColour(128,255,128,99)); } } // Render guide grids if( EclGetWindow("editor_guidegrid") ) { glEnable( GL_LINE_SMOOTH ); glEnable( GL_BLEND ); if (m_selectionId != -1) { LandscapeTile *tile = tiles->GetData(m_selectionId); if( tile->m_guideGrid && tile->m_guideGrid->GetNumColumns() > 0 ) { float gridCellSize = tile->m_size / (float) (tile->m_guideGrid->GetNumColumns()+1); for( int x = 0; x < tile->m_guideGrid->GetNumColumns()-1; ++x ) { for( int z = 0; z < tile->m_guideGrid->GetNumColumns()-1; ++z ) { float value1 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x, z ) / 256.0); float value2 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x+1, z ) / 256.0 ); float value3 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x+1, z+1 ) / 256.0 ); float value4 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x, z+1 ) / 256.0 ); float tileX = tile->m_posX + (x+1) * gridCellSize; float tileZ = tile->m_posZ + (z+1) * gridCellSize; float tileW = gridCellSize; float tileH = gridCellSize; glDisable( GL_DEPTH_TEST ); glLineWidth( 1.0 ); glColor4f( 1.0, 0.0, 0.0, 0.2 ); glBegin( GL_LINE_LOOP ); glVertex3f( tileX, tile->m_posY + value1, tileZ ); glVertex3f( tileX + tileW, tile->m_posY + value2, tileZ ); glVertex3f( tileX + tileW, tile->m_posY + value3, tileZ + tileH ); glVertex3f( tileX, tile->m_posY + value4, tileZ + tileH ); glEnd(); glEnable( GL_DEPTH_TEST ); glColor4f( 1.0, 0.0, 0.0, 0.8 ); glLineWidth( 3.0 ); glBegin( GL_LINE_LOOP ); glVertex3f( tileX, tile->m_posY + value1, tileZ ); glVertex3f( tileX + tileW, tile->m_posY + value2, tileZ ); glVertex3f( tileX + tileW, tile->m_posY + value3, tileZ + tileH ); glVertex3f( tileX, tile->m_posY + value4, tileZ + tileH ); glEnd(); } } } } glDisable( GL_BLEND ); glEnable( GL_DEPTH_TEST ); } // Render a green box around the currently selected tile (if any) if (m_selectionId != -1) { LandscapeTile *tile = tiles->GetData(m_selectionId); float x = tile->m_posX - tile->m_heightMap->m_cellSizeX; float y = tile->m_outsideHeight; float z = tile->m_posZ - tile->m_heightMap->m_cellSizeY; float sX = tile->m_size; float sY = tile->m_desiredHeight - tile->m_outsideHeight; float sZ = tile->m_size; Vector3 centre(x, y, z); centre.x += sX * 0.5; centre.y += sY * 0.5; centre.z += sZ * 0.5; RenderCube(centre, sX, sY, sZ, RGBAColour(128,255,128)); if( m_newLandscapeX != tile->m_posX || m_newLandscapeZ != tile->m_posZ ) { x = m_newLandscapeX; y = 1.0; z = m_newLandscapeZ; glColor3ub( 0, 0, 255 ); glBegin( GL_LINE_LOOP ); glVertex3f( x, y, z ); glVertex3f( x + sX, y, z ); glVertex3f( x + sX, y, z + sZ ); glVertex3f( x, y, z + sZ ); glEnd(); } } CHECK_OPENGL_STATE(); }
void CCube::RenderScene( GLsizei iWidth, GLsizei iHeight, GLfloat viewpoint, GLfloat pitch, GLfloat roll ) { static int iRecompute = 0; static float size[4] = {.3,.3,.3,.3}; //static float newsize[4] = {.3,.3,.3,.3}; //glColor4fv(black); //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); m_iWidth = iWidth; m_iHeight = iHeight; m_viewpoint = viewpoint; bVar = (bool)(iRecompute++ % 10); // cube size depends on our variance, have it range from .3 to .8, default to .4 // sample the last 1 second to find a max, and then see if our value is the max for that range float fTest[4] = {0,0,0,0}; float fSubsample[4] = {0,0,0,0}; long lMaxOffset = sm ? sm->lOffset-2 : 0; float fCtr = 0; const float cfNumSeconds = .2f; const float cfNumSecondsMean = 2.0f; long lStartOffset = sm ? (long)(cfNumSeconds/sm->dt) : 0; long lStartMean = sm ? (long)(cfNumSecondsMean/sm->dt) : 0; if (sm && lMaxOffset > lStartOffset && lMaxOffset > lStartMean) { // get the max for a 3-second window if (!bVar) { // compute baseline, note these values are member vars so just set once iRecompute = 1; qcn_util::ComputeMeanStdDevVarianceKnuth((const float*) sm->x0, MAXI, lMaxOffset - lStartMean, lMaxOffset, &fMean[E_DX], &fStdDev[E_DX], &fVariance[E_DX], &fMin[E_DX], &fMax[E_DX]); qcn_util::ComputeMeanStdDevVarianceKnuth((const float*) sm->y0, MAXI, lMaxOffset - lStartMean, lMaxOffset, &fMean[E_DY], &fStdDev[E_DY], &fVariance[E_DY], &fMin[E_DY], &fMax[E_DY]); qcn_util::ComputeMeanStdDevVarianceKnuth((const float*) sm->z0, MAXI, lMaxOffset - lStartMean, lMaxOffset, &fMean[E_DZ], &fStdDev[E_DZ], &fVariance[E_DZ], &fMin[E_DZ], &fMax[E_DZ]); } fCtr = 0; // now sample the last second for (long i = lMaxOffset; i >= lMaxOffset - lStartOffset; i--) { fCtr++; fTest[E_DX] = sm->x0[i]; fTest[E_DY] = sm->y0[i]; fTest[E_DZ] = sm->z0[i]; for (int j = E_DX; j <= E_DZ ; j++) { fSubsample[j] += fTest[j];//Changed by Jesse Lawrence-JUST Y DIRECTION NOW. // fSubsample[j]=fTest[E_DY]; } } } for (int j = E_DX; j <= E_DZ ; j++) { fSubsample[j] /= fCtr; fTest[j] = (fSubsample[j] - fMean[j]); // fStdDev[E_DY]; // more than +4 is huge, +2 is big, with stddev is normal, -2 smaller, -4 tiny /* newsize[j] = 0.30f + ((10.0f*(fTest[j]/4.0f) + fMouseFactor; // don't do abrupt changes, so if newsize is much bigger than size just do a little change (.1) if (newsize[j] < size[j] + .1f) size[j] -= .1f; else if (newsize[j] > size[j] + .1f) size[j] += .1f; */ size[j] = 0.30f + fTest[j]/4.0f + fMouseFactor; if (size[j] > 2.0f) size[j] = 2.0f; else if (size[j] < -1.3f) size[j] = -1.3f; //Jesse Lawrence Added - Maximum negative value else if (size[j] < .05f && size[j] > 0.f) size[j] = .05f; else if (size[j] > -.05f && size[j] <= 0.f) size[j] = -.05f;//Jesse Lawrence Added - Minimum negative value } size[E_DY] = ( (size[E_DY]+1.3f) /6.f );//Jesse Lawrence Added - Y to non-negative number RenderCube(size); }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); // Define the viewport dimensions int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); // Setup and compile our shaders Shader shader("bloom.vs", "bloom.frag"); Shader shaderLight("bloom.vs", "light_box.frag"); Shader shaderBlur("blur.vs", "blur.frag"); Shader shaderBloomFinal("bloom_final.vs", "bloom_final.frag"); // Set samplers shaderBloomFinal.Use(); glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "scene"), 0); glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloomBlur"), 1); // Light sources // - Positions std::vector<glm::vec3> lightPositions; lightPositions.push_back(glm::vec3(0.0f, 0.5f, 1.5f)); // back light lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.0f)); lightPositions.push_back(glm::vec3(3.0f, 0.5f, 1.0f)); lightPositions.push_back(glm::vec3(-.8f, 2.4f, -1.0f)); // - Colors std::vector<glm::vec3> lightColors; lightColors.push_back(glm::vec3(5.0f, 5.0f, 5.0f)); lightColors.push_back(glm::vec3(5.5f, 0.0f, 0.0f)); lightColors.push_back(glm::vec3(0.0f, 0.0f, 15.0f)); lightColors.push_back(glm::vec3(0.0f, 1.5f, 0.0f)); // Load textures GLuint woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); GLuint containerTexture = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str()); // Set up floating point framebuffer to render scene to GLuint hdrFBO; glGenFramebuffers(1, &hdrFBO); glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); // - Create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values) GLuint colorBuffers[2]; glGenTextures(2, colorBuffers); for (GLuint i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, colorBuffers[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); 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_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values! glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // attach texture to framebuffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0); } // - Create and attach depth buffer (renderbuffer) GLuint rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, attachments); // - Finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); // Ping pong framebuffer for blurring GLuint pingpongFBO[2]; GLuint pingpongColorbuffers[2]; glGenFramebuffers(2, pingpongFBO); glGenTextures(2, pingpongColorbuffers); for (GLuint i = 0; i < 2; i++) { glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]); glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); 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_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values! glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0); // Also check if framebuffers are complete (no need for depth buffer) if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; } glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Game loop while (!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); // 1. Render scene into floating point framebuffer glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 model; shader.Use(); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); // - set lighting uniforms for (GLuint i = 0; i < lightPositions.size(); i++) { glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]); glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]); } glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); // - create one large cube that acts as the floor model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0)); model = glm::scale(model, glm::vec3(25.0f, 1.0f, 25.0f)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); // - then create multiple cubes as the scenery glBindTexture(GL_TEXTURE_2D, containerTexture); model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.0f, -1.0f, 2.0)); model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(2.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 2.7f, 4.0)); model = glm::rotate(model, 23.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(2.5)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-2.0f, 1.0f, -3.0)); model = glm::rotate(model, 124.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); model = glm::scale(model, glm::vec3(2.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); RenderCube(); model = glm::mat4(); model = glm::translate(model, glm::vec3(-3.0f, 0.0f, 0.0)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); // - finally show all the light sources as bright cubes shaderLight.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); for (GLuint i = 0; i < lightPositions.size(); i++) { model = glm::mat4(); model = glm::translate(model, glm::vec3(lightPositions[i])); model = glm::scale(model, glm::vec3(0.5f)); glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniform3fv(glGetUniformLocation(shaderLight.Program, "lightColor"), 1, &lightColors[i][0]); RenderCube(); } glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. Blur bright fragments w/ two-pass Gaussian Blur GLboolean horizontal = true, first_iteration = true; GLuint amount = 10; shaderBlur.Use(); for (GLuint i = 0; i < amount; i++) { glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); glUniform1i(glGetUniformLocation(shaderBlur.Program, "horizontal"), horizontal); glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); // bind texture of other framebuffer (or scene if first iteration) RenderQuad(); horizontal = !horizontal; if (first_iteration) first_iteration = false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderBloomFinal.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); //glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloom"), bloom); glUniform1f(glGetUniformLocation(shaderBloomFinal.Program, "exposure"), exposure); RenderQuad(); // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); glGetError(); // Define the viewport dimensions glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); // Setup and compile our shaders Shader shaderGeometryPass("ssao_geometry.vs", "ssao_geometry.frag"); Shader shaderLightingPass("ssao.vs", "ssao_lighting.frag"); Shader shaderSSAO("ssao.vs", "ssao.frag"); Shader shaderSSAOBlur("ssao.vs", "ssao_blur.frag"); // Set samplers shaderLightingPass.Use(); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gPositionDepth"), 0); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gNormal"), 1); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "gAlbedo"), 2); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "ssao"), 3); shaderSSAO.Use(); glUniform1i(glGetUniformLocation(shaderSSAO.Program, "gPositionDepth"), 0); glUniform1i(glGetUniformLocation(shaderSSAO.Program, "gNormal"), 1); glUniform1i(glGetUniformLocation(shaderSSAO.Program, "texNoise"), 2); // Objects Model nanosuit(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj").c_str()); // Lights glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0); glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7); // Set up G-Buffer // 3 textures: // 1. Positions + depth (RGBA) // 2. Color (RGB) // 3. Normals (RGB) GLuint gBuffer; glGenFramebuffers(1, &gBuffer); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); GLuint gPositionDepth, gNormal, gAlbedo; // - Position + linear depth color buffer glGenTextures(1, &gPositionDepth); glBindTexture(GL_TEXTURE_2D, gPositionDepth); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); 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_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPositionDepth, 0); // - Normal color buffer glGenTextures(1, &gNormal); glBindTexture(GL_TEXTURE_2D, gNormal); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); // - Albedo color buffer glGenTextures(1, &gAlbedo); glBindTexture(GL_TEXTURE_2D, gAlbedo); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedo, 0); // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, attachments); // - Create and attach depth buffer (renderbuffer) GLuint rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); // - Finally check if framebuffer is complete if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "GBuffer Framebuffer not complete!" << std::endl; // Also create framebuffer to hold SSAO processing stage GLuint ssaoFBO, ssaoBlurFBO; glGenFramebuffers(1, &ssaoFBO); glGenFramebuffers(1, &ssaoBlurFBO); glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); GLuint ssaoColorBuffer, ssaoColorBufferBlur; // - SSAO color buffer glGenTextures(1, &ssaoColorBuffer); glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "SSAO Framebuffer not complete!" << std::endl; // - and blur stage glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glGenTextures(1, &ssaoColorBufferBlur); glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBufferBlur, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "SSAO Blur Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); // Sample kernel std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 std::default_random_engine generator; std::vector<glm::vec3> ssaoKernel; for (GLuint i = 0; i < 64; ++i) { glm::vec3 sample(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, randomFloats(generator)); sample = glm::normalize(sample); sample *= randomFloats(generator); GLfloat scale = GLfloat(i) / 64.0; // Scale samples s.t. they're more aligned to center of kernel scale = lerp(0.1f, 1.0f, scale * scale); sample *= scale; ssaoKernel.push_back(sample); } // Noise texture std::vector<glm::vec3> ssaoNoise; for (GLuint i = 0; i < 16; i++) { glm::vec3 noise(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, 0.0f); // rotate around z-axis (in tangent space) ssaoNoise.push_back(noise); } GLuint noiseTexture; glGenTextures(1, &noiseTexture); glBindTexture(GL_TEXTURE_2D, noiseTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); 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_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Game loop while (!glfwWindowShouldClose(window)) { // Set frame time GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); Do_Movement(); // 1. Geometry Pass: render scene's geometry/color data into gbuffer glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 50.0f); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 model; shaderGeometryPass.Use(); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); // Floor cube model = glm::translate(model, glm::vec3(0.0, -1.0f, 0.0f)); model = glm::scale(model, glm::vec3(20.0f, 1.0f, 20.0f)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); RenderCube(); // Nanosuit model on the floor model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 5.0)); model = glm::rotate(model, -90.0f, glm::vec3(1.0, 0.0, 0.0)); model = glm::scale(model, glm::vec3(0.5f)); glUniformMatrix4fv(glGetUniformLocation(shaderGeometryPass.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); nanosuit.Draw(shaderGeometryPass); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. Create SSAO texture glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO); glClear(GL_COLOR_BUFFER_BIT); shaderSSAO.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPositionDepth); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, noiseTexture); // Send kernel + rotation for (GLuint i = 0; i < 64; ++i) glUniform3fv(glGetUniformLocation(shaderSSAO.Program, ("samples[" + std::to_string(i) + "]").c_str()), 1, &ssaoKernel[i][0]); glUniformMatrix4fv(glGetUniformLocation(shaderSSAO.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); RenderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 3. Blur SSAO texture to remove noise glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO); glClear(GL_COLOR_BUFFER_BIT); shaderSSAOBlur.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer); RenderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 4. Lighting Pass: traditional deferred Blinn-Phong lighting now with added screen-space ambient occlusion glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderLightingPass.Use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gPositionDepth); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, gAlbedo); glActiveTexture(GL_TEXTURE3); // Add extra SSAO texture to lighting pass glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur); // Also send light relevant uniforms glm::vec3 lightPosView = glm::vec3(camera.GetViewMatrix() * glm::vec4(lightPos, 1.0)); glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "light.Position"), 1, &lightPosView[0]); glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "light.Color"), 1, &lightColor[0]); // Update attenuation parameters const GLfloat constant = 1.0; // Note that we don't send this to the shader, we assume it is always 1.0 (in our case) const GLfloat linear = 0.09; const GLfloat quadratic = 0.032; glUniform1f(glGetUniformLocation(shaderLightingPass.Program, "light.Linear"), linear); glUniform1f(glGetUniformLocation(shaderLightingPass.Program, "light.Quadratic"), quadratic); glUniform1i(glGetUniformLocation(shaderLightingPass.Program, "draw_mode"), draw_mode); RenderQuad(); // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }