在 OpenGL 中的 2D 纹理顶部渲染一个带轮廓的红色矩形

2022-01-12 00:00:00 opengl rectangles textures mfc texture2d

我已经搜索了很多这个网站,但无法准确找到我的问题.大多数类似的问题都使用了控制台和 glut 库.但是由于我是 OpenGL 和 MFC 的新手,并且开始使用 MFC 的组合,所以他们帮不了我很多.

I have searched alot this site but couldn't exactly find what is exactly my problem. Most of the similar problems had used console and the glut library. But since I'm new to OpenGL and MFC and started it with the combination of MFC, they couldn't help me alot.

我正在自定义类 COpenGLcontrol 在 codeguru 中用于我自己的目的.这里是完整的自定义类 但是如果你没有兴趣下载它,没问题我会解释相关的部分.这可能需要一段时间,所以我希望你能耐心等待!

I'm customizing the class COpenGLcontrol here in codeguru for my own purposes. Here's the full customized class but if you're not interested in downloading it, no problem I will explain the parts that are related. This may take a while, so I hope you will be patient!

首先我应该告诉你,我绘制这样一个矩形的目标是,我想在我的程序中创建该类的两个实例.
在较小的窗口中,图像始终处于 zoom extent 模式,但在较大的窗口中,用户可以执行不同的导航任务.因此,例如每次在较大实例的 OnDraw 函数中平移或缩放图像时,都会计算范围矩形并将其传递给较小的窗口并在那里绘制到显示我们在如此大的图像中的整体位置

First of all I should tell you that my goal of drawing such a rectangle is that, I want to create two instances of the class in my program.
in the smaller window the image would always be in the zoom extent mode but in the bigger one, the user has the ability to do different navigation tasks. So each time that for example the image is panned or zoomed in the OnDraw function of the bigger instance the extent rectangle will be computed and passed to the smaller window and drawn there to show that where we are on the whole of such a big image

我已按照以下步骤操作:
修改投影矩阵堆栈并模拟2D场景

I have followed these steps:
Modyifying the projection matrix stack and simulating a 2D scene

void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
wglMakeCurrent(hdc, hrc);
CWnd::OnSize(nType, cx, cy);

if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;
oglWindowWidth = cx;
oglWindowHeight = cy;
// Map the OpenGL coordinates.
glViewport(0, 0, oglWindowWidth, oglWindowHeight);

// Projection view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set our current view perspective
glOrtho(-oglWindowWidth/2, oglWindowWidth/2, -oglWindowHeight/2,oglWindowHeight/2, 1, -1);
// Model view
glMatrixMode(GL_MODELVIEW);
wglMakeCurrent(NULL, NULL);
}  

修改modelview矩阵栈和设置camera(好像我们在看z轴的负方向)

void COpenGLControl::OnDraw(CDC *pDC)
{
// TODO: Camera controls
wglMakeCurrent(hdc,hrc);
glLoadIdentity();
gluLookAt(0,0,1,0,0,0,0,1,0);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glScalef(m_fZoom,m_fZoom,1.0);
setViewRectangle();
if (WantToDrawRectangle)
    DrawRectangleOnTopOfTexture();
wglMakeCurrent(NULL, NULL);
}  

setViewRectangle() 用于计算 vectorViewRectangle 类的公共成员数据之一,如果用户需要,vector<;int>RectangleToDraw 其他公共成员数据将用于绘制矩形.这是因为我们不希望在大窗口中绘制这样的矩形,但在较小的窗口中我们会这样做.而较小的将使用较大的数据.但我还没有实现如何在一个类的两个实例之间实时传递这些数据!
因此,在尝试上课时,我将 RectangleToDraw 的初始值设置如下,并且由于窗口是 [0,0,573,543] 设置的 glOrtho,我认为应该在纹理顶部的中心绘制矩形.但事实并非如此.
反正
应用将在 OnTimer 中调用的纹理的代码

the line setViewRectangle() is for computing vector<int>ViewRectangle one of the public member datas of the class and if the user wants, the vector<int>RectangleToDraw other public member-data will be used to draw the rectangle. This is because we don't want in the big window to draw such a rectangle but in the smaller we do. And the smaller will use the data of the bigger.But I haven't still implemented how to pass these data real-time between two instances of a class!
So at time just for trying out the class, I have set the initial value of RectangleToDraw as follows and since the window is a [0,0,573,543] setted by glOrtho, I think the rectangle should be drawn in center, at top of the texture. But this is not the case.
anyway
Code to apply the texture that will be called in the OnTimer

