我正在学习将 C++ 与 OpenGl 结合使用。我试图在帧缓冲区中使用采样,但它只显示场景中模型的纹理。这是我正在关注的教程视频https://www.youtube.com/@VictorGordan/videos。我已经尝试用非采样帧缓冲区中使用的普通纹理代码替换多重采样代码,该代码可以工作并在场景中显示模型及其纹理。
我尝试过的事情
禁用帧缓冲区中与多重采样相关的其他代码部分,会导致同样的问题。
用在非多重采样帧缓冲区中使用的非多重采样代码替换多重采样纹理代码,有效。
如有任何帮助,我们将不胜感激。
这是我的代码:
帧缓冲区类
#include "FrameBuffer.h"
FrameBuffer::FrameBuffer()
{
SetupUnsigned();
framebufferProgram.Activate();
glUniform1i(glGetUniformLocation(framebufferProgram.ID, "screenTexture"), 0);
Vertex();
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
Texture();
Buffer();
}
void FrameBuffer::AddPostProcessor(PostProcessing pp)
{
pp.Setup();
storedPostProcessings.push_back(pp);
}
void FrameBuffer::Bind()
{
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
}
void FrameBuffer::Draw()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, FBO);
for (int i = 0; i < storedPostProcessings.size(); i++)
{
storedPostProcessings[i].DrawOnly();
}
glBlitFramebuffer(0, 0, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), 0, 0, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void FrameBuffer::Activate(vector<PostProcessing>& pp)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
framebufferProgram.Activate();
glBindVertexArray(rectVAO);
glDisable(GL_DEPTH_TEST);
for (int i = 0; i < pp.size(); i++)
{
pp[i].Activate();
}
glDrawArrays(GL_TRIANGLES, 0, 6);
}
void FrameBuffer::Activate()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
framebufferProgram.Activate();
glBindVertexArray(rectVAO);
glDisable(GL_DEPTH_TEST);
for (int i = 0; i < storedPostProcessings.size(); i++)
{
storedPostProcessings[i].Activate();
}
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
void FrameBuffer::SetupUnsigned()
{
FBO = NULL;
RBO = NULL;
rectVAO = NULL;
rectVBO = NULL;
}
void FrameBuffer::Vertex()
{
glGenVertexArrays(1, &rectVAO);
glGenBuffers(1, &rectVBO);
glBindVertexArray(rectVAO);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
if (screenVerticiesCopy.empty())
{
glBufferData(GL_ARRAY_BUFFER, sizeof(originalScreenVerticies), &originalScreenVerticies, GL_STATIC_DRAW);
}
else
{
//https://stackoverflow.com/questions/7173494/vbos-with-stdvector
glBufferData(GL_ARRAY_BUFFER, screenVerticiesCopy.size() * sizeof(screenVerticiesCopy), &screenVerticiesCopy.front(), 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)));
}
void FrameBuffer::Texture()
{
glGenTextures(1, &framebufferTexture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, framebufferTexture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, BuildingBlocksEngineSettings::GetSamples(), GL_RGB, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), GL_TRUE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, framebufferTexture, 0);
/*glGenTextures(1, &framebufferTexture);
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, 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, framebufferTexture, 0);*/
}
void FrameBuffer::Buffer()
{
glGenRenderbuffers(1, &RBO);
glBindRenderbuffer(GL_RENDERBUFFER, RBO);
//glRenderbufferStorageMultisample(GL_RENDERBUFFER, *samples, GL_DEPTH24_STENCIL8, *width, *height);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, BuildingBlocksEngineSettings::GetSamples(), GL_DEPTH24_STENCIL8, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenWidth());
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO);
auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
cout << "Framebuffer error: " << fboStatus << endl;
}
}
主班
#include"ExtensionManager.h"
#include"Model.h"
#include"PostProcessing.h"
#include"CubeMap.h"
#include"FrameBuffer.h"
#include"BuildingBlocksEngineSettings.h"
using namespace std;
using namespace glm;
//Address to new window for project
GLFWwindow* window;
ExtensionManager extManager;
const unsigned int width = 800;
const unsigned int height = 800;
string parentFolder = (filesystem::current_path().filesystem::path::make_preferred()).string();
//How many samples for MSAA
unsigned int samples = 8;
enum PostProcessingMethod
{
Setup,
Bind,
Activate,
ReadOnly,
Draw
};
float rectangleVerticies[] =
{
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
};
array<float, 24> test =
{
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
};
/// <summary>
/// Generates and sets up the window for the project
/// </summary>
void GenerateGLFWWindow()
{
//Initualises the window
glfwInit();
//Tells GLFW the version of OpenGL is being used (V3.3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//MSAA
//Only for non frame buffer projects
//glfwWindowHint(GLFW_SAMPLES, samples);
//Tells GLFW what profile is being used
//Modern = GLFW_OPENGL_CORE_PROFILE
//Modern with backwards compatibility = GLFW_OPENGL_COMPAT_PROFILE
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//Creates the window for the project being 800 by 800 pixels and renaming the window
//window = glfwCreateWindow(width, height, "Video Game Engine Practice", NULL, NULL);
window = glfwCreateWindow(BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), "Video Game Engine Practice", NULL, NULL);
}
void DrawModels(Shader& shader, Camera& cam, vector<Model>& models)
{
for (int i = 0; i < models.size(); i++)
{
models[i].Draw(shader, cam);
}
}
void PostProcessors(vector<PostProcessing>& postProcessings, PostProcessingMethod ppm)
{
for (int i = 0; i < postProcessings.size(); i++)
{
if (ppm == PostProcessingMethod::Setup)
{
//postProcessings[i].Setup(&width, &height, &samples);
//postProcessings[i].Setup(&width, &height);
postProcessings[i].Setup();
}
else if (ppm == PostProcessingMethod::Bind)
{
//postProcessings[i].Bind();
}
else if (ppm == PostProcessingMethod::Activate)
{
postProcessings[i].Activate();
}
else if (ppm == PostProcessingMethod::ReadOnly)
{
//postProcessings[i].ReadOnly();
}
else if (ppm == PostProcessingMethod::Draw)
{
postProcessings[i].DrawOnly();
}
else
{
cout << "Not a command!!!" << endl;
}
}
}
float randf()
{
return -1.0f + (rand() / (RAND_MAX / 2.0f));
}
int main()
{
cout << filesystem::current_path().filesystem::path::make_preferred() << endl;
BuildingBlocksEngineSettings::SetSamples(SampleAmount::X2);
//BuildingBlocksEngineSettings::SetScreenSize(1920, 1080);
//FrameBuffer frameBufferTexture = FrameBuffer();
GenerateGLFWWindow();
//Error checking if the window was not created successfully
if (window == NULL)
{
cout << "Window Generation Failed" << endl;
glfwTerminate();
return -1;
}
//Puts the window into the current context
glfwMakeContextCurrent(window);
//Loads GLAD and configures OpenGL
gladLoadGL();
extManager = ExtensionManager();
extManager.Setup();
//Connects the viewport of OpenGL to window
//glViewport(0, 0, width, height);
glViewport(0, 0, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight());
Shader shaderProgram("default.vert", "default.frag", "default.geom");
//Out lining
Shader outliningProgram("outlining.vert", "outlining.frag");
//Shader asteroidShader("asteroid.vert", "default.frag", "default.geom");
//PostProcessing frameBufferTexture = PostProcessing();
FrameBuffer frameBufferTexture = FrameBuffer();
vector<PostProcessing> postProcessings;
//Post Processing
//postProcessings.push_back(PostProcessing("framebufferTest.frag"));
//frameBufferTexture.AddPostProcessor(PostProcessing("framebufferTest.frag"));
vec4 lightColour = vec4(1.0f, 1.0f, 1.0f, 1.0f);
vec3 lightPos = vec3(0.5f, 0.5f, 0.5f);
//mat4 lightModel = mat4(1.0f);
//lightModel = translate(lightModel, lightPos);
shaderProgram.Activate();
glUniform4f(glGetUniformLocation(shaderProgram.ID, "lightColor"), lightColour.x, lightColour.y, lightColour.z, lightColour.w);
glUniform3f(glGetUniformLocation(shaderProgram.ID, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
glUniform1i(glGetUniformLocation(shaderProgram.ID, "lightNumb"), 1);
/*asteroidShader.Activate();
glUniform4f(glGetUniformLocation(asteroidShader.ID, "lightColor"), lightColour.x, lightColour.y, lightColour.z, lightColour.w);
glUniform3f(glGetUniformLocation(asteroidShader.ID, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
glUniform1i(glGetUniformLocation(asteroidShader.ID, "lightNumb"), 1);*/
CubeMap defualtCubeMap;
//frameBufferTexture.Setup(&width, &height, &samples);
//Post Processing
//PostProcessors(postProcessings, PostProcessingMethod::Setup);
//Enables the depth buffer
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//MSAA
//Only for non frame buffer projects
glEnable(GL_MULTISAMPLE);
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glFrontFace(GL_CCW);
Camera camera(width, height, vec3(0.0f, 0.0f, 2.0f));
vector<Model> models;
//models.push_back(Model("models/Ground/scene.gltf"));
//models.push_back(Model("models/Trees/scene.gltf"));
//models.push_back(Model("models/Bunny/bunny_scene.gltf"));
//models.push_back(Model((parentFolder + "models/Sword/scene.gltf").c_str()));
models.push_back(Model("models/Sword/scene.gltf"));
//models.push_back(Model("Tests/Jupiter/scene.gltf"));
double prevTime = 0.0;
double crntTime = 0.0;
double timeDiff;
unsigned int counter = 0;
//Disables v-sync
//glfwSwapInterval(0);
defualtCubeMap.Setup();
/*const unsigned int asteroidNumber = 5000;
float asteroidRadius = 100.0f;
float asteroidRadiusDeviantion = 25.0f;
vector<mat4> asteroidInstanceMatrix;
for (unsigned int i = 0; i < asteroidNumber; i++)
{
float x = randf();
float finalRadius = asteroidRadius + randf() * asteroidRadiusDeviantion;
float y = ((rand() % 2) * 2 - 1) * sqrt(1.0f - x * x);
vec3 tempTranslation;
quat tempRotation;
vec3 tempScale;
if (randf() > 0.5f)
{
tempTranslation = vec3(y * finalRadius, randf(), x * finalRadius);
}
else
{
tempTranslation = vec3(x * finalRadius, randf(), y * finalRadius);
}
tempRotation = quat(1.0f, randf(), randf(), randf());
tempScale = 0.1f * vec3(randf(), randf(), randf());
mat4 trans = mat4(1.0f);
mat4 rot = mat4(1.0f);
mat4 sca = mat4(1.0f);
trans = translate(trans, tempTranslation);
rot = mat4_cast(tempRotation);
sca = scale(sca, tempScale);
asteroidInstanceMatrix.push_back(trans * rot * sca);
}*/
//Model asteroid = Model("Tests/Asteroid/scene.gltf", asteroidNumber, asteroidInstanceMatrix);
//models.push_back(Model("Tests/Jupiter/scene.gltf"));
//models.push_back(Model("Tests/Asteroid/scene.gltf", asteroidNumber, asteroidInstanceMatrix));
//Waits until the window is closed
while (!glfwWindowShouldClose(window))
{
crntTime = glfwGetTime();
timeDiff = crntTime - prevTime;
counter++;
if (timeDiff >= 1.0f / 30)
{
string FPS = to_string((1.0f / timeDiff) * counter);
string ms = to_string((timeDiff / counter) * 1000);
string newTitle = "Test Game Engine - " + FPS + "FPS / " + ms + "ms";
glfwSetWindowTitle(window, newTitle.c_str());
prevTime = crntTime;
counter = 0;
if (extManager.wglGetSwapIntervalEXT() == 0)
{
camera.Inputs(window);
}
}
//frameBufferTexture.Bind();
//Post Processing
//PostProcessors(postProcessings, PostProcessingMethod::Bind);
frameBufferTexture.Bind();
//Colour of the background
glClearColor(0.07f, 0.13f, 0.17f, 1);
//Clean the back buffer and assigns the new colour to it
//Clears the depth buffer as well
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//defualtCubeMap.Activate(camera, width, height);
//Post Processing
glEnable(GL_DEPTH_TEST);
if (extManager.wglGetSwapIntervalEXT() == 1)
{
camera.Inputs(window);
}
camera.UpdateMatrix(45.0f, 0.1f, 1000.0f);
//Outline
//glStencilFunc(GL_ALWAYS, 1, 0xFF);
//glStencilMask(0xFF);
DrawModels(shaderProgram, camera, models);
//asteroid.Draw(asteroidShader, camera);
//asteroid.Draw(shaderProgram, camera);
//Outline
//glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
//glStencilMask(0x00);
//glDisable(GL_DEPTH_TEST);
//outliningProgram.Activate();
//glUniform1f(glGetUniformLocation(outliningProgram.ID, "outlining"), 0.08f);
//DrawModels(outliningProgram, camera, models);
//Outline
//glStencilMask(0xFF);
//glStencilFunc(GL_ALWAYS, 1, 0xFF);
//Outline
//glEnable(GL_DEPTH_TEST);
frameBufferTexture.Draw();
//PostProcessors(postProcessings, PostProcessingMethod::Draw);
//glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
//glBlitFramebuffer(0, 0, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), 0, 0, BuildingBlocksEngineSettings::ScreenWidth(), BuildingBlocksEngineSettings::ScreenHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
//Post Processing
//PostProcessors(postProcessings, PostProcessingMethod::Activate);
//frameBufferTexture.Activate(postProcessings);
frameBufferTexture.Activate();
//Swap back to front buffer
glfwSwapBuffers(window);
//Looks after the events called from GLFW
glfwPollEvents();
}
shaderProgram.Delete();
defualtCubeMap.Delete();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
如果您使用 C++ 和 OpenGL,并且在帧缓冲区中使用多重采样,但您只看到纹理而不是预期的渲染,则导致此问题的原因可能有多种。以下是一些常见的故障排除步骤,可帮助您诊断和解决问题:
检查多重采样配置:
确保您已在 OpenGL 上下文中正确配置多重采样。创建 OpenGL 上下文时,您需要指定每个像素的样本数。 帧缓冲区设置:
验证您的帧缓冲区设置是否正确以支持多重采样。您需要创建一个多重采样渲染缓冲区或纹理并将其附加到帧缓冲区。 帧缓冲区完整性:
检查您的帧缓冲区是否完整。您可以使用 glCheckFramebufferStatus() 检查其完整性状态。 着色器程序:
确保您的着色器程序设置正确,并且您不会意外丢弃片段着色器中的片段。 纹理绑定:
确保您在 OpenGL 程序中绑定了正确的纹理和采样器。仔细检查纹理单元和活动纹理。 渲染顺序:
考虑渲染对象的顺序。在纹理和后处理效果之前渲染几何体并应用多重采样至关重要。 OpenGL 状态:
检查是否无意中修改了影响渲染的OpenGL状态变量,例如深度测试、模板测试或混合模式。 错误处理:
使用 glGetError() 等 OpenGL 函数实施错误检查以捕获任何运行时错误。 调试工具:
使用 OpenGL 调试器或 GPU 分析器等调试工具来检查渲染管道并识别任何问题。 文档和教程:
请参阅特定于您的 OpenGL 版本和您正在使用的库的官方 OpenGL 文档和教程。通常,可能存在细微的差异或要求。 更新驱动程序:
确保您的图形驱动程序是最新的,因为过时的驱动程序有时会导致渲染问题。 最小可重复示例:
如果问题仍然存在,请考虑创建一个最小的可重现代码示例,并在相关论坛或社区上分享以寻求帮助。 通过系统地审查和验证 OpenGL 代码的这些方面,您可以查明导致渲染缺失的问题并采取适当的纠正措施。