CP21:FRAMEBUFFER
这章我又被贴图单元迷惑了,经过理性的测试,发现一个Frag材质里只有一个贴图.那么绘制如下:
#version 450 core // INCOMING DATA layout ( location = 0 ) in vec4 v_position; // pos //layout ( location = 1 ) in vec3 v_normal; // norm layout ( location = 1 ) in vec2 v_texCoord; // st // define out data out vec2 f_TexCoord; // normal at world matrix, we direct from C++ calcalation out vec3 f_Normal; // to world matrix : mat3( transpose(inverse(model)) ) * v_normal; out vec3 f_Pos; // INCOMING THE MATRIX FROM CLIENT to transform the gl point position uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ // Transform the world matrix to view matrix gl_Position = projection * view * model * v_position; //f_Normal = mat3(transpose(inverse(model))) * v_normal; // f_Normal at world matrix f_TexCoord = v_texCoord; // out TexCoord f_Pos = vec3(model *v_position); // out fragment position }
#version 450 core // Final Color To export out vec4 FragColor; // from vert shader in vec3 f_Normal; in vec2 f_TexCoord; in vec3 f_Pos; // fragment position uniform sampler2D diffuse_map; void main() { vec4 df = texture(diffuse_map, f_TexCoord); FragColor = df; }
教程中用了个Quad 形状覆盖到整个窗口上的材质:
#version 450 core // INCOMING DATA layout (location = 0) in vec2 aPos; layout (location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { TexCoords = aTexCoords; gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); }
#version 450 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D screenTexture; void main() { vec3 col = texture2D(screenTexture, TexCoords).rgb; FragColor = vec4(col, 1.0); }
教程中所展示的: 不用贴图单元是完全可以的:
#define GLEW_STATIC // GLEW #include <GL/glew.h> #include <cstdlib> #undef GLFW_DLL // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "ALG_LoadShader.h" #include "ALG_LoadTexture.h" #include "ALG_GLFWCamera.h" #include "ALG_FrameWindow.h" #include "ALG_ModelDelegate.h" #include "ALG_SceneDelegate.h" #include "ALG_DrawGrid.h" #include <cmath> #include "OGLHelper.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <map> using namespace AlgebraMaster; const unsigned int SRC_WIDTH = 1400; const unsigned int SRC_HEIGHT = 720; static LoadShader SurfaceShader; static LoadShader ScreenShader; void init(); void display(); void processInput(GLFWwindow *window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); // camera static GLFWCamera *camera; static float lastX = float(SRC_WIDTH) / 2.0f; static float lastY = float(SRC_HEIGHT) / 2.0f; static bool firstMouse = true; static bool firstMiddowMouse = true; // timing static float deltaTime = 0.0f; // time between current frame and last frame static float lastFrame = 0.0f; // light define static glm::vec3 lightPos(0.0f, 4.0f,-2.0f); // Geometry static DrawGrid grid; static float cubeVertices[] = { // positions // texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; static float planeVertices[] = { // positions // texture Coords 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; static float transparentVertices[] = { // positions // texture Coords (swapped y coordinates because texture is flipped upside down) 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f }; float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. // positions // texCoords -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; // cube vao vbo static unsigned int cubeVAO,cubeVBO; static unsigned int planeVAO,planeVBO; static unsigned int quadVAO,quadVBO; static unsigned int FBO; // frame buffer object static unsigned int FBOTextureID; // texture attachment to FBO static unsigned int RBO; // render buffer object static LoadTexture cubeTex; static LoadTexture groundTex; void init(){ camera = new GLFWCamera; camera->pos.y = 1.0f; camera->pos.z = 4.0f; // GL depth zbuffer glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); SurfaceShader.load("shaders/SurfaceShader.vert","shaders/SurfaceShader.frag"); ScreenShader.load("shaders/ScreenShader.vert","shaders/ScreenShader.frag"); glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(planeVAO, planeVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(planeVertices),&planeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(quadVAO, quadVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(quadVertices),&quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glBindVertexArray(0); cout << "cube VAO:" << cubeVAO <<endl; cubeTex.load("texture/marble.jpg"); groundTex.load("texture/metal.png"); // FBO with texture attchment glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glGenTextures(1, &FBOTextureID); glBindTexture(GL_TEXTURE_2D, FBOTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SRC_WIDTH, SRC_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBOTextureID, 0); // render buffer object glGenRenderbuffers(1, &RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SRC_WIDTH, SRC_WIDTH); // use a single renderbuffer object for both a depth AND stencil buffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); // now actually attach it // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); grid.initialize(); } // ----------- Render Loop ---------- void display(){ // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // bind to framebuffer and draw scene as we normally would to color texture glBindFramebuffer(GL_FRAMEBUFFER, FBO); glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // object .vert settings glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f); glm::mat4 view = camera->GetViewMatrix(); // object world transformation glm::mat4 model = glm::mat4(1.0f); grid.draw(projection,view); // render cube glBindTexture(GL_TEXTURE_2D,cubeTex.textureID); SurfaceShader.use(); SurfaceShader.setInt("diffuse_map", 0); SurfaceShader.setMat4("projection", projection); SurfaceShader.setMat4("view", view); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); SurfaceShader.setMat4("model", model); glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); // floor glBindTexture(GL_TEXTURE_2D, groundTex.getTextureID()); SurfaceShader.setInt("diffuse_map", 0); glBindVertexArray(planeVAO); model = glm::mat4(1.0f); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); // now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture glBindFramebuffer(GL_FRAMEBUFFER, 0); // disable depth test so screen-space quad isn't discarded due to depth test. glDisable(GL_DEPTH_TEST); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) glClear(GL_COLOR_BUFFER_BIT); ScreenShader.use(); ScreenShader.setInt("screenTexture",0 ); glBindVertexArray(quadVAO); glBindTexture(GL_TEXTURE_2D, FBOTextureID); glDrawArrays(GL_TRIANGLES, 0, 6); } int main() { glfwInit(); FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT); glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback); glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback); glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback); init(); // RENDER-------------- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); while(!glfwWindowShouldClose(FrameWindow.getWindow())){ processInput(FrameWindow.getWindow()); display(); glfwSwapBuffers(FrameWindow.getWindow()); glfwPollEvents(); } delete camera; glDeleteVertexArrays(1, &cubeVAO); glDeleteVertexArrays(1, &planeVAO); glDeleteVertexArrays(1, &quadVAO); glDeleteBuffers(1, &cubeVBO); glDeleteBuffers(1, &planeVBO); glDeleteBuffers(1, &quadVBO); return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT); } // ROTATE VIEW DIR void mouse_callback(GLFWwindow* window, double xpos, double ypos){ int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE); int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT); int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT); // set up the camera view if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS) { if (firstMouse){ lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->processMouseMove(xoffset,yoffset); } if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){ firstMouse = true; } // Move Camera Position if( middow_mouse_state == GLFW_PRESS) { if (firstMiddowMouse){ lastX = xpos; lastY = ypos; firstMiddowMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->pos.x += xoffset*0.01f; camera->pos.y += yoffset*0.01f; } if ( middow_mouse_state == GLFW_RELEASE){ firstMiddowMouse = true; } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){ camera->processFov(yoffset); }
观察下面的Render Cube 和 Render Floor 部分,因为材质只有一个diffuse_map,
虽然系统加载了2个贴图,但是每个贴图有个ID,所以:
只要在渲染立方体时候,绑定立方体的贴图ID
glBindTexture(GL_TEXTURE_2D,cubeTex.textureID);
SurfaceShader.setInt("diffuse_map", 0);
只要在渲染地面时候,绑定地面的贴图ID
glBindTexture(GL_TEXTURE_2D, groundTex.getTextureID());
SurfaceShader.setInt("diffuse_map", 0);
所以系统默认的贴图单元是:
glActiveTexture(GL_TEXTURE0)
现在我想强制使用贴图单元控制:
#define GLEW_STATIC // GLEW #include <GL/glew.h> #include <cstdlib> #undef GLFW_DLL // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "ALG_LoadShader.h" #include "ALG_LoadTexture.h" #include "ALG_GLFWCamera.h" #include "ALG_FrameWindow.h" #include "ALG_ModelDelegate.h" #include "ALG_SceneDelegate.h" #include "ALG_DrawGrid.h" #include <cmath> #include "OGLHelper.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <map> using namespace AlgebraMaster; const unsigned int SRC_WIDTH = 1400; const unsigned int SRC_HEIGHT = 720; static LoadShader SurfaceShader; static LoadShader ScreenShader; void init(); void display(); void processInput(GLFWwindow *window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); // camera static GLFWCamera *camera; static float lastX = float(SRC_WIDTH) / 2.0f; static float lastY = float(SRC_HEIGHT) / 2.0f; static bool firstMouse = true; static bool firstMiddowMouse = true; // timing static float deltaTime = 0.0f; // time between current frame and last frame static float lastFrame = 0.0f; // light define static glm::vec3 lightPos(0.0f, 4.0f,-2.0f); // Geometry static DrawGrid grid; static float cubeVertices[] = { // positions // texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; static float planeVertices[] = { // positions // texture Coords 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; static float transparentVertices[] = { // positions // texture Coords (swapped y coordinates because texture is flipped upside down) 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f }; float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. // positions // texCoords -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; // cube vao vbo static unsigned int cubeVAO,cubeVBO; static unsigned int planeVAO,planeVBO; static unsigned int quadVAO,quadVBO; static unsigned int FBO; // frame buffer object static unsigned int FBOTextureID; // texture attachment to FBO static unsigned int RBO; // render buffer object static LoadTexture cubeTex; static LoadTexture groundTex; void init(){ camera = new GLFWCamera; camera->pos.y = 1.0f; camera->pos.z = 4.0f; // GL depth zbuffer glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); SurfaceShader.load("shaders/SurfaceShader.vert","shaders/SurfaceShader.frag"); ScreenShader.load("shaders/ScreenShader.vert","shaders/ScreenShader.frag"); glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(planeVAO, planeVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(planeVertices),&planeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(quadVAO, quadVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(quadVertices),&quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glBindVertexArray(0); cout << "cube VAO:" << cubeVAO <<endl; cubeTex.load("texture/marble.jpg"); groundTex.load("texture/metal.png"); // FBO with texture attchment glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glGenTextures(1, &FBOTextureID); glBindTexture(GL_TEXTURE_2D, FBOTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SRC_WIDTH, SRC_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBOTextureID, 0); // render buffer object glGenRenderbuffers(1, &RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SRC_WIDTH, SRC_WIDTH); // use a single renderbuffer object for both a depth AND stencil buffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); // now actually attach it // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); grid.initialize(); } // ----------- Render Loop ---------- void display(){ // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // bind to framebuffer and draw scene as we normally would to color texture glBindFramebuffer(GL_FRAMEBUFFER, FBO); glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // object .vert settings glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f); glm::mat4 view = camera->GetViewMatrix(); // object world transformation glm::mat4 model = glm::mat4(1.0f); grid.draw(projection,view); // render cube glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,cubeTex.textureID); SurfaceShader.use(); SurfaceShader.setInt("diffuse_map", 0); SurfaceShader.setMat4("projection", projection); SurfaceShader.setMat4("view", view); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); SurfaceShader.setMat4("model", model); glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); // floor glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, groundTex.getTextureID()); SurfaceShader.setInt("diffuse_map", 1); glBindVertexArray(planeVAO); model = glm::mat4(1.0f); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); // now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture glBindFramebuffer(GL_FRAMEBUFFER, 0); // disable depth test so screen-space quad isn't discarded due to depth test. glDisable(GL_DEPTH_TEST); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) glClear(GL_COLOR_BUFFER_BIT); ScreenShader.use(); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, FBOTextureID); ScreenShader.setInt("screenTexture",2 ); glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLES, 0, 6); } int main() { glfwInit(); FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT); glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback); glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback); glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback); init(); // RENDER-------------- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); while(!glfwWindowShouldClose(FrameWindow.getWindow())){ processInput(FrameWindow.getWindow()); display(); glfwSwapBuffers(FrameWindow.getWindow()); glfwPollEvents(); } delete camera; glDeleteVertexArrays(1, &cubeVAO); glDeleteVertexArrays(1, &planeVAO); glDeleteVertexArrays(1, &quadVAO); glDeleteBuffers(1, &cubeVBO); glDeleteBuffers(1, &planeVBO); glDeleteBuffers(1, &quadVBO); return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT); } // ROTATE VIEW DIR void mouse_callback(GLFWwindow* window, double xpos, double ypos){ int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE); int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT); int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT); // set up the camera view if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS) { if (firstMouse){ lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->processMouseMove(xoffset,yoffset); } if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){ firstMouse = true; } // Move Camera Position if( middow_mouse_state == GLFW_PRESS) { if (firstMiddowMouse){ lastX = xpos; lastY = ypos; firstMiddowMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->pos.x += xoffset*0.01f; camera->pos.y += yoffset*0.01f; } if ( middow_mouse_state == GLFW_RELEASE){ firstMiddowMouse = true; } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){ camera->processFov(yoffset); }
对于立方体绘制:
// render cube
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,cubeTex.textureID);
SurfaceShader.use();
SurfaceShader.setInt("diffuse_map", 0);
SurfaceShader.setMat4("projection", projection);
SurfaceShader.setMat4("view", view);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
SurfaceShader.setMat4("model", model);
// draw geometry
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
SurfaceShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
对于地面绘制:
// floor glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, groundTex.getTextureID()); SurfaceShader.setInt("diffuse_map", 1); glBindVertexArray(planeVAO); model = glm::mat4(1.0f); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6);
对于屏幕那个方形绘制:
// now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture glBindFramebuffer(GL_FRAMEBUFFER, 0);
// disable depth test so screen-space quad isn't discarded due to depth test. glDisable(GL_DEPTH_TEST); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) glClear(GL_COLOR_BUFFER_BIT); ScreenShader.use(); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, FBOTextureID); ScreenShader.setInt("screenTexture",2 ); glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLES, 0, 6);
教程的目的是自己建立的buffer用来绘制场景,包括深度,模板。
而自己建立的Quad覆盖到窗口上,是只绘制了Quad,加载了个buffer texture