码迷,mamicode.com
首页 > 其他好文 > 详细

初学DirectX11, 留个纪恋。

时间:2016-08-15 06:37:11      阅读:588      评论:0      收藏:0      [点我收藏+]

标签:

  以前学的是openGL, 最近才开始学DirectX11,写了个很垃圾的代码,怀念以前的glPushMatrix(), glPopMatrix(), glBegin(), glEnd(), 多简单啊,可惜在openGL4后面的版本中放弃了这些经典的函数,改成了跟directX差不多的自定义管线, 我觉得openGL已经被改的面目全非了,可能是openGL慢的缘故吧。openGL4.3的VAO,VBO还是不能理解。  

      写了个垃圾的程序,许多个几何体,自己写函数实现了以前glPushMatrix(),glPopMatrix()的功能。界面还是Qt写的,毕竟方便,调用API函数代码量太大。DirectX的代码真多啊,以后分装成一个类库试试。

     贴一下主要的代码吧。

 

技术分享

几何体顶点过多变成球的时候,运行很卡,我的代码效率海水很差啊。

 

#ifndef DWIDGET_H
#define DWIDGET_H
#include "xBasic.h"
#include <d3d11.h>
#include <DirectXMath.h>
#include "DPainter.h"
#include <QWidget>
#include <stack>

class DPainter;

class DWidget : public QWidget
{
    Q_OBJECT

public:
    DWidget(QWidget *parent = nullptr);
    ~DWidget();
    void rotateX();
    void rotateY();
    void rotateZ();

protected:
    virtual void paintEvent(QPaintEvent *event);
    virtual void resizeEvent(QResizeEvent *event);
    void mousePressEvent(QMouseEvent *event);
    virtual QPaintEngine *paintEngine() const { return nullptr; }

private:
    void updateWVP();
    void initializeD3D();   
    void pushWorldMatrix();
    void multipyWorldMatrix(DirectX::XMMATRIX *matrix);
    void popWorldMatrix();
    void worldMatrixIdentity();
    void setCurrentWorldMatrix(DirectX::XMMATRIX *matrix);

    std::stack<XMFLOAT4X4> worldStack;
    DPainter *d3dPainter;
    HWND hwnd;
    
    ID3D11Device *device;
    ID3D11DeviceContext *context;
    IDXGISwapChain *swapChain;
    ID3D11RenderTargetView *renderTargetView;
    ID3D11VertexShader *VS;
    ID3D11PixelShader *PS;
    ID3D10Blob *VS_Buffer;
    ID3D10Blob *PS_Buffer;
    ID3D11Buffer *constantBuffer;
    ID3D11InputLayout *vertexLayout;
    ID3D11Buffer *worldBuffer;
    ID3D11Buffer *viewBuffer;
    ID3D11Buffer *projectionBuffer;
    ID3D11DepthStencilView *depthStencilView;
    ID3D11Texture2D *depthStencilBuffer;
    ID3D11DepthStencilState *depthStencilState;

    XMFLOAT4X4 world;
    XMFLOAT4X4 view;
    XMFLOAT4X4 projection;
    XMFLOAT4 eye;
    XMFLOAT4 target;
    XMFLOAT4 up;
    CPerObject WVP;

    const D3D11_INPUT_ELEMENT_DESC layout[2] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    int numElements = 200;
};

#endif // DWIDGET_H

 

 // cpp文件

#include "DWidget.h"
#include <qevent.h>
#include "GeometryProvider.h"

ID3D11Buffer *boolBuffer;
ID3D11DepthStencilView* pDSV;
struct ABCD
{
    bool a;
}isT;

ID3D11Buffer *cylinderVertexBuffer;
ID3D11Buffer *cylinderIndexBuffer;

DWidget::DWidget(QWidget *parent)
    : QWidget(parent)
{
    setAttribute(Qt::WA_PaintOnScreen, true);
    setAttribute(Qt::WA_NativeWindow, true);
    setAutoFillBackground(false);
    setFocusPolicy(Qt::StrongFocus);
    hwnd = (HWND)winId();
    initializeD3D();
    depthStencilBuffer = nullptr;
    depthStencilView = nullptr;
    d3dPainter = new DPainter;
    d3dPainter->context = context;
    d3dPainter->device = device;
    d3dPainter->createSphere(3, 100);
}