void COpenGLControl::oglDrawScene(void)
{
wglMakeCurrent(hdc, hrc);
float x0 = -ImageWidth/2; // top left corner of image
float y0 = ImageHeight/2;
float x1 = x0 + ImageWidth; // bottom right corner of image
float y1 = y0 - ImageHeight;

glBegin(GL_TRIANGLE_STRIP);
{
    glTexCoord2f(0,1);glVertex2f(x0, y1);
    glTexCoord2f(0,0);glVertex2f(x0, y0);
    glTexCoord2f(1,1);glVertex2f(x1, y1);
    glTexCoord2f(1,0);glVertex2f(x1, y0);
}
glEnd();
wglMakeCurrent(NULL, NULL);
}  

计算 ViewRectangle 的代码将传递给该类的另一个实例

Code to compute ViewRectangle that will be passed to another instance of the class

void COpenGLControl::setViewRectangle()
{
ViewRectangle.at(0) = m_fPosX - oglWindowWidth*m_fZoomInverse/2;
ViewRectangle.at(1) = m_fPosY - oglWindowHeight*m_fZoomInverse/2;
ViewRectangle.at(2) = m_fPosX + oglWindowWidth*m_fZoomInverse/2;
ViewRectangle.at(3) = m_fPosY + oglWindowHeight*m_fZoomInverse/2;
}  

在纹理顶部绘制矩形的代码

void COpenGLControl::DrawRectangleOnTopOfTexture()
{
wglMakeCurrent(hdc, hrc);
glColor3f(1.0f,0.0f,0.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUADS);
   glVertex3f(RectangleToDraw.at(0),RectangleToDraw.at(1),0.5);
   glVertex3f(RectangleToDraw.at(0),RectangleToDraw.at(3),0.5);
   glVertex3f(RectangleToDraw.at(2),RectangleToDraw.at(3),0.5);
   glVertex3f(RectangleToDraw.at(2),RectangleToDraw.at(1),0.5);
glEnd();
SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL);
}  

即使在上述函数中使用 glVertex2f 也没有任何区别,在这两种情况下,我都会遇到:

不要混淆.两个窗口都画错的原因是我在构造函数中设置的:

even using glVertex2f in the above function does not make any difference and in both circumstances, I encounter:

Don't get confused. The reason that the wrong drawing is applied on both windows, is that I have set in the constructor:

WantToDrawRectangle = true;  
RectangleToDraw.at(0) = -100;
RectangleToDraw.at(1) = -100;
RectangleToDraw.at(2) = 100;
RectangleToDraw.at(3) = 100;  

只是为了尝试如何在纹理上绘制一个矩形.当然,在编写正确的代码后,我会将它们设置为 true 模式.告诉我吧

just for trying out how to draw a rectangle on top of a texture. Surely after writing the correct code, I will set them to the true mode. Just tell me

如何以需要实时渲染的面向对象的方式在纹理顶部绘制矩形?

推荐答案

由于现代 OpenGL 不推荐使用 edge flags,我会避免使用多边形填充模式来绘制轮廓.如果我正确理解您的屏幕截图,您会在用于绘制矩形的两个三角形的内部边缘上得到线条.

Since edge flags are deprecated in modern OpenGL, I would avoid using a polygon fill mode to draw the outlines. If I understand your screenshot correctly, you are getting lines on the interior edges of the two triangles used to draw your rectangle.

改为使用矩形的 4 个角绘制一个红色的 GL_LINE_LOOP...这是出于便携性原因的首选技术,因为 GL_QUADS 也已被弃用.p>

Instead draw a red GL_LINE_LOOP that uses the 4 corners of your rectangle... this is the preferred technique for portability reasons, since GL_QUADS are also deprecated.

glColor3f     (1.0f, 0.0f, 0.0f);
glBegin       (GL_LINE_LOOP);
   glVertex3f (RectangleToDraw.at (0), RectangleToDraw.at (1), -1.0f);
   glVertex3f (RectangleToDraw.at (0), RectangleToDraw.at (3), -1.0f);
   glVertex3f (RectangleToDraw.at (2), RectangleToDraw.at (3), -1.0f);
   glVertex3f (RectangleToDraw.at (2), RectangleToDraw.at (1), -1.0f);
glEnd         ();

此外,您的屏幕截图似乎因尝试对轮廓进行纹理处理而受到影响.在画线之前禁用 GL_TEXTURE_2D.

Also, your screenshot appears to be suffering from attempting to texture the outline. Disable GL_TEXTURE_2D before you draw your lines.

相关文章