OpenGL 计算细节层次
OpenGL compute level of detail
我尝试将一些线条渲染到纹理,然后对它们进行 mipmap。但是当我缩小整个事情时,它并没有我想要的那么详细。如何获得较低的纹理分辨率?我尝试了一个稍微弯曲的三角形。所以当我缩小 50% 时,它看起来应该像一个普通的三角形。有没有办法像这样渲染它?由于我对 OpenGL 的经验非常少,我将 post 给你完整的代码。
版本:
极光 2.1.0
OpenGL 4.6
代码:
SDL_Window* window;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow("BA", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
std::vector<Vertex> vertices;
vertices.push_back(Vertex{ -0.5f,-0.5f });
vertices.push_back(Vertex{ 0.0f,0.8f });
vertices.push_back(Vertex{ 0.0f,0.8f });
vertices.push_back(Vertex{ 0.0f,0.5f });
vertices.push_back(Vertex{ 0.0f,0.5f });
vertices.push_back(Vertex{ 0.5f, -0.5f });
vertices.push_back(Vertex{ 0.5f, -0.5f });
vertices.push_back(Vertex{ -0.5f,-0.5f });
GLenum err = glewInit();
//Framebuffer
GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
//Texture
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
/*glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);*/
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glViewport(0, 0, 1920, 1080);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(struct Vertex, x));
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, 1920, 1080);
glScalef(0.9f, 0.9f, 1.0f);
glTranslatef(1.0f, 1.0f, 0.0f);
bool closeFlag = false;
while (!closeFlag) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_LINES, 0, vertices.size());
SDL_GL_SwapWindow(window);
/*GLenum error = glGetError();
std::cout << "Error: " << error;*/
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
closeFlag = true;
}
if (event.key.keysym.sym == SDLK_DOWN) {
glScalef(0.95f, 0.95f, 1.0f);
}
if (event.key.keysym.sym == SDLK_UP) {
glScalef(1.05f, 1.05f, 1.0f);
}
}
}
输出:
Actual Output
期望的输出:
Desired output
首先阅读 glGenerateMipmap 的描述。
为了更深入地了解 mipmapping 及其实现方式:OpenGl Specification 8.14.3 Mipmapping
为了达到(看到)您想要的结果,您将不得不进一步缩小。顺便说一下,可能会出现缩小图像,这是您所期望的。
纹理过滤的微调可以通过 glTexParameter 和不同的参数来完成,例如:
- GL_TEXTURE_BASE_LEVEL
- GL_TEXTURE_LOD_BIAS
- GL_TEXTURE_MIN_FILTER
- GL_TEXTURE_MAG_FILTER
- GL_TEXTURE_MIN_LOD
- GL_TEXTURE_MAX_LOD
- GL_TEXTURE_MAX_LEVEL
您也可以通过 glTexStorage2D and glTexSubImage2D but this requires two texture objects and multiple render steps (render reduced image into texture A, upload into specific level of texture B; see also glCopyTexImage2D, glCopyTexSubImage2D).
自己生成 mipmap
您还可以进行几何 LOD(更多 here)。
我尝试将一些线条渲染到纹理,然后对它们进行 mipmap。但是当我缩小整个事情时,它并没有我想要的那么详细。如何获得较低的纹理分辨率?我尝试了一个稍微弯曲的三角形。所以当我缩小 50% 时,它看起来应该像一个普通的三角形。有没有办法像这样渲染它?由于我对 OpenGL 的经验非常少,我将 post 给你完整的代码。 版本: 极光 2.1.0 OpenGL 4.6
代码:
SDL_Window* window;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow("BA", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
std::vector<Vertex> vertices;
vertices.push_back(Vertex{ -0.5f,-0.5f });
vertices.push_back(Vertex{ 0.0f,0.8f });
vertices.push_back(Vertex{ 0.0f,0.8f });
vertices.push_back(Vertex{ 0.0f,0.5f });
vertices.push_back(Vertex{ 0.0f,0.5f });
vertices.push_back(Vertex{ 0.5f, -0.5f });
vertices.push_back(Vertex{ 0.5f, -0.5f });
vertices.push_back(Vertex{ -0.5f,-0.5f });
GLenum err = glewInit();
//Framebuffer
GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
//Texture
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
/*glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);*/
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glViewport(0, 0, 1920, 1080);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(struct Vertex, x));
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, 1920, 1080);
glScalef(0.9f, 0.9f, 1.0f);
glTranslatef(1.0f, 1.0f, 0.0f);
bool closeFlag = false;
while (!closeFlag) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_LINES, 0, vertices.size());
SDL_GL_SwapWindow(window);
/*GLenum error = glGetError();
std::cout << "Error: " << error;*/
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
closeFlag = true;
}
if (event.key.keysym.sym == SDLK_DOWN) {
glScalef(0.95f, 0.95f, 1.0f);
}
if (event.key.keysym.sym == SDLK_UP) {
glScalef(1.05f, 1.05f, 1.0f);
}
}
}
输出: Actual Output
期望的输出: Desired output
首先阅读 glGenerateMipmap 的描述。
为了更深入地了解 mipmapping 及其实现方式:OpenGl Specification 8.14.3 Mipmapping
为了达到(看到)您想要的结果,您将不得不进一步缩小。顺便说一下,可能会出现缩小图像,这是您所期望的。
纹理过滤的微调可以通过 glTexParameter 和不同的参数来完成,例如:
- GL_TEXTURE_BASE_LEVEL
- GL_TEXTURE_LOD_BIAS
- GL_TEXTURE_MIN_FILTER
- GL_TEXTURE_MAG_FILTER
- GL_TEXTURE_MIN_LOD
- GL_TEXTURE_MAX_LOD
- GL_TEXTURE_MAX_LEVEL
您也可以通过 glTexStorage2D and glTexSubImage2D but this requires two texture objects and multiple render steps (render reduced image into texture A, upload into specific level of texture B; see also glCopyTexImage2D, glCopyTexSubImage2D).
自己生成 mipmap您还可以进行几何 LOD(更多 here)。