c++ - QtOpenGLWidget 绘制三角形
问题描述
如何更改以下代码以使其实际绘制三角形?
首先是着色器,然后是从QOpenglWidget
.
// shaders here
static const char* vertexShaderSource =
"#version 330 core\n"
"in vec3 posAttr;\n"
//"attribute lowp vec3 colAttr;\n"
//"varying lowp vec4 col;\n"
//"uniform highp mat4 matrix;\n"
"void main() {\n"
//" col = colAttr;\n"
" gl_Position = vec4(posAttr, 1) ;\n"
"}\n";
// fragment shader
static const char* fragmentShaderSource =
"#version 330 core\n"
//"varying lowp vec4 col;\n"
"void main() {\n"
"gl_FragColor = vec4(1.0, 0.0, 1.0, 0.0);\n"
"}\n";
Glwidget::Glwidget(QWidget* parent):QOpenGLWidget(parent)
{
//
}
Glwidget::~Glwidget()
{
cleanup();
}
void Glwidget::initializeGL()
{
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &Glwidget::cleanup);
initializeOpenGLFunctions();
glClearColor(.0f, .0f, .0f, 1.0f);
shader = new QOpenGLShaderProgram(this);
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
// posAttribute = shader->attributeLocation("posAttr");
//colAttribute = shader->attributeLocation("colAttr");
//matrixAttribute = shader->uniformLocation("matrix");
Q_ASSERT(shader->link());
Q_ASSERT(shader->bind());
//shader->release();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
void Glwidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
makeCurrent();
matrix.perspective(60.0, 4.0f/3.0f, 0.1f, 10.0f);
matrix.translate(0, 0, -2);
matrix.rotate(100.0f, 0, 1, 0);
//shader->setUniformValue(matrixAttribute, matrix);
// shader->bind();
GLfloat vertices[] = {
0.0f, 0.707f, 1.0f,
-0.5f, -0.5f, 1.0f,
0.5f, -0.5f, 1.0f
};
shader->setAttributeArray(posAttribute,vertices, 3);
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
glVertexAttribPointer(posAttribute, 3, GL_FLOAT, GL_FALSE, 0, vertices);
//glVertexAttribPointer(colAttribute, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(posAttribute);
//glEnableVertexAttribArray(colAttribute);
glDrawArrays(GL_TRIANGLES, 0, 1);
glDisableVertexAttribArray(posAttribute);
//glDisableVertexAttribArray(colAttribute);
//shader->release();
}
void Glwidget::resizeGL(int w, int h)
{
matrix.setToIdentity();
matrix.perspective(45.0f, w / float(h), 0.01f, 1000.0f);
//glViewport(0, 0, w, h);
}
void Glwidget::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
}
void Glwidget::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event);
}
void Glwidget::cleanup()
{
if (shader == nullptr)
return;
makeCurrent();
delete shader;
shader = 0;
doneCurrent();
}
解决方案
posAttr
程序链接后,您必须确定 的属性索引:
Q_ASSERT(shader->link());
posAttribute = shader->attributeLocation("posAttr");
由于启用了深度测试,您必须清除深度缓冲区。见glClear
:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
您不使用任何模型、视图或投影矩阵,因此必须在标准化设备空间中设置坐标。这意味着所有坐标都必须在 [-1.0, 1.0] 范围内,尤其是 -1.0 和 1.0 的近平面和远平面必须考虑。默认情况下,深度测试函数是GL_LESS
,所以你的三角形被远平面裁剪,因为 1.0 的 z 坐标不小于 1.0 的远平面。使用 0.0 的 az 坐标作为顶点(当然也可以使用 0.99 之类的东西):
GLfloat vertices[] = { 0.0f, 0.707f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f };
shader->setAttributeArray(posAttribute,vertices, 3);
的 3d 参数glDrawArrays
必须是顶点的数量而不是图元的数量:
glDrawArrays(GL_TRIANGLES, 0, 3);
相关的代码部分可能如下所示:
void Glwidget::initializeGL()
{
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &Glwidget::cleanup);
initializeOpenGLFunctions();
glClearColor(.0f, .0f, .0f, 1.0f);
shader = new QOpenGLShaderProgram(this);
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
Q_ASSERT(shader->link());
posAttribute = shader->attributeLocation("posAttr");
Q_ASSERT(shader->bind());
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
void Glwidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat vertices[] = { 0.0f, 0.707f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f };
shader->setAttributeArray(posAttribute,vertices, 3);
glEnableVertexAttribArray(posAttribute);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(posAttribute);
}
请注意,由于启用了面剔除,因此您必须尊重基元的缠绕顺序(在您的代码中就是这种情况)。
此外,正如@derhass 所提到的,在评论中,您必须更改片段着色器。您必须定义一个输出变量。
(旁注,使用原始字符串文字):
static const char* fragmentShaderSource = R"(
#version 330 core
out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.0, 1.0, 0.0);
}
)";
查看预览:
如果要绘制线条而不是多边形,则可以通过GL_LINE_LOOP
. 请参阅线原语。
glDrawArrays(GL_LINE_LOOP, 0, 3);
推荐阅读
- c++ - c++中指针的类型是如何实现的?
- django - 如何在 Django 的 change_password 中显示错误消息
- java - RuntimeException:com.android.builder.dexing.DexArchiveMergerException:无法合并 dex
- angular - 如何将模板从一个组件传递到另一个组件
- python - 如何获取当前shell并在其中执行命令?
- android - ToolbarAndroid navIcon 不显示
- fiware-orion - Fiware Orion CB 订阅限制
- jquery - 使html页面内容的高度与iframe的高度一起调整
- android - 如果空间可用,在另一个水平对齐的视图下方展开多行文本视图的宽度
- java - 为什么 RecycleView 中的水平项在单击时不起作用?