DWidget::~DWidget()
{
    context->Release();
    device->Release();
}

void DWidget::rotateX()
{
    XMMATRIX tmpWord;// = XMLoadFloat4x4(&world);
    XMVECTOR anx = XMVectorSet(1, 0, 0, 0);
    tmpWord = XMMatrixRotationAxis(anx, 0.05);
    multipyWorldMatrix(&tmpWord);
    update();
}

void DWidget::rotateY()
{
    XMMATRIX tmpWord;// = XMLoadFloat4x4(&world);
    XMVECTOR anx = XMVectorSet(0, 1, 0, 0);
    tmpWord = XMMatrixRotationAxis(anx, 0.05);
    multipyWorldMatrix(&tmpWord);
    update();
}

void DWidget::rotateZ()
{
    XMMATRIX tmpWord;
    XMVECTOR anx = XMVectorSet(0, 0, 1, 0);
    tmpWord = XMMatrixRotationAxis(anx, 0.01);
    multipyWorldMatrix(&tmpWord);
    update();
}

void DWidget::paintEvent(QPaintEvent * event)
{
    FLOAT bgColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
    context->ClearRenderTargetView(renderTargetView, bgColor);
    context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0.0f);
    
    { 
        pushWorldMatrix();
        multipyWorldMatrix(&XMMatrixScaling(0.14, 0.14, 0.14));
        multipyWorldMatrix(&XMMatrixTranslation(-10, -10, -10));

        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        UINT stride = sizeof(Vertex);
        UINT offset = 0;
        context->IASetVertexBuffers(0, 1, &cylinderVertexBuffer, &stride, &offset);
        context->IASetIndexBuffer(cylinderIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
        context->DrawIndexed(300, 0, 0);

        {
            pushWorldMatrix();
            multipyWorldMatrix(&XMMatrixTranslation(1, 0, 0));
            multipyWorldMatrix(&XMMatrixScaling(0.1, 0.1, 0.1));

            d3dPainter->drawSphere();

            popWorldMatrix();
        }


        for (int i = 1; i < 15; i++)
        {
            for (int j = 1; j <= 15; j++)
            {
                for (int k = 1; k < 51; k++)
                {
                    pushWorldMatrix();
                    multipyWorldMatrix(&XMMatrixTranslation(i, j, k));
                    multipyWorldMatrix(&XMMatrixScaling(0.1, 0.1, 0.1));
                    d3dPainter->drawSphere();
                    popWorldMatrix();

                }
            }
        }

        
        popWorldMatrix();
    }//d3dPainter->drawSphere();
    
    swapChain->Present(0, 0);

}

void DWidget::updateWVP()
{
    XMStoreFloat4x4(&WVP.view, XMMatrixTranspose(XMLoadFloat4x4(&view)));
    XMStoreFloat4x4(&WVP.world, XMMatrixTranspose(XMLoadFloat4x4(&world)));
    XMStoreFloat4x4(&WVP.projection, XMMatrixTranspose(XMLoadFloat4x4(&projection)));
    context->UpdateSubresource(constantBuffer, 0, NULL, &WVP, 0, 0);
    context->VSSetConstantBuffers(0, 1, &constantBuffer);
    ::isT.a = 0;
}

void DWidget::resizeEvent(QResizeEvent * event)
{
    int width = this->width();
    int height = this->height();
    ::xBasicChangeSize(device, context, swapChain, &renderTargetView, width, height);


    D3D11_TEXTURE2D_DESC depthStencilBufferDesc;
    ZeroMemory(&depthStencilBufferDesc, sizeof(D3D11_TEXTURE2D_DESC));
    depthStencilBufferDesc.Width = width;
    depthStencilBufferDesc.Height = height;
    depthStencilBufferDesc.MipLevels = 1;
    depthStencilBufferDesc.ArraySize = 1;
    depthStencilBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilBufferDesc.SampleDesc.Count = 1;
    depthStencilBufferDesc.SampleDesc.Quality = 0;
    depthStencilBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthStencilBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthStencilBufferDesc.CPUAccessFlags = 0;
    depthStencilBufferDesc.MiscFlags = 0;

    device->CreateTexture2D(&depthStencilBufferDesc, NULL, &depthStencilBuffer);

    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
    ZeroMemory(&depthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    device->CreateDepthStencilState(&depthStencilDesc, &depthStencilState);

    context->OMSetDepthStencilState(depthStencilState, 1);

    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    device->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView);
    context->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
    
    XMMATRIX tmpProjection = XMMatrixPerspectiveFovLH(XM_PIDIV2 / 2, (float)width / (float)height, 0.01f, 100.0f);
    XMStoreFloat4x4(&projection, tmpProjection);
}

