Directx--绘制六边形(图元类型)

准备阶段:

流程如下:

 设备创建准备条件阶段:

ComPtr<ID3DBlob> blob;
	//创建顶点着色器
	HR(CreateShaderFromFile(L"HLSL\\VS_Hexagon.cso", L"HLSL\\VS_Hexagon.hlsl", "VS", "vs_5_0", blob.ReleaseAndGetAddressOf()));
	m_pDevice->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, m_pVertexShader.GetAddressOf());
	//创建输入布局
	m_pDevice->CreateInputLayout(VertexPosColor::inputLayout, ARRAYSIZE(VertexPosColor::inputLayout),
		blob->GetBufferPointer(), blob->GetBufferSize(), m_pVertexLayout.GetAddressOf());
	//创建像素着色器
	CreateShaderFromFile(L"HLSL\\PS_Hexagon.cso", L"HLSL\\PS_Hexagon.hlsl", "PS", "ps_5_0", blob.ReleaseAndGetAddressOf());
	m_pDevice->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, m_pPixelShader.GetAddressOf());

    //描述顶点描述区
    D3D11_BUFFER_DESC vbd;
	ZeroMemory(&vbd, sizeof(vbd));
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof vertices;
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	//顶点缓冲区数据来源
	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = vertices;
	m_pDevice->CreateBuffer(&vbd, &InitData, m_pVertexBuffer.GetAddressOf());

绑定设备上下文阶段:

UINT stride = sizeof(VertexPosColor);	// 跨越字节数
	UINT offset = 0;						// 起始偏移量

	//绑定着色器
	m_pContext->VSSetShader(m_pVertexShader.Get(), nullptr, 0);
	m_pContext->PSSetShader(m_pPixelShader.Get(), nullptr, 0);
	//设置图元类型
	m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	//设置输入布局
	m_pContext->IASetInputLayout(m_pVertexLayout.Get());
	//绑定顶点缓冲区
	m_pContext->IASetVertexBuffers(0, 1, m_pVertexBuffer.GetAddressOf(), &stride, &offset);

图元类型:

DirectX11中有多种图元类型,以下图片容易理解图元类型是什么:

 无论是最为简单的一维图形还愈加复杂的多维图形,都有点、线、面构成,有了图元,我们就可以通过点、线、三角形以及多边形构成多元的图像了。

以下是一些dx11中可调用的图元类型以及含义:

图元类型含义
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST按一系列点进行装配
D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP按一系列线段进行装配,每相邻两个顶点(或索引数组相邻的两个索引对应的顶点)构成一条线段
D3D11_PRIMITIVE_TOPOLOGY_LINELIST按一系列线段进行装配,每两个顶点(或索引数组每两个索引对应的顶点)构成一条线段
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP按一系列三角形进行装配,每相邻三个顶点(或索引数组相邻的三个索引对应的顶点)构成一个三角形
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST按一系列三角形进行装配,每三个顶点(或索引数组每三个索引对应的顶点)构成一个三角形
D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ每4个顶点为一组,只绘制第2个顶点与第3个顶点的连线(或索引数组每4个索引为一组,只绘制索引模4余数为2和3的连线)
D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ绘制除了最开始和结尾的所有线段(或者索引数组不绘制索引0和1的连线,以及n-2和n-1的连线)
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ每6个顶点为一组,只绘制第1、3、5个顶点构成的三角形(或索引数组每6个索引为一组,只绘制索引模6余数为0, 2, 4的三角形)
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ抛弃所有索引模2为奇数的顶点或索引,剩余的进行Triangle Strip的绘制

第一种绘制方式(按图元类型TRIANGLESTRIP):

设置绘制顶点数:

设置顶点:

 设置图元类型:

第二种绘制方式(按图元类型TRIANGLELIST):

设置绘制顶点数:

设置顶点: 

设置图元类型:

效果图:

 总结:

当我们用TRIANGLESTRIP图元类型的时候,我们需要6个顶点绘制正六边形,而用TRIANGLELIST图元类型的时候,则需要绘制12个顶点。

因为TRIANGLESTRIP每三个顶点组成三角形后,下一个三角形可以利用前两个顶然后再加上一个顶点就可以绘制另一个三角形了,也就是说,我们可以绘制4个顶点绘制两个三角形。

而TRIANGLELIST图元类型则需要每三个顶点创建一个三角形,就算你绘制了4个顶点,也就可以绘制一个三角形而已。不用说,因为4小于6,而2个三角形需要6个顶点,三个三角形需要12个顶点——

备注:

顶点的创建必须从顺时针创建。

一般情况下,三角形顶点从顺时针创建,是面向摄像机的。三角形顶点从逆时针排布则说明当前三角形的面向摄像机。对于背向摄像机的三角形会被剔除,不进行光栅化操作。这种做法叫背面消隐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例,演示如何在Qt中使用鼠标绘制直线图: ```cpp #include <QtGui> #include <Widgets> class Line : public QGraphicsLineItem { public: Line(const QLineF& line) : QGraphicsLineItem(line) {} QRectF boundingRect() const override { return pen().widthF() + 20.0 + QGraphicsLineItem::boundingRect(); } QPainterPath shape() const override { QPainterPath path = QGraphicsLineItem::shape(); path.addRect(boundingRect()); return path; } void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override { if (option->state & QStyle::State_Selected) { painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine)); painter->drawRect(boundingRect()); } QGraphicsLineItem::paint(painter, option, widget); } }; class GraphicsView : public QGraphicsView { public: GraphicsView(QWidget* parent = nullptr) : QGraphicsView(parent), m_isDrawing(false), m_line(nullptr) { setRenderHint(QPainter::Antialiasing); setDragMode(QGraphicsView::RubberBandDrag); setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing); setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); setSelectionMode(QGraphicsView::SingleSelection); } protected: void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { m_startPos = mapToScene(event->pos()); m_isDrawing = true; } QGraphicsView::mousePressEvent(event); } void mouseMoveEvent(QMouseEvent* event) override { if (m_isDrawing) { if (!m_line) { m_line = new Line(QLineF(m_startPos, mapToScene(event->pos()))); scene()->addItem(m_line); } else { m_line->setLine(QLineF(m_startPos, mapToScene(event->pos()))); } } QGraphicsView::mouseMoveEvent(event); } void mouseReleaseEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton && m_isDrawing) { m_isDrawing = false; m_line = nullptr; } QGraphicsView::mouseReleaseEvent(event); } private: bool m_isDrawing; QPointF m_startPos; Line* m_line; }; int main(int argc, char* argv[]) { QApplication app(argc, argv); QGraphicsScene scene; GraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setScene(&scene); view.setDragMode(QGraphicsView::RubberBandDrag); QGraphicsLineItem* line = new QGraphicsLineItem(QLineF(0.0, 0.0, 100.0, 100.0)); line->setPen(QPen(Qt::red, 2)); scene.addItem(line); QGraphicsEllipseItem* ellipse = new QGraphicsEllipseItem(QRectF(0.0, 0.0, 100.0, 100.0)); ellipse->setPen(QPen(Qt::blue, 2)); ellipse->setBrush(QBrush(Qt::green)); scene.addItem(ellipse); view.setSceneRect(-150, -150, 300, 300); view.setFixedSize(300, 300); view.show(); return app.exec(); } ``` 该示例演示了如何使用QGraphicsView和QGraphicsScene来绘制直线。在鼠标按下时,记录起始位置,并在鼠标移动时绘制直线。在鼠标释放时,停止绘制。该示例还演示了如何添加其他类型图元,如椭圆和直线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值