zoukankan      html  css  js  c++  java
  • DirectX11 学习笔记6

    这个样例是在之前的样例基础上 。把之前d3dx10math数学库换成了最新的d3dxmath。长处就不说了。先上效果图



    所有代码。以及效果文件

    文件结构



    所有代码:

    依照上图的文件顺序

    #pragma once
    #include <D3DX10math.h>
    #include <xnamath.h>
    class XCamera
    {
    public:
    	XCamera()
    	{
    		m_positionX = 0.0f;
    		m_positionY = 0.0f;
    		m_positionZ = 0.0f;
    
    		m_rotationX = 0.0f;
    		m_rotationY = 0.0f;
    		m_rotationZ = 0.0f;
    	}
    	void setPosition(float x,float y,float z)
    	{
    		m_positionX = x;
    		m_positionY = y;
    		m_positionZ = z;
    	}
    	void setRotation(float x,float y,float z)
    	{
    		m_rotationX = x;
    		m_rotationY = y;
    		m_rotationZ = z;
    	}
    	D3DXVECTOR3 getPosition()
    	{
    		return D3DXVECTOR3(m_positionX, m_positionY, m_positionZ);
    	}
    	D3DXVECTOR3 getRotation()
    	{
    		return D3DXVECTOR3(m_rotationX, m_rotationY, m_rotationZ);
    	}
    	void render(XMMATRIX& viewMatrix)
    	{
    		XMVECTOR up, position, lookAt;
    		float yaw, pitch, roll;
    		XMMATRIX rotationMatrix;
    
    		// 设置up向量为(0,1,0).
    		up=XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
    
    		// 设置摄像机的位置.
    		position=XMVectorSet(m_positionX, m_positionY,m_positionZ, 0.0f);
    		
    		// 设置摄像机lookat的方向.
    		//lookAt=XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
    		lookAt=XMVector3Normalize(position);
    		lookAt=lookAt*(-1);
    		// 得到弧度单位的欧拉旋转 yaw (Y axis), pitch (X axis), 以及 roll (Z axis) .
    		// 1 = PI/180 =  0.0174532925
    		pitch = m_rotationX * 0.0174532925f; 
    		yaw   = m_rotationY * 0.0174532925f;
    		roll  = m_rotationZ * 0.0174532925f;
    
    		// 得到旋转矩阵.
    		rotationMatrix=XMMatrixRotationRollPitchYaw(pitch,yaw,roll);
    
    		// 变换lookat和up向量,一般view可以在原点被正确旋转.
    		lookAt=XMVector3TransformCoord(lookAt,rotationMatrix);
    		up=XMVector3TransformCoord(up,rotationMatrix);
    
    		// 平移旋转后的摄像机位置.
    		lookAt = position + lookAt;
    
    		// 创建观察矩阵.
    		viewMatrix=XMMatrixLookAtLH( position, lookAt, up);
    	}
    	void getViewMatrix(XMMATRIX& viewMatrix)
    	{
    		render(viewMatrix);
    	}
    private:
    	float m_positionX, m_positionY, m_positionZ;//摄像机在世界坐标系中的位置
    	float m_rotationX, m_rotationY, m_rotationZ;//摄像机的欧拉旋转角度
    };


    #pragma once
    #pragma comment(lib, "dxgi.lib")
    #pragma comment(lib, "d3d11.lib")
    #pragma comment(lib, "d3dx11.lib")
    #pragma comment(lib, "d3dx10.lib")
    #include <dxgi.h>
    #include <d3dcommon.h>
    #include <d3d11.h>
    #include <d3dx11.h>
    #include <d3dcompiler.h>
    #include <d3dx10math.h>
    #include <xnamath.h>
    
    XMMATRIX m_projectionMatrix; //投影矩阵
    XMMATRIX m_worldMatrix;//世界坐标系矩阵
    XMMATRIX m_orthoMatrix;//正交投影矩阵
    class XD3Device
    {
    public:
    	XD3Device();
    	//3D设备全部初始化
    	bool init(int, int, bool, HWND, bool, float, float);
    	//关闭设备
    	void close();
    	//開始渲染设备
    	void begin(float, float, float, float);
    	//显示到前景
    	void end();
    
    public:
    	bool m_vsync_enabled; //是否启用垂直同步
    	IDXGISwapChain* m_swapChain; //交换链对象
    	ID3D11Device* m_device;  //设备对象
    	ID3D11DeviceContext* m_deviceContext; //设备上下文对象
    	ID3D11RenderTargetView* m_renderTargetView; //渲染目标视图
    	ID3D11Texture2D* m_depthStencilBuffer; //深度模板缓冲
    	ID3D11DepthStencilState* m_depthStencilState; //深度磨成状态
    	ID3D11DepthStencilView* m_depthStencilView; //深度目标视图
    	ID3D11RasterizerState* m_rasterState; //光栅化状态
    
    public:
    	void getWordMatrix(XMMATRIX& world){world=m_worldMatrix;}
    	void getProjMatrix(XMMATRIX& proj){proj=m_projectionMatrix;}
    };
    void XD3Device::begin(float red, float green, float blue, float alpha)
    {
    	float color[]={red,green,blue,alpha};
    	//清除后缓冲.
    	m_deviceContext->ClearRenderTargetView(m_renderTargetView, color);
    
    	//清除深度缓冲.
    	m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
    
    }
    void XD3Device::end()
    {
    	//渲染完毕后,把后缓冲内容present到前缓冲
    	if(m_vsync_enabled)
    	{
    		// 锁定屏幕刷新率.
    		m_swapChain->Present(1, 0);
    	}
    	else
    	{
    		// 尽可能快的present后缓冲.
    		m_swapChain->Present(0, 0);
    	}
    
    }
    void XD3Device::close()
    {
    	// 释放交换链资源前,先设置为窗体模式,否则可能会产生异常.
    	if(m_swapChain)
    	{
    		m_swapChain->SetFullscreenState(false, NULL);
    	}
    
    	if(m_rasterState)
    	{
    		m_rasterState->Release();
    		m_rasterState = 0;
    	}
    
    	if(m_depthStencilView)
    	{
    		m_depthStencilView->Release();
    		m_depthStencilView = 0;
    	}
    
    	if(m_depthStencilState)
    	{
    		m_depthStencilState->Release();
    		m_depthStencilState = 0;
    	}
    
    	if(m_depthStencilBuffer)
    	{
    		m_depthStencilBuffer->Release();
    		m_depthStencilBuffer = 0;
    	}
    
    	if(m_renderTargetView)
    	{
    		m_renderTargetView->Release();
    		m_renderTargetView = 0;
    	}
    
    	if(m_deviceContext)
    	{
    		m_deviceContext->Release();
    		m_deviceContext = 0;
    	}
    
    	if(m_device)
    	{
    		m_device->Release();
    		m_device = 0;
    	}
    
    	if(m_swapChain)
    	{
    		m_swapChain->Release();
    		m_swapChain = 0;
    	}
    
    }
    XD3Device::XD3Device()
    {
    	m_swapChain = 0;
    	m_device = 0;
    	m_deviceContext = 0;
    	m_renderTargetView = 0;
    	m_depthStencilBuffer = 0;
    	m_depthStencilState = 0;
    	m_depthStencilView = 0;
    	m_rasterState = 0;
    }
    //Initialize函数包括完毕D3D设置的全部代码。

    bool XD3Device::init(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear) { HRESULT result; //IDXGIFactory* factory; //IDXGIAdapter* adapter; //IDXGIOutput* adapterOutput; //unsigned int numModes, stringLength; //DXGI_MODE_DESC* displayModeList; //DXGI_ADAPTER_DESC adapterDesc; //int error; DXGI_SWAP_CHAIN_DESC swapChainDesc; //D3D_FEATURE_LEVEL featureLevel; ID3D11Texture2D* backBufferPtr; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; D3D11_VIEWPORT viewport; float fieldOfView, screenAspect; // 保存垂直同步设置 m_vsync_enabled = vsync; // 初始化交换链描写叙述 ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); //MessageBox(hwnd, L"Could 2", L"Error", MB_OK); // 用1个后缓冲 swapChainDesc.BufferCount = 1; //帧缓冲的大小和应用程序窗体大小相等. swapChainDesc.BufferDesc.Width = screenWidth; swapChainDesc.BufferDesc.Height = screenHeight; // 后缓冲的surface的格式为DXGI_FORMAT_R8G8B8A8_UNORM. // surface的每一个像素用4个无符号的8bit[映射到0-1]来表示。

    NORM表示归一化。

    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 假设使用垂直同步。设置后缓冲的刷新率。. //刷新率就是一秒钟把后缓冲内容在屏幕上画出的次数。 //假设开启垂直同步,则锁定刷新率,则fps是固定的 if(m_vsync_enabled) { swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } else { swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } // 设置后缓冲的用途 // 我们的渲染目标缓冲为后缓冲。

    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 后缓冲输出的窗体句柄. swapChainDesc.OutputWindow = hwnd; // 不使用多重採样 swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; // 设置全屏或者窗体模式. if(fullscreen) { swapChainDesc.Windowed = false; } else { swapChainDesc.Windowed = true; } //MessageBox(hwnd, L"Could 1", L"Error", MB_OK); // 设定扫描线ordering以及缩放为unspecified. swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // 后缓冲内容呈现到屏幕后。放弃其内容 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //不设置标志 swapChainDesc.Flags = 0; // 设置feature level为D3D11 // 假设显卡不支持D3D11,我们可以通过设置这个參数,使用D3D10,或者9. //featureLevel = D3D_FEATURE_LEVEL_10_1; D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); // 创建交换链。设备以及设备上下文. result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext); //MessageBox(hwnd, L"Could 1", L"Error", MB_OK); if(FAILED(result)) { return false; } // 得到交换链中的后缓冲指针. result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr); if(FAILED(result)) { return false; } // 用后缓冲创建渲染目标视图. result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView); if(FAILED(result)) { return false; } //释放后缓冲.(引用计数减1) backBufferPtr->Release(); backBufferPtr = 0; // 初始化深度缓冲描写叙述. ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); //设置深度缓冲描写叙述 depthBufferDesc.Width = screenWidth; depthBufferDesc.Height = screenHeight; depthBufferDesc.MipLevels = 1;//对于深度缓冲为1 depthBufferDesc.ArraySize = 1;//对于深度缓冲为1,对于纹理。这2个參数有很多其它用途 depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.SampleDesc.Quality = 0; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthBufferDesc.CPUAccessFlags = 0; depthBufferDesc.MiscFlags = 0; // 创建深度缓冲. result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); if(FAILED(result)) { return false; } // 初始化深度模版状态描写叙述. ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); // 设置深度模版状态描写叙述. depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;//D3D11_DEPTH_WRITE_MASK_ZERO禁止写深度缓冲 depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // 对于front face 像素使用的模版操作操作. 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; // 对于back face像素使用的模版操作模式. 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; // 创建深度模版状态。使其生效 result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); if(FAILED(result)) { return false; } // 设置深度模版状态. m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); // 初始化深度模版视图. ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); // 设置深度模版视图描写叙述. depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; // 创建深度模版视图. result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); if(FAILED(result)) { return false; } // 绑定渲染目标视图和深度缓冲到渲染管线. m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); // 设置光栅化描写叙述,指定多边形怎样被渲染. rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; // 创建光栅化状态 result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState); if(FAILED(result)) { return false; } //设置光栅化状态,使其生效 m_deviceContext->RSSetState(m_rasterState); // 设置视口,显示全部后缓冲内容 viewport.Width = (float)screenWidth; viewport.Height = (float)screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; // 创建视口 m_deviceContext->RSSetViewports(1, &viewport); // 设置透视投影矩阵 fieldOfView = (float)D3DX_PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; // 创建透视投影矩阵. m_projectionMatrix=XMMatrixPerspectiveFovLH( fieldOfView, screenAspect, screenNear, screenDepth); //初始化world矩阵为单位矩阵. //该矩阵实现局部坐标到世界坐标的转换 m_worldMatrix=XMMatrixIdentity(); // 创建正交投影矩阵,主要用来实施2D渲染. m_orthoMatrix=XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); return true; }

    #pragma once
    
    #include <windows.h>
    #include "XD3Device.h"
    #include "XCamera.h"
    #include "XModel.h"
    #include "XShader.h"
    ///////////// 
    // GLOBALS // 
    ///////////// 
    const bool  FULL_SCREEN = false; //是否全屏 
    const bool  VSYNC_ENABLED = true; //是否垂直同步 
    const float SCREEN_DEPTH = 1000.0f; //深度。远点 
    const float SCREEN_NEAR = 0.1f; //深度。近点
    
    class XGraphics 
    { 
    public: 
    	XGraphics():x_d3d(0),x_camera(0),x_model(0),x_shader(0){}
    	bool init(int, int, HWND); //初始化渲染设备
    	void close(); 
    	bool frame();
    
    private: 
    	bool render(); 
    private:
    	XD3Device *x_d3d;//3D设备
    	XCamera *x_camera;//摄像机
    	XModel *x_model;//模型
    	XShader *x_shader;//渲染器
    	HWND hwnd;
    };
    
    bool XGraphics:: init(int screenWidth, int screenHeight, HWND hwnd) 
    {
    	//先清空
    	close();
    	//初始化设备
    	this->hwnd=hwnd;
    	x_d3d=new XD3Device;
    	bool hr=x_d3d->init(screenWidth,screenHeight,VSYNC_ENABLED,hwnd,FULL_SCREEN,SCREEN_DEPTH,SCREEN_NEAR);
    	if(!hr)
    	{
    		MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK); 
    		return false; 
    	}
    	//初始化摄像机
    	x_camera=new XCamera;
    	x_camera->setPosition(3.0f,3.0f,-10.0f); 
    	//初始化模型
    	x_model=new XModel;
    	x_model->init(x_d3d->m_device);
    	//初始化Shader
    	x_shader=new XShader;
    	x_shader->init(x_d3d->m_device,hwnd);
    	return true; 
    }
    
    void XGraphics::close() 
    {
    	if(x_d3d)
    	{
    		x_d3d->close();
    		delete x_d3d;
    		x_d3d=0;
    	}
    	if(x_camera)
    	{
    		delete x_camera;
    		x_camera=NULL;
    	}
    	if(x_shader)
    	{
    		x_shader->close();
    		delete x_shader;
    		x_shader=NULL;
    	}
    	if(x_model)
    	{
    		x_model->close();
    		delete x_model;
    		x_model=NULL;
    	}
    
    
    }
    
    bool XGraphics::frame() 
    {
    	bool hr=render();
    	return hr; 
    }
    
    
    bool XGraphics::render() 
    {
    	XMMATRIX viewMatrix, projectionMatrix, worldMatrix;
    	x_d3d->begin(0.0f,0.0f,0.5f,1.0f);//蓝色
    	//世界矩阵
    	x_d3d->getWordMatrix(worldMatrix);
    	//观察矩阵
    	x_camera->getViewMatrix(viewMatrix);
    	//投影矩阵
    	x_d3d->getProjMatrix(projectionMatrix);
    	//模型增加管线
    	x_model->render(x_d3d->m_deviceContext);
    	//開始渲染
    	x_shader->render(x_d3d->m_deviceContext,x_model->m_indexCount,worldMatrix,viewMatrix,projectionMatrix);
    	//结束
    	x_d3d->end();
    	return true; 
    }
    

    #pragma once
    class XInput
    {
    public:
    	void init();
    	void keyDown(unsigned int);
    	void keyUp(unsigned int);
    	bool isKeyDown(unsigned int);
    private:
    	bool x_keys[256];
    
    };
    void XInput::init()
    {
    	int i;
    
    	// 初始全部的键都是非按下状态. 
    	for(i=0; i<256; i++) 
    	{ 
    		x_keys[i] = false; 
    	}
    
    	return; 
    }
    void XInput::keyDown(unsigned int input) 
    { 
    	//键被按下. 
    	x_keys[input] = true; 
    	return; 
    }
    void XInput::keyUp(unsigned int input) 
    { 
    	//键被按下. 
    	x_keys[input] = false; 
    	return; 
    }
    bool XInput::isKeyDown(unsigned int key) 
    { 
    	// 推断键是否被按下? 
    	return x_keys[key]; 
    }
    


    #pragma  once
    #include <D3D11.h>
    //定义一些经常使用颜色 
    const XMFLOAT4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); 
    const XMFLOAT4 BLACK(0.0f, 0.0f, 0.0f, 1.0f); 
    const XMFLOAT4 RED(1.0f, 0.0f, 0.0f, 1.0f); 
    const XMFLOAT4 GREEN(0.0f, 1.0f, 0.0f, 1.0f); 
    const XMFLOAT4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); 
    const XMFLOAT4 YELLOW(1.0f, 1.0f, 0.0f, 1.0f); 
    const XMFLOAT4 CYAN(0.0f, 1.0f, 1.0f, 1.0f); //蓝绿色 
    const XMFLOAT4 MAGENTA(1.0f, 0.0f, 1.0f, 1.0f); //洋红色
    
    const XMFLOAT4 BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f); 
    const XMFLOAT4 LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f, 1.0f); 
    const XMFLOAT4 DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f, 1.0f); 
    const XMFLOAT4 DARKBROWN(0.45f, 0.39f, 0.34f, 1.0f);
    
    
    class XModel
    {
    private:struct SimpleVertex
    		{
    			XMFLOAT3 Pos;
    			XMFLOAT4 Color;
    		};
    public://顶点缓冲和顶点索引缓冲
    		ID3D11Buffer *m_vertexBuffer, *m_indexBuffer;
    		int m_vertexCount, m_indexCount;
    public:
    	XModel():m_vertexCount(0),m_indexCount(0){};
    	virtual void init(ID3D11Device*);
    	virtual void close();
    	virtual void render(ID3D11DeviceContext*);
    };
    void XModel::init(ID3D11Device* device)
    {
    	unsigned long* indices;
    	D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
    	D3D11_SUBRESOURCE_DATA vertexData, indexData;
    
    	//首先,我们创建2个暂时缓冲存放顶点和索引数据,以便后面使用。. 
    
    	// 设置顶点缓冲大小为3,一个三角形.
    	m_vertexCount = 8;
    
    	// 设置索引缓冲大小.
    	m_indexCount = 36;  //6面*2三角形*3个点
    
    	// 创建顶点暂时缓冲.
    	SimpleVertex vertices[] = {
    		{XMFLOAT3(-1.0f, -1.0f, -1.0f),WHITE},
    		{XMFLOAT3(-1.0f, 1.0f, -1.0f),BLACK},
    		{XMFLOAT3(1.0f, 1.0f, -1.0f),RED},
    		{XMFLOAT3(1.0f, -1.0f, -1.0f),GREEN},
    		{XMFLOAT3(-1.0f, -1.0f, 1.0f),BLUE},
    		{XMFLOAT3(-1.0f, 1.0f, 1.0f),YELLOW},
    		{XMFLOAT3(1.0f, 1.0f, 1.0f),CYAN},
    		{XMFLOAT3(1.0f, -1.0f, 1.0f),MAGENTA},
    
    	};
    
    	// 创建索引缓冲.
    	indices = new unsigned long[m_indexCount];
    	// 设置索引缓冲数据.
    	indices[0] = 0;  // 前面 
    	indices[1] = 1; 
    	indices[2] = 2;  
    	indices[3] = 0; 
    	indices[4] = 2; 
    	indices[5] = 3;  
    
    	indices[6] = 4;  // 后面 
    	indices[7] = 6; 
    	indices[8] = 5;  
    	indices[9] = 4; 
    	indices[10] = 7; 
    	indices[11] = 6;
    
    	indices[12] = 4;  // 左面 
    	indices[13] = 5; 
    	indices[14] = 1;  
    	indices[15] = 4; 
    	indices[16] = 1; 
    	indices[17] = 0;
    
    	indices[18] = 3;  //右面 
    	indices[19] = 2; 
    	indices[20] = 6;  
    	indices[21] = 3; 
    	indices[22] = 6; 
    	indices[23] = 7;
    
    	indices[24] = 1;  // 上面 
    	indices[25] = 5; 
    	indices[26] = 6;  
    	indices[27] = 1; 
    	indices[28] = 6; 
    	indices[29] = 2;
    
    	indices[30] = 4; // 以下 
    	indices[31] = 0; 
    	indices[32] = 3;  
    	indices[33] = 4; 
    	indices[34] = 3; 
    	indices[35] = 7;
    
    
    
    	// 设置顶点缓冲描写叙述
    	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    	vertexBufferDesc.ByteWidth = sizeof(SimpleVertex) * m_vertexCount;
    	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    	vertexBufferDesc.CPUAccessFlags = 0;
    	vertexBufferDesc.MiscFlags = 0;
    	vertexBufferDesc.StructureByteStride = 0;
    
    	// 指向保存顶点数据的暂时缓冲.
    	vertexData.pSysMem = vertices;
    	vertexData.SysMemPitch = 0;
    	vertexData.SysMemSlicePitch = 0;
    
    	// 创建顶点缓冲.
        device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
    
    
    	// 设置索引缓冲描写叙述.
    	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    	indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
    	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    	indexBufferDesc.CPUAccessFlags = 0;
    	indexBufferDesc.MiscFlags = 0;
    	indexBufferDesc.StructureByteStride = 0;
    
    	// 指向存暂时索引缓冲.
    	indexData.pSysMem = indices;
    	indexData.SysMemPitch = 0;
    	indexData.SysMemSlicePitch = 0;
    
    	// 创建索引缓冲.
    	device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
    
    
    
    
    	delete [] indices;
    	indices = 0;
    }
    void XModel::close()
    {
    	// 释放顶点缓冲.
    	if(m_indexBuffer)
    	{
    		m_indexBuffer->Release();
    		m_indexBuffer = 0;
    	}
    
    	// 释放索引缓冲
    	if(m_vertexBuffer)
    	{
    		m_vertexBuffer->Release();
    		m_vertexBuffer = 0;
    	}
    
    }
    void XModel::render(ID3D11DeviceContext* deviceContext)
    {
    	unsigned int stride;
    	unsigned int offset;
    
    
    	// 设置顶点缓冲跨度和偏移.
    	stride = sizeof(SimpleVertex); 
    	offset = 0;
    
    	//在input assemberl阶段绑定顶点缓冲。以便可以被渲染
    	deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
    
    	//在input assemberl阶段绑定索引缓冲,以便可以被渲染
    	deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
    
    	// 设置体元语义,渲染三角形列表.
    	deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    }

    #pragma once
    #include <d3d11.h>
    #include <d3dx11.h>
    #include <d3dcompiler.h>
    #include <xnamath.h>
    #include <fstream>
    using namespace std;
    //常量缓冲区
    struct ConstantBuffer
    {
    	XMMATRIX mWorld;
    	XMMATRIX mView;
    	XMMATRIX mProjection;
    };
    class XShader
    {
    public:
    	XShader();
    	HRESULT init(ID3D11Device*, HWND);//初始化
    	void close(); //关闭
    	HRESULT render(ID3D11DeviceContext* , int , XMMATRIX& , XMMATRIX &, XMMATRIX &);//渲染
    private:
    	HRESULT InitializeShader(ID3D11Device*, HWND, WCHAR*);
    	void ShutdownShader();
    	void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*);
        HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut );
    	HRESULT SetShaderParameters(ID3D11DeviceContext*, XMMATRIX&, XMMATRIX&, XMMATRIX&);
    	void RenderShader(ID3D11DeviceContext*, int);
    
    	ID3D11VertexShader* m_vertexShader;
    	ID3D11PixelShader* m_pixelShader;
    	ID3D11InputLayout* m_layout;
    	ID3D11Buffer* m_matrixBuffer;
    };
    XShader::XShader()
    {
    	m_vertexShader = 0;
    	m_pixelShader = 0;
    	m_layout = 0;
    	m_matrixBuffer = 0;
    }
    HRESULT XShader::init(ID3D11Device* device, HWND hwnd)
    {
    	HRESULT result;
    	// 初始化vs 和ps.
    	result = InitializeShader(device, hwnd, L"shader.fx");
    	return result;
    }
    void XShader::close()
    {
    	// 释放shader资源.
    	ShutdownShader();
    
    	return;
    }
    HRESULT XShader::render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX &worldMatrix, 
    							  XMMATRIX& viewMatrix, XMMATRIX& projectionMatrix)
    {
    
    	// 设置shader常量缓冲区
    	SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix);
    
    	// 用shader渲染指定缓冲顶点
    	RenderShader(deviceContext, indexCount);
    
    	return S_OK;
    }
    HRESULT XShader::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
    {
    	HRESULT hr = S_OK;
    
    	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
    #if defined( DEBUG ) || defined( _DEBUG )
    	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    	// Setting this flag improves the shader debugging experience, but still allows 
    	// the shaders to be optimized and to run exactly the way they will run in 
    	// the release configuration of this program.
    	dwShaderFlags |= D3DCOMPILE_DEBUG;
    #endif
    
    	ID3DBlob* pErrorBlob;
    	hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel, 
    		dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
    	if( FAILED(hr) )
    	{
    		if( pErrorBlob != NULL )
    			OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
    		if( pErrorBlob ) pErrorBlob->Release();
    		return hr;
    	}
    	if( pErrorBlob ) pErrorBlob->Release();
    
    	return S_OK;
    }
    HRESULT XShader::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* Filename)
    {
    	HRESULT hr=S_OK;
    	// Compile the vertex shader
    	ID3DBlob* pVSBlob = NULL;
    	hr = CompileShaderFromFile( Filename, "VS", "vs_4_0", &pVSBlob );
    	if( FAILED( hr ) )
    	{
    		MessageBox( NULL,
    			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
    		return hr;
    	}
    
    	// Create the vertex shader
    	hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_vertexShader );
    	if( FAILED( hr ) )
    	{	
    		pVSBlob->Release();
    		return hr;
    	}
    	// Compile the pixel shader
    	ID3DBlob* pPSBlob = NULL;
    	hr = CompileShaderFromFile( Filename, "PS", "ps_4_0", &pPSBlob );
    	if( FAILED( hr ) )
    	{
    		MessageBox( NULL,
    			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
    		return hr;
    	}
    
    	// Create the pixel shader
    	hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pixelShader );
    	pPSBlob->Release();
    	if( FAILED( hr ) )
    		return hr;
    
    	// Define the input layout
    	D3D11_INPUT_ELEMENT_DESC layout[] =
    	{
    		{ "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 },
    	};
    	UINT numElements = ARRAYSIZE( layout );
    
    	// Create the input layout
    	hr = device->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
    		pVSBlob->GetBufferSize(), &m_layout );
    	pVSBlob->Release();
    	if( FAILED( hr ) )
    		return hr;
    	// Create the constant buffer
    	D3D11_BUFFER_DESC bd;
    	ZeroMemory( &bd, sizeof(bd) );
    	bd.Usage = D3D11_USAGE_DEFAULT;
    	bd.ByteWidth = sizeof(ConstantBuffer);
    	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    	bd.CPUAccessFlags = 0;
    	hr = device->CreateBuffer( &bd, NULL, &m_matrixBuffer );
    	if( FAILED( hr ) )
    		return hr;
    	return S_OK;
    }
    
    void XShader::ShutdownShader()
    {
    	// 释放常量缓冲
    	if(m_matrixBuffer)
    	{
    		m_matrixBuffer->Release();
    		m_matrixBuffer = 0;
    	}
    
    	//释放顶点布局
    	if(m_layout)
    	{
    		m_layout->Release();
    		m_layout = 0;
    	}
    
    	// 释放ps .
    	if(m_pixelShader)
    	{
    		m_pixelShader->Release();
    		m_pixelShader = 0;
    	}
    
    	// 释放vs
    	if(m_vertexShader)
    	{
    		m_vertexShader->Release();
    		m_vertexShader = 0;
    	}
    
    	return;
    }
    
    void XShader::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename)
    {
    	char* compileErrors;
    	unsigned long bufferSize, i;
    	ofstream fout;
    
    
    	// 得到错误信息buffer指针.
    	compileErrors = (char*)(errorMessage->GetBufferPointer());
    
    	// 得到buffer的长度.
    	bufferSize = errorMessage->GetBufferSize();
    
    	// 打开一个文件写错误信息.
    	fout.open("shader-error.txt");
    
    	// 输出错误信心.
    	for(i=0; i<bufferSize; i++)
    	{
    		fout << compileErrors[i];
    	}
    
    	// 关闭文件
    	fout.close();
    
    	// 释放错误消息.
    	errorMessage->Release();
    	errorMessage = 0;
    
    	//弹出错误提示.
    	MessageBox(hwnd, L"Error compiling shader.  Check shader-error.txt for message.", shaderFilename, MB_OK);
    
    	return;
    }
    
    HRESULT XShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX &worldMatrix, 
    										   XMMATRIX &viewMatrix, XMMATRIX &projectionMatrix)
    {
    	//
    	// Update variables
    	//
    	ConstantBuffer cb;
    	cb.mWorld = XMMatrixTranspose( worldMatrix);
    	cb.mView = XMMatrixTranspose( viewMatrix );
    	cb.mProjection = XMMatrixTranspose( projectionMatrix );
    	deviceContext->UpdateSubresource( m_matrixBuffer, 0, NULL, &cb, 0, 0 );
    	deviceContext->VSSetConstantBuffers( 0, 1, &m_matrixBuffer );
    
    	return true;
    }
    
    void XShader::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
    {
    	// 绑定顶点布局.
    	deviceContext->IASetInputLayout(m_layout);
    
    	// 设置渲染使用vs和ps.
    	deviceContext->VSSetShader(m_vertexShader, NULL, 0);
    	deviceContext->PSSetShader(m_pixelShader, NULL, 0);
    
    	// 渲染图形
    	deviceContext->DrawIndexed(indexCount, 0, 0);
    
    	return;
    }
    

    #pragma once 
    //定义该宏可以降低windows头文件的大小。使编译器不编译一些不必要的文件。加快编译时间 
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    #include "XGraphics.h"
    #include "XInput.h"
    //退出
    static bool Xexit=false;
    //全屏
    static bool fullScreen=false;
    class XWindow
    {
    private:
    	//窗体类名字
    	LPCWSTR m_applicationName;
    	//实例句柄
    	HINSTANCE m_hinstance;
    	//窗体句柄
    	HWND m_hwnd;
    	int xwidth,xheight;
    	//按键类
    	XInput * x_input;
    	//图形类
    	XGraphics * x_graphics;
    private:
    	//初始化窗体
    	void initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName);
    	//关闭窗体
    	void closeWindows();
    	//消息循环
    	void runWindows();
    	
    public:
    	//初始化全局
    	virtual void init();
    	//渲染
    	virtual bool frame();
    	//退出
    	virtual void close();
    	//消息函数
    	LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM); 
    };
    //消息循环回调函数
    static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    static XWindow * appXWindow=NULL;
    void XWindow::close()
    {
    	if(x_input)
    	{
    		delete x_input;
    		x_input=NULL;
    	}
    	if(x_graphics)
    	{
    		x_graphics->close();
    		delete x_graphics;
    		x_graphics=NULL;
    	}
    }
    void XWindow::init()
    {
    	xwidth=500;
    	xheight=400;
    	x_input=new XInput;
    	x_graphics=new XGraphics;
    	
    	//创建窗体
    	initWindows(xwidth,xheight,L"Engine");
    	//初始化键盘
    	x_input->init();
    	//初始化渲染
    	x_graphics->init(xwidth,xheight,m_hwnd);
    
    
    	//消息循环
    	runWindows();
    	//关闭窗体
    	closeWindows();
    }
    bool XWindow::frame()
    {
    	//推断是否按下ESC键
    	if(x_input->isKeyDown(VK_ESCAPE))
    		return false;
    	//開始渲染
    	return x_graphics->frame();
    }
    void XWindow::initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName)
    {
    	WNDCLASSEX wc; 
    	DEVMODE dmScreenSettings; 
    	int posX, posY;
    	this->m_applicationName=m_applicationName;
    	// 得到应用程序实例句柄 
    	m_hinstance = GetModuleHandle(NULL);
    	appXWindow=this;
    	// 设置窗体类參数. 
    	wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
    
    	wc.lpfnWndProc   = WndProc; //指定回调函数 
    	wc.cbClsExtra    = 0; 
    	wc.cbWndExtra    = 0; 
    	wc.hInstance     = m_hinstance; 
    	wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO); 
    	wc.hIconSm       = wc.hIcon; 
    	wc.hCursor       = LoadCursor(NULL, IDC_ARROW); 
    	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //默认黑色窗体黑色背景 
    	wc.lpszMenuName  = NULL; 
    	wc.lpszClassName = m_applicationName; 
    	wc.cbSize        = sizeof(WNDCLASSEX);
    
    	// 注冊窗体类 
    	RegisterClassEx(&wc);
    
    	// 依据是否全屏设置不同的分辨率. 
    	if(fullScreen) 
    	{ 
    		// 得到windows桌面分辨率 
    		screenWidth  = GetSystemMetrics(SM_CXSCREEN); 
    		screenHeight = GetSystemMetrics(SM_CYSCREEN);
    		//全屏模式下,设置窗体大小为windows桌面分辨率. 
    		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); 
    		dmScreenSettings.dmSize       = sizeof(dmScreenSettings); 
    		dmScreenSettings.dmPelsWidth  = (unsigned long)screenWidth; 
    		dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight; 
    		dmScreenSettings.dmBitsPerPel = 32;            
    		dmScreenSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    
    		// 暂时设置显示设备为全屏模式,注意:应用程序退出时候。将恢复系统默认设置。 
    		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
    
    		// 设置窗体的左上角坐标位置为(0,0). 
    		posX = posY = 0; 
    	} 
    	else 
    	{ 
    		// 窗体左上角坐标位置,posX, posY
    		posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth)  / 2; 
    		posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2; 
    	}
    
    	// 全屏和窗体使用不同的參数. 
    	if( fullScreen) 
    	{ 
    		m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
    			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, 
    			posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); 
    	} 
    	else 
    	{ 
    		m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
    			WS_OVERLAPPEDWINDOW, 
    			posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); 
    	}
    
    	// 显示窗体并设置其为焦点. 
    	ShowWindow(m_hwnd, SW_SHOW); 
    	SetForegroundWindow(m_hwnd); 
    	SetFocus(m_hwnd);
    	// 隐藏鼠标. 
    	//ShowCursor(false);
    
    }
    
    void XWindow::runWindows()
    {
    	MSG msg; 
    	// 初始化消息结构. 
    	ZeroMemory(&msg, sizeof(MSG));
    	// 循环进行消息处理
    	while(!Xexit) 
    	{ 
    		// 处理windows消息. 
    		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    		{ 
    			TranslateMessage(&msg); 
    			DispatchMessage(&msg); 
    		}
    		// 接收到WM_QUIT消息。退出程序. 
    		if(msg.message == WM_QUIT) 
    		{ 
    			Xexit=true;
    		} 
    		else 
    		{ 
    			//渲染
    			Xexit=!frame();
    		}
    
    	}
    	return; 
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam) 
    { 
    	switch(umessage) 
    	{
    
    		// 窗体销毁消息. 
    	case WM_DESTROY: 
    	case WM_CLOSE: 
    		{ 
    			PostQuitMessage(0); 
    			return 0; 
    		}
    		break;
    		//MessageHandle过程处理其他全部消息. 
    	default: 
    		{ 
    			return appXWindow->MessageHandler(hwnd, umessage, wparam, lparam); 
    		} 
    		break;
    	} 
    
    }
    
    LRESULT CALLBACK XWindow::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) 
    {
    
    	switch(umsg) 
    	{ 
    		// 检測按键消息. 
    	case WM_KEYDOWN: 
    		x_input->keyDown(wparam);
    	    break;
    	case WM_KEYUP:
    		x_input->keyUp(wparam);
    		break;
    		//不论什么其他消息发送到windows缺省处理. 
    	case WM_SIZE:
    		//防止窗体大小改变渲染变形
    		x_graphics->init(LOWORD(lparam),HIWORD(lparam),hwnd);
    		break;
    	default: 
    		{ 
    			return DefWindowProc(hwnd, umsg, wparam, lparam); 
    		} 
    	} 
    	return 0;
    }
    void XWindow::closeWindows()
    {
    	//显示光标. 
    	//ShowCursor(true);
    	// 恢复默认显示设置. 
    	if(fullScreen) 
    	{ 
    		ChangeDisplaySettings(NULL, 0); 
    	}
    	//释放窗体句柄. 
    	DestroyWindow(m_hwnd); 
    	m_hwnd = NULL;
    	// 释放应用程序实例. 
    	UnregisterClass(m_applicationName, m_hinstance); 
    	m_hinstance = NULL;
    	appXWindow=NULL;
    	return; 
    }

    #include "XWindow.h"
    #include <d3dcompiler.h>
    //入口
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) 
    {
    
    	XWindow *xwindow=new XWindow;
    	xwindow->init(); //初始化
    	xwindow->close();
    	delete xwindow;
    	return 0; 
    }
    

    //--------------------------------------------------------------------------------------
    // File: Tutorial04.fx
    //
    // Copyright (c) Microsoft Corporation. All rights reserved.
    //--------------------------------------------------------------------------------------
    
    //--------------------------------------------------------------------------------------
    // Constant Buffer Variables
    //--------------------------------------------------------------------------------------
    cbuffer ConstantBuffer 
    {
    	matrix World;
    	matrix View;
    	matrix Projection;
    }
    
    //--------------------------------------------------------------------------------------
    struct VS_OUTPUT
    {
        float4 Pos : SV_POSITION;
        float4 Color : COLOR;
    };
    
    //--------------------------------------------------------------------------------------
    // Vertex Shader
    //--------------------------------------------------------------------------------------
    VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR )
    {
        VS_OUTPUT output = (VS_OUTPUT)0;
        output.Pos = mul( Pos, World );
        output.Pos = mul( output.Pos, View );
        output.Pos = mul( output.Pos, Projection );
        output.Color = Color;
        return output;
    }
    
    
    //--------------------------------------------------------------------------------------
    // Pixel Shader
    //--------------------------------------------------------------------------------------
    float4 PS( VS_OUTPUT input ) : SV_Target
    {
        return input.Color;
    }
    


  • 相关阅读:
    Linux-1-用户管理
    接口相关资料整理
    JPype1使用总结
    1.django项目的创建(在CMD中)
    公有云、私有云和混合云的区别
    接口测试1.测试用例要点与模板
    PostMan Test 的脚本scripts编写方法
    Tensorflow RNN中的坑
    2019年终总结
    tensorflow中一种融合多个模型的方法
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6905326.html
Copyright © 2011-2022 走看看