void DWidget::mousePressEvent(QMouseEvent * event)
{
}

void DWidget::initializeD3D()
{
    ::xBasicInitializeDirectX11(hwnd, &swapChain, &device, &context, &renderTargetView);
    ::xBasicCreateShader(device, context, L"Effects.fx", &VS_Buffer, &PS_Buffer, &VS, &PS);
    ::xBasicCreateBuffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(CPerObject), &WVP, &constantBuffer);
    ::xBasicCreateBuffer(device, D3D11_BIND_CONSTANT_BUFFER, 16, &::isT, &::boolBuffer);

    XMMATRIX tmpWorld = XMMatrixScaling(0.1, 0.1, 0.1) *XMMatrixTranslation(100 * 0, 100 * 0, 0);;
    XMStoreFloat4x4(&world, tmpWorld);

    XMVECTOR eye = XMVectorSet(0.0f, 0.0f, -1.0f, 0.0f);
    XMVECTOR at = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
    XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
    XMStoreFloat4x4(&view, XMMatrixLookAtLH(eye, at, up));

    //Create the Input Layout
    device->CreateInputLayout(layout, 2, VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), &vertexLayout);

    //Set the Input Layout
    context->IASetInputLayout(vertexLayout);

    GeometryProvider provider;
    std::vector<Vertex> vertices;
    std::vector<UINT> indices;
    GeometryProvider::MeshData data;
    provider.createCylinder(data, 36);
    for (size_t i = 0; i < data.vertices.size(); i++)
    {
        Vertex tmpV;
        tmpV.pos = data.vertices[i].position;
        tmpV.color = XMFLOAT4(rand() % 2, rand() % 2, rand() % 2, 1);
        vertices.push_back(tmpV);
    }

    for (size_t i = 0; i < data.indices.size(); i++)
    {
        indices.push_back(data.indices[i]);
    }

    ::xBasicCreateBuffer(device, D3D11_BIND_VERTEX_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], &cylinderVertexBuffer);
    ::xBasicCreateBuffer(device, D3D11_BIND_INDEX_BUFFER, indices.size() * sizeof(UINT), &indices[0], &cylinderIndexBuffer);
}

void DWidget::pushWorldMatrix()
{
    if (worldStack.empty())
    {
        worldMatrixIdentity();
    }
    worldStack.push(worldStack.top());
}

void DWidget::multipyWorldMatrix(DirectX::XMMATRIX * matrix)
{
    if (worldStack.empty())
    {
        worldMatrixIdentity();
    }

    XMMATRIX aMatrix = XMLoadFloat4x4(&worldStack.top());
    XMMATRIX ansMatrix = *matrix * aMatrix;
    XMStoreFloat4x4(&worldStack.top(), ansMatrix);

    world = worldStack.top();
    updateWVP();
}

void DWidget::popWorldMatrix()
{
    worldStack.pop();

    world = worldStack.top();

    updateWVP();
}

void DWidget::worldMatrixIdentity()
{
    while (!worldStack.empty())
    {
        worldStack.pop();
    }

    worldStack.push(XMFLOAT4X4());

    XMStoreFloat4x4(&worldStack.top(), XMMatrixIdentity());
    
    world = worldStack.top();
    updateWVP();
}

void DWidget::setCurrentWorldMatrix(DirectX::XMMATRIX * matrix)
{
    if (worldStack.empty())
    {
        worldMatrixIdentity();
    }


    XMMATRIX aMatrix = XMLoadFloat4x4(&worldStack.top());
    XMMATRIX ansMatrix = *matrix * aMatrix;
    XMStoreFloat4x4(&worldStack.top(), ansMatrix);

    world = worldStack.top();
    updateWVP();
}

 

 

有些很奇葩的写法就不管了。

初学DirectX11, 留个纪恋。

标签:

原文地址:http://www.cnblogs.com/cxcBlog/p/5771523.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!