OpenGL,渲染纹理上的异常伪影,渲染坐标?
OpenGL, unusual artifacts on rendered texture, render co-ordinates?
我正在尝试渲染一个简单的四边形以完美覆盖屏幕(一对一复制)。我用来渲染的纹理是使用帧缓冲区和 glGetTexImage
从之前的渲染中捕获的。这部分我很好。然而,当我再次加载并显示纹理时,我在渲染(左上角)中得到了一些奇怪的伪影,到目前为止我一直无法摆脱它们。
为了比较,这是目前的样子:
它应该是这样的:
这可能是由于纹理坐标、屏幕坐标引起的,但到目前为止我尝试的所有方法都失败了。我应该 change/do 有什么不同?
渲染代码如下。
void setWidthHeightRender(GLsizei width, GLsizei height) {
if(height == 0)
height = 1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
unsigned createGLTexture(unsigned width, unsigned height, const uint8_t* data) {
// the texture we're going to render
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
// bind the newly created texture
glBindTexture(GL_TEXTURE_2D, renderedTexture);
// give the image to opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
glBindTexture(GL_TEXTURE_2D, 0);
return renderedTexture;
}
void drawImage(unsigned glTxt, float tx, float ty, float bx, float by, float z) {
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, glTxt);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 1);
glVertex3f(tx, ty, z);
glTexCoord2f(0, 0);
glVertex3f(tx, by, z);
glTexCoord2f(1, 0);
glVertex3f(bx, by, z);
glTexCoord2f(1, 1);
glVertex3f(bx, ty, z);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
//...
wglMakeCurrent(it->second->hDC, it->second->hRC);
//create the texture + load the texture
unsigned glTxt = createGLTexture((right - left), (bottom - top), &bfr[0]);
//render the texture to the correct screen positions
setWidthHeightRender((right - left), (bottom - top));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawImage(glTxt, 0.0, 0.0, (right - left), (bottom - top), 0.0f);
//swap the buffers
SwapBuffers(it->second->hDC);
//unload the texture
glDeleteTextures(1, &glTxt);
//...
我找到了答案,原来是我从 windows 获得的 window 宽度和高度有问题。
我使用宽度和高度设置 window 大小,我也使用 glTexImage2D
获取纹理。
SetWindowPos(glWindow->hWnd, 0,
0, 0, glWindow->width, glWindow->height,
SWP_NOMOVE | SWP_NOZORDER);
但是这会设置 window 大小,我需要设置的是客户区大小,因为这是通过调用 glTexImage2D
收到的大小。要设置客户区大小,您应该使用:
RECT Rect;
Rect.left = (long)glWindow->x_pos; // Set Left Value To x_pos
Rect.right = (long)glWindow->x_pos+glWindow->width; // Set Right Value To x_pos+width
Rect.top = (long)glWindow->y_pos; // Set Top Value To y_pos
Rect.bottom = (long)glWindow->y_pos+glWindow->height; // Set Bottom Value To y_pos+height
AdjustWindowRectEx(&Rect, glWindow->dwStyle, FALSE, glWindow->dwExStyle);
SetWindowPos(glWindow->hWnd, 0,
0, 0, Rect.right-Rect.left, Rect.bottom-Rect.top,
SWP_NOMOVE | SWP_NOZORDER);
//...
//bind the texture for modification
glBindTexture(GL_TEXTURE_2D, glWindow->renderedTexture);
//Now correct width and height used here (and else where) matching client area.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glWindow->width, glWindow->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//...
我正在尝试渲染一个简单的四边形以完美覆盖屏幕(一对一复制)。我用来渲染的纹理是使用帧缓冲区和 glGetTexImage
从之前的渲染中捕获的。这部分我很好。然而,当我再次加载并显示纹理时,我在渲染(左上角)中得到了一些奇怪的伪影,到目前为止我一直无法摆脱它们。
为了比较,这是目前的样子:
它应该是这样的:
这可能是由于纹理坐标、屏幕坐标引起的,但到目前为止我尝试的所有方法都失败了。我应该 change/do 有什么不同?
渲染代码如下。
void setWidthHeightRender(GLsizei width, GLsizei height) {
if(height == 0)
height = 1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
unsigned createGLTexture(unsigned width, unsigned height, const uint8_t* data) {
// the texture we're going to render
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
// bind the newly created texture
glBindTexture(GL_TEXTURE_2D, renderedTexture);
// give the image to opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
glBindTexture(GL_TEXTURE_2D, 0);
return renderedTexture;
}
void drawImage(unsigned glTxt, float tx, float ty, float bx, float by, float z) {
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, glTxt);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 1);
glVertex3f(tx, ty, z);
glTexCoord2f(0, 0);
glVertex3f(tx, by, z);
glTexCoord2f(1, 0);
glVertex3f(bx, by, z);
glTexCoord2f(1, 1);
glVertex3f(bx, ty, z);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
//...
wglMakeCurrent(it->second->hDC, it->second->hRC);
//create the texture + load the texture
unsigned glTxt = createGLTexture((right - left), (bottom - top), &bfr[0]);
//render the texture to the correct screen positions
setWidthHeightRender((right - left), (bottom - top));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawImage(glTxt, 0.0, 0.0, (right - left), (bottom - top), 0.0f);
//swap the buffers
SwapBuffers(it->second->hDC);
//unload the texture
glDeleteTextures(1, &glTxt);
//...
我找到了答案,原来是我从 windows 获得的 window 宽度和高度有问题。
我使用宽度和高度设置 window 大小,我也使用 glTexImage2D
获取纹理。
SetWindowPos(glWindow->hWnd, 0,
0, 0, glWindow->width, glWindow->height,
SWP_NOMOVE | SWP_NOZORDER);
但是这会设置 window 大小,我需要设置的是客户区大小,因为这是通过调用 glTexImage2D
收到的大小。要设置客户区大小,您应该使用:
RECT Rect;
Rect.left = (long)glWindow->x_pos; // Set Left Value To x_pos
Rect.right = (long)glWindow->x_pos+glWindow->width; // Set Right Value To x_pos+width
Rect.top = (long)glWindow->y_pos; // Set Top Value To y_pos
Rect.bottom = (long)glWindow->y_pos+glWindow->height; // Set Bottom Value To y_pos+height
AdjustWindowRectEx(&Rect, glWindow->dwStyle, FALSE, glWindow->dwExStyle);
SetWindowPos(glWindow->hWnd, 0,
0, 0, Rect.right-Rect.left, Rect.bottom-Rect.top,
SWP_NOMOVE | SWP_NOZORDER);
//...
//bind the texture for modification
glBindTexture(GL_TEXTURE_2D, glWindow->renderedTexture);
//Now correct width and height used here (and else where) matching client area.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glWindow->width, glWindow->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//...