ryzmxczx 2025-07-27 14:26 采纳率: 50%
浏览 14
已结题

OpenGL 模板测试绘制的模型描边 在自制的帧缓冲中无法被渲染

在opengl中
使用模板测试绘制的模型描边 在默认帧缓冲中可以被正常绘制出来
但在自制的帧缓冲中无法被渲染
创建帧缓冲时有创建深度 + 模板缓冲对象
且切换帧缓冲时有清理
主循环:

framebuffer->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
framebuffer->engineCamera(deltaTime);
Light::use();
EngineSystem::draw(app->getWorld());


glDepthFunc(GL_LEQUAL);
UseShader::use(Shader_SkyBox);
glm::mat4 view = glm::mat4(glm::mat3(Engine::view));
UseShader::setMat4("view", view);
// skybox cube
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS); 


glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    
framebuffer->update(deltaTime);
Light::use();
EngineSystem::draw(app->getWorld());

模板测试:

if (Engine::selectEntity!= UINT32_MAX) {
     glEnable(GL_STENCIL_TEST); // ステンシルテストを有効に 模板测试
     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
     glStencilFunc(GL_ALWAYS, 1, 0xFF); // 常にパスし、参照値 1 を書き込む
     glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); // パスしたら 1 で置き換える

     ModelComponent* mSelect = world->getEntityComponent<ModelComponent>(Engine::selectEntity);
     TransformComponent* tSelect = world->getEntityComponent<TransformComponent>(Engine::selectEntity);
     if (!mSelect||!tSelect)return;
     Transform tran = tSelect->getTransform();
     glm::mat4 T = glm::translate(glm::mat4(1.0f), tran.position());
     glm::mat4 R = glm::toMat4(tran.rotation());
     glm::mat4 S = glm::scale(glm::mat4(1.0f), tran.lossyScale());

     glm::mat4 model = T * R * S;
     UseShader::setMat4("model", model);
     DrawModle::Draw(mSelect->modelID);
  
    
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     glDepthFunc(GL_ALWAYS);//总是通过深度测试
     glDepthMask(GL_FALSE); // 不写入深度缓冲

     // ステンシルテストを使用して、描画を制限する
     glStencilFunc(GL_NOTEQUAL, 1, 0xFF); // ステンシルバッファが 1 でないピクセルのみ描画
     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // ステンシルバッファの値を変更しない

     UseShader::use(Shader_Collider);

     glm::mat4 modelOutLine = model;
     //计算平均缩放
     glm::vec3 scale;
     scale.x = glm::length(glm::vec3(modelOutLine[0][0], modelOutLine[0][1], modelOutLine[0][2]));
     scale.y = glm::length(glm::vec3(modelOutLine[1][0], modelOutLine[1][1], modelOutLine[1][2]));
     scale.z = glm::length(glm::vec3(modelOutLine[2][0], modelOutLine[2][1], modelOutLine[2][2]));

     float averageScale = (scale.x + scale.y + scale.z) / 3.0f;
     float outlineWidth = 0.02f;
     float scaleFactor = 1.0f + outlineWidth / averageScale;

     modelOutLine = modelOutLine * glm::scale(glm::mat4(1.0f), glm::vec3(scaleFactor));
     UseShader::setMat4("model", modelOutLine);
     DrawModle::Draw(mSelect->modelID);
     UseShader::end();

     glDepthFunc(GL_LESS);
     glDepthMask(GL_TRUE);
     glDisable(GL_STENCIL_TEST);
 }

帧缓冲的创建函数

 // 创建帧缓冲及其附件
 void createFramebuffer() {
     // 创建帧缓冲对象
     glGenFramebuffers(1, &framebuffer);
     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

     // 创建颜色纹理附件
     glGenTextures(1, &texColorBuffer);
     glBindTexture(GL_TEXTURE_2D, texColorBuffer);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::windowWidth, Engine::windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     // 附加颜色纹理
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);

     // 创建深度 + 模板缓冲对象(RBO)
     glGenRenderbuffers(1, &rbo);
     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, Engine::windowWidth, Engine::windowHeight);
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

     // 检查帧缓冲是否完整
     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
         std::cerr << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
     }

     // 解绑
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
```c++


```

  • 写回答

6条回答 默认 最新

  • IT工程师-二师兄 2025-07-27 16:14
    关注

    运行日志有没有,有的话发给我

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 8月4日
  • 已采纳回答 7月27日
  • 创建了问题 7月27日