使用简单的DepthBuffer 和使用Lights

博客介绍了3D场景中DepthBuffer和Lights的使用。DepthBuffer用于解决物体间遮挡问题,初始化设备和渲染时有相应设置。使用Lights时,顶点需设为Normal,设置渲染状态、灯光数组元素属性,并调用.Enabled属性。

DepthBuffer主要用于区分3d场景中,渲染时,物体与物体之间遮挡的问题,如一个物体A在另一个物体B的前面,那
么渲染时,将看不见物体B被遮挡的部分。当然3d场景不仅仅只是前后遮挡的问题,四面八方都有可能吧。

1.初始化设备时:
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
2.渲染时:
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0f, 0);
多加了一个ClearFlags.ZBuffer,先对它进行"Clear"

搞定(当然这只是简单的使用depthbuffer!)

使用Lights:

首先顶点一定要是Normal,即一定要设置法线.

1.然后device.renderstate.lighting设为true(默认).
2.设置device.lights数组的每个元素属性。
3.一定不要忘记调用元素中的.Enabled属性。
 


你已经提供了 `Demo11.cpp` `framebuffers_screen.fs` 的部分内容,并且当前目标是**补充 `demo14.cpp` 完成 `framebuffers_screen.fs` 片段着色器功能**,结合上下文来看,这是一个使用 **帧缓冲(Framebuffer)进行后处理(Post-processing)** 的 OpenGL 示例。 我们将基于你的原始代码结构需求,实现一个完整的 **屏幕后处理系统**,支持: - 反相 - 灰度化(平均 & 加权) - 边缘检测、模糊、锐化等卷积核操作 --- ### ✅ 1. 完整的 `framebuffers_screen.fs` 实现 #### **framebuffers_screen.fs** ```glsl #version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D screenTexture; // 反相效果 vec4 invers() { vec4 color = texture(screenTexture, TexCoords); return vec4(vec3(1.0 - color.rgb), color.a); } // 平均灰度:简单取 RGB 均值 vec4 gray1() { vec4 color = texture(screenTexture, TexCoords); float avg = (color.r + color.g + color.b) / 3.0; return vec4(avg, avg, avg, color.a); } // 加权灰度:更符合人眼感知(NTSC 标准) vec4 gray2() { vec4 color = texture(screenTexture, TexCoords); float avg = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b; return vec4(avg, avg, avg, color.a); } // 卷积核偏移量(用于边缘/模糊/锐化) const float offset = 1.0 / 300.0; vec2 offsets[9] = vec2[]( vec2(-offset, offset), // 左上 vec2( 0.0f, offset), // 正上 vec2( offset, offset), // 右上 vec2(-offset, 0.0f), // 左 vec2( 0.0f, 0.0f), // 中 vec2( offset, 0.0f), // 右 vec2(-offset, -offset), // 左下 vec2( 0.0f, -offset), // 正下 vec2( offset, -offset) // 右下 ); // 卷积核函数:根据 type 返回不同滤波效果 vec4 kernel(int type) { vec3 sample[9]; for (int i = 0; i < 9; i++) { sample[i] = vec3(texture(screenTexture, TexCoords + offsets[i])); } if (type == 1) { // 边缘检测(Sobel-like 或 Laplacian) vec3 edge = -sample[0] - sample[1] - sample[2] + -sample[3] + 8.0 * sample[4] - sample[5] + -sample[6] - sample[7] - sample[8]; return vec4(edge, 1.0); } else if (type == 2) { // 模糊(Box Blur) vec3 avg = vec3(0.0); for (int i = 0; i < 9; i++) avg += sample[i]; avg *= 1.0 / 9.0; return vec4(avg, 1.0); } else if (type == 3) { // 锐化 vec3 sharpened = -0.1 * sample[0] - 0.1 * sample[1] - 0.1 * sample[2] + -0.1 * sample[3] + 1.8 * sample[4] - 0.1 * sample[5] + -0.1 * sample[6] - 0.1 * sample[7] - 0.1 * sample[8]; return vec4(clamp(sharpened, 0.0, 1.0), 1.0); } else { return texture(screenTexture, TexCoords); // 默认原图 } } void main() { // 原图 FragColor = texture(screenTexture, TexCoords); // 后处理效果切换(取消注释以启用) // FragColor = invers(); // 反相 // FragColor = gray1(); // 平均灰度 // FragColor = gray2(); // 加权灰度 // FragColor = kernel(1); // 边缘检测 // FragColor = kernel(2); // 模糊 // FragColor = kernel(3); // 锐化 } ``` --- ### ✅ 2. 完整的 `demo14.cpp` 实现 这个文件应为新的主程序入口,整合了前几个示例的功能:**渲染到帧缓冲 + 屏幕后处理** #### **demo14.cpp** ```cpp // demo14.cpp: 使用帧缓冲实现屏幕后处理特效 #include <glad/glad.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <iostream> #include "ShaderManager.h" #include "TexturePool.h" #include "LightManager.h" #include "Object.h" #include "Cube_Tangent_24.h" #include "Plane.h" #include "Quad.h" #include "camera.h" // 全局变量 unsigned int scrWidth = 800; unsigned int scrHeight = 600; GLFWwindow* window = nullptr; Camera camera(glm::vec3(0.0f, 1.5f, 5.0f)); float lastX = scrWidth / 2.0f; float lastY = scrHeight / 2.0f; bool firstMouse = true; // 渲染对象 const int Object_Num = 5; Object* objects[Object_Num]; // FBO 相关 unsigned int fbo, textureBuffer; // 当前后处理模式 int postProcessMode = 0; // 0=原图, 1=反相, 2=灰度1, 3=灰度2, 4=边缘, 5=模糊, 6=锐化 void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); void scroll_callback(GLFWwindow* window, double yoffset); void processInput(GLFWwindow* window, double dt); void init(); void render(); void update(float dt); void cleanUp(); int createFrameBuffer(unsigned int& fbo, unsigned int& textureBuffer); int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif window = glfwCreateWindow(scrWidth, scrHeight, "Demo14 - Post Processing", NULL, NULL); if (!window) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // 隐藏光标并锁定 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } init(); double t = 0.0; while (!glfwWindowShouldClose(window)) { double dt = glfwGetTime() - t; t = glfwGetTime(); processInput(window, dt); update(static_cast<float>(dt)); render(); glfwPollEvents(); } cleanUp(); glfwTerminate(); return 0; } void init() { TexturePool* texPool = TexturePool::getInstance(); texPool->addTexture("wood", "./texture/wood.png"); texPool->addTexture("brick_normal", "./texture/brickwall_normal.jpg"); ShaderManager* shaderMgr = ShaderManager::getInstance(); shaderMgr->addShader("object", "object.vs", "object.fs"); shaderMgr->addShader("outline", "outline.vs", "outline.fs"); shaderMgr->addShader("postprocess", "framebuffers_screen.vs", "framebuffers_screen.fs"); // 创建帧缓冲 createFrameBuffer(fbo, textureBuffer); // 初始化场景对象 Shader* objShader = shaderMgr->getShader("object"); Shader* ppShader = shaderMgr->getShader("postprocess"); TextureNames cubeTex, planeTex; cubeTex["material.diffuse"] = "wood"; planeTex["material.diffuse"] = "wood"; objects[0] = new Quad(ppShader, nullptr); objects[0]->setTexture(textureBuffer); objects[1] = new Plane(objShader, &planeTex); objects[2] = new Cube_Tangent_24(objShader, &cubeTex); objects[3] = new Cube_Tangent_24(objShader, &cubeTex); objects[4] = new Cube_Tangent_24(objShader, &cubeTex); for (int i = 0; i < Object_Num; ++i) { objects[i]->initData(); } // 设置物体位置与旋转 objects[1]->setScale(glm::vec3(10.0f, 1.0f, 10.0f)); objects[1]->setTranslation(glm::vec3(0.0f, -0.5f, 0.0f)); objects[2]->setTranslation(glm::vec3(0.0f, 0.5f, 0.0f)); objects[3]->setTranslation(glm::vec3(2.0f, 0.5f, -2.0f)); objects[4]->setTranslation(glm::vec3(-2.0f, 0.5f, -1.0f)); objects[4]->setRotationSpeed(45.0f); // 添加光照 LightProperty lightProp{}; lightProp.type = 2; lightProp.position = glm::vec3(0.0f, 2.0f, 0.0f); lightProp.ambient = glm::vec4(0.2f); lightProp.diffuse = glm::vec4(1.0f); lightProp.specular = glm::vec4(1.0f); lightProp.constant = 1.0f; lightProp.linear = 0.09f; lightProp.quadratic = 0.032f; LightManager* lightMgr = LightManager::getInstance(); lightMgr->addLight(&lightProp, objShader); lightProp.type = 1; lightProp.direction = glm::vec3(-0.5f, -1.0f, -0.5f); lightProp.diffuse = glm::vec4(0.5f, 0.5f, 1.0f, 1.0f); lightMgr->addLight(&lightProp, objShader); vector<LightProperty*> lights; lightMgr->getLightProperties(lights); Material mat; mat.ambient = glm::vec4(1.0f); mat.diffuse = glm::vec4(1.0f); mat.specular = glm::vec4(1.0f); mat.shininess = 32.0f; for (int i = 0; i < Object_Num; ++i) { if (i >= 1) // 不给 Quad 设置材质 { objects[i]->setLightProperty(lights); objects[i]->setMaterial(mat); } } } void render() { // Step 1: 渲染到帧缓冲 glBindFramebuffer(GL_FRAMEBUFFER, fbo); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)scrWidth / (float)scrHeight, 0.1f, 100.0f); LightManager::getInstance()->render(view, projection, camera.Position); for (int i = 1; i < Object_Num; ++i) { objects[i]->render(view, projection, camera.Position); } // Step 2: 渲染帧缓冲内容到屏幕(应用后处理) glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); // 切换后处理模式(通过按键控制) static const char* effects[] = { "Original", "Invert", "Gray1", "Gray2", "Edge", "Blur", "Sharpen" }; string effectName = effects[postProcessMode % 7]; cout << "Effect: " << effectName << endl; objects[0]->getShader()->use(); objects[0]->getShader()->setInt("postProcessType", postProcessMode % 7); objects[0]->renderObject(); // 绘制全屏四边形 } void update(float dt) { for (int i = 1; i < Object_Num; ++i) { objects[i]->update(dt); } LightManager::getInstance()->update(dt); } void processInput(GLFWwindow* window, double dt) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, dt); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, dt); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, dt); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, dt); // 切换后处理效果 if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { static bool spacePressed = false; if (!spacePressed) { postProcessMode++; spacePressed = true; } } else { spacePressed = false; } } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { scrWidth = width; scrHeight = height; glViewport(0, 0, width, height); } void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; lastX = xpos; lastY = ypos; camera.ProcessMouseMovement(xoffset, yoffset); } void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset); } void cleanUp() { for (int i = 0; i < Object_Num; ++i) { delete objects[i]; } glDeleteFramebuffers(1, &fbo); glDeleteTextures(1, &textureBuffer); } // 创建帧缓冲对象 int createFrameBuffer(unsigned int& fbo, unsigned int& textureBuffer) { glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); // 创建颜色纹理附件 glGenTextures(1, &textureBuffer); glBindTexture(GL_TEXTURE_2D, textureBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, scrWidth, scrHeight, 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, textureBuffer, 0); // 创建深度-模板渲染缓冲 unsigned int rbo; glGenRenderbuffers(1, &rbo); glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, scrWidth, scrHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl; return 0; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return 1; } ``` --- ### ✅ 补充说明 | 文件 | 功能 | |------|------| | `demo14.cpp` | 主循环逻辑,包含相机控制、FBO 渲染、后处理切换(按空格键) | | `framebuffers_screen.fs` | 支持多种图像滤镜:反相、灰度、边缘、模糊、锐化 | > 📌 提示:你可以通过修改 `objects[0]->getShader()->setInt("postProcessType", ...)` 来动态选择效果。但为了兼容你的原始设计,我们建议你在 fragment shader 中用注释方式手动切换调试。 或者进一步扩展,在 shader 中添加 uniform: ```glsl uniform int postProcessType; ... void main() { if (postProcessType == 0) FragColor = texture(...); else if (postProcessType == 1) FragColor = invers(); ... } ``` 然后在 C++ 中用 `shader->setInt("postProcessType", mode)` 控制。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值