D3D11的像素裁剪

来源:互联网 发布:单色led显示屏软件 编辑:程序博客网 时间:2024/05/19 22:02

本篇将如何快速有效的裁剪绘制到屏幕上的像素。

如果α值接近0时,如何使用着色器文件中的clip()函数来阻止处理当前像素。

一个使用clip函数的实例:

clip(alpha - .25);


如果α值小于等于0.25时,将会对像素进行裁剪。clip函数的工作方式就是如果值小于等于0时,它就会彻底阻止像素着色器进一步的处理,且没有数据会写入到渲染目标或这深度模板缓冲中。


全局声明

为了看到箱子的后面,需要禁止背面的裁剪。通过创建一个新的渲染状态来完成这项任务。

ID3D11RasterizerState* noCull;

清除

void CleanUp(){    //Release the COM Objects we created    SwapChain->Release();    d3d11Device->Release();    d3d11DevCon->Release();    renderTargetView->Release();    squareVertBuffer->Release();    squareIndexBuffer->Release();    VS->Release();    PS->Release();    VS_Buffer->Release();    PS_Buffer->Release();    vertLayout->Release();    depthStencilView->Release();    depthStencilBuffer->Release();    cbPerObjectBuffer->Release();    ///////////////**************new**************////////////////////    noCull->Release();    ///////////////**************new**************////////////////////}


新的图像文件

将会加载进一个png格式的图像文件,因为它包含了一个α部分。通常使用jpg,但是jpg不包含α部分。在此加载箱子纹理。

hr = D3DX11CreateShaderResourceViewFromFile( d3d11Device, L"Cage.png",    NULL, NULL, &CubesTexture, NULL );


不要背面裁剪

创建一个新的光栅化状态(渲染状态)来禁止背面裁剪,为的是能够看到箱子的背面。渲染状态会在后面说到:

D3D11_RASTERIZER_DESC rastDesc;ZeroMemory(&rastDesc, sizeof(D3D11_RASTERIZER_DESC));rastDesc.FillMode = D3D11_FILL_SOLID;rastDesc.CullMode = D3D11_CULL_NONE;d3d11Device->CreateRasterizerState(&rastDesc, &noCull);

设置渲染状态

首先会渲染使用默认渲染状态的对象,随后渲染使用没有背面裁剪状态的对象。为了设置渲染状态为默认状态,设置参数为NULL,随后渲染使用默认渲染状态的对象。下一步设置渲染状态到在初始化场景时创建的对象,这儿为了能够看到箱子背面会禁止背面裁剪。会传入noCull渲染状态。

d3d11DevCon->RSSetState(NULL);//Draw objects that will use backface cullingd3d11DevCon->RSSetState(noCull);

裁剪像素

clip()

现在跳入着色器文件,在这儿修改PS阶段。首先可以看到的是已经创建了一个新的float4变量,它将存储像素的颜色和α值并将它设置到图像的纹理中。随后调用clip(),指定diffuse.a-.25。使用.25是因为在过滤像素之后,它的α值可能变模糊,且可能不等于0,所以要给它一点空间。任何像素的α值小于等于.25将会被裁剪掉,也就是说不会渲染到屏幕上。随后如果clip函数没有结束PS阶段,则返回像素颜色(diffuse)。

float4 PS(VS_OUTPUT input) : SV_TARGET{    float4 diffuse = ObjTexture.Sample( ObjSamplerState, input.TexCoord );        clip(diffuse.a - .25);        return diffuse;}



代码实例:

#include "stdafx.h"#pragma comment(lib, "d3d11.lib")#pragma comment(lib, "d3dx11.lib")#pragma comment(lib, "d3dx10.lib")#include <windows.h>#include "Resource.h"#include <d3d11.h>#include <d3dx11.h>#include <d3dx10.h>#include <xnamath.h>//全局描述符IDXGISwapChain* SwapChain;ID3D11Device* d3d11Device;ID3D11DeviceContext* d3d11DevCon;ID3D11RenderTargetView* renderTargetView;//索引缓冲ID3D11Buffer* squareIndexBuffer;ID3D11Buffer* squareVertBuffer;//深度值-20170927ID3D11DepthStencilView* depthStencilView;ID3D11Texture2D* depthStencilBuffer;//着色器ID3D11Buffer* triangleVertBuffer;ID3D11VertexShader* VS;ID3D11PixelShader* PS;ID3D10Blob* VS_Buffer;ID3D10Blob* PS_Buffer;ID3D11InputLayout* vertLayout;///ID3D11Buffer* cbPerObjectBuffer;///ID3D11ShaderResourceView* CubesTexture;ID3D11SamplerState* CubesTexSamplerState;// 设置线框//ID3D11RasterizerState* WireFrame;//无裁剪ID3D11RasterizerState* noCull;#if 0//混合设置ID3D11BlendState* Transparency;ID3D11RasterizerState* CCWcullMode;ID3D11RasterizerState* CWcullMode;float red = 0.0f;float green = 0.0f;float blue = 0.0f;int colormodr = 1;int colormodg = 1;int colormodb = 1;#endif/////LPCTSTR WndClassName = "firstwindow";HWND hwnd = NULL;HRESULT hr;const int Width = 800; //设置宽const int Height = 800; // 设置高///四个空间以及相机属性XMMATRIX WVP;//立方体XMMATRIX cube1World;XMMATRIX cube2World;//XMMATRIX World;XMMATRIX camView;XMMATRIX camProjection;XMVECTOR camPosition;XMVECTOR camTarget;XMVECTOR camUp;//相机XMMATRIX Rotation;XMMATRIX Scale;XMMATRIX Translation;float rot = 0.01f;//////函数声明bool InitializeDirect3d11App(HINSTANCE hInstance);//void ReleaseObjects();void CleanUp();bool InitScene();void UpdateScene();void DrawScene();// 初始化窗口bool InitializeWindow(HINSTANCE hInstance,int ShowWnd,int width, int height,bool windowed);//初始化消息循环函数int messageloop();//初始化窗口回调过程。Windows API是事件驱动型的编程模型。在该函数中捕获Windows消息,比如一个按键按下(也叫事件)以及程序操作流程。LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);//创建效果常量缓冲的结构体struct cbPerObject{XMMATRIX WVP;};cbPerObject cbPerObj;//顶点结构体以及顶点布局(输入布局)#if 1struct Vertex{Vertex(){}Vertex(float x, float y, float z,float u, float v):pos(x, y, z), texCoord(u, v){}XMFLOAT3 pos;XMFLOAT2 texCoord;};D3D11_INPUT_ELEMENT_DESC layout[] = {{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },};UINT numElements = ARRAYSIZE(layout);#elsestruct Vertex{Vertex(){}Vertex(float x, float y, float z,float cr, float cg, float cb, float ca):pos(x, y, z), color(cr, cg, cb, ca){}XMFLOAT3 pos;XMFLOAT4 color;};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);#endif//主函数,传入应用程序句柄hInstance,前一个应用程序句柄hPrevInstance,传给函数处理的命令行lpCmdLine以及窗口显示方式的nShowCmdint WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){//创建并注册窗口if (!InitializeWindow(hInstance, nShowCmd, Width, Height, true)){MessageBox(0, "Window Initilization - Failed", "Error", MB_OK);return 0;}/////newif (!InitializeDirect3d11App(hInstance)) // 初始化D3D{MessageBox(0, "Direct3D Initialization - Failed", "Error", MB_OK);return 0;}if (!InitScene()){MessageBox(0, "Scene Initialization - Failed", "Error", MB_OK);return 0;}messageloop();CleanUp();//ReleaseObjects();return 0;}// windowed 若为true则为窗口模式显示,若为false则为全屏模式显示bool InitializeWindow(HINSTANCE hInstance,int ShowWnd,int width, int height,bool windowed){/*typedef struct _WNDCLASS{UINT cbSize;UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HANDLE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCTSTR lpszMenuName;LPCTSTR lpszClassName;}WNDCLASS;*/WNDCLASSEX wc;wc.cbSize = sizeof(WNDCLASSEX); //window类的大小/********windows类风格*CS_CLASSDC 一个使用该类创建的在所有窗口间共享的设备上下文*CS_DBLCLKS 在窗口上使能双击功能*CS_HREDRAW 若窗口的宽度有改变或者窗口水平地移动,窗口将会刷新*CS_NOCLOSE 窗口菜单上禁止关闭选项*CS_OWNDC   为每个窗口创建自己的设备上下文。正好与CS_CLASSDC相反*CS_PARENTDC 这会设置创建的子窗口的剪裁四边形到父窗口,这允许子窗口能够在父窗口上绘画*CS_VERDRAW 若在窗口的高度或窗口在垂直方向有移动窗口会重绘**/wc.style = CS_HREDRAW | CS_VREDRAW;//lpfnWndProc是一个指向处理窗口消息函数的指针,设置窗口处理函数的函数名WndProcwc.lpfnWndProc = WndProc;//cbClsExtra是WNDCLASSEX之后额外申请的字节数wc.cbClsExtra = NULL;//cbWndExtra指定窗口实例之后所申请的字节数wc.cbWndExtra = NULL;//当前窗口应用程序的句柄,通过给函数GetModuleHandle()函数第一个参数传入NULL可获取当前窗口应用程序。wc.hInstance = hInstance;//hIcon用来指定窗口标题栏左上角的图标。以下是一些标准图标:/**IDI_APPLICATION 默认应用程序图标*IDI_HAND 手形状的图标*IDI_EXCLAMATION 感叹号图标*IDI_INFORMATION 星号图标*IDI_QUESTION 问号图标*IDI_WINLOGO 若使用的是XP则是默认应用程序图标,否则是窗口logo*/wc.hIcon = LoadIcon(NULL, (LPCTSTR)IDI_SMALL);/*定义光标图标*IDC_APPSTARTING 标准箭头以及小型沙漏光标*IDC_ARROW 标准箭头光标*IDC_CROSS 十字线光标*IDC_HAND 手型光标*IDC_NO 斜线圈光标*IDC_WAIT 沙漏光标*/wc.hCursor = LoadCursor(NULL, IDC_ARROW);//hbrBackground是一个刷子的句柄,可使得背景黑色。wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW + 2);//附加到窗口的菜单名字,不需要的话设置为NULLwc.lpszMenuName = NULL;//对类进行命名wc.lpszClassName = WndClassName;//指定任务栏的图标,使用上面的IDI_图标wc.hIconSm = LoadIcon(NULL, (LPCTSTR)IDI_MYICON);//注册类。若失败则会获得一个错误,若成功,则继续创建窗口if (!RegisterClassEx(&wc)){MessageBox(NULL, "Error registering class", "Error", MB_OK | MB_ICONERROR);return 1;}//创建窗口hwnd = CreateWindowEx(NULL, WndClassName, "Rotating Cube", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width,height, NULL, NULL, hInstance, NULL);if (!hwnd){MessageBox(NULL, "Error registering class", "Error", MB_OK | MB_ICONERROR);return 1;}//BOOL ShowWindow(HWND hWnd, int nCmdShow);//BOOL UpdateWindow(HWND hWnd);ShowWindow(hwnd, ShowWnd);UpdateWindow(hwnd);// 发送WM_PAINT消息到窗口过程,若窗口客户区没有任何东西要显示,则不发送消息。返回true,继续运行到mainloop中去。return true;}bool InitializeDirect3d11App(HINSTANCE hInstance){//声明缓冲DXGI_MODE_DESC bufferDesc;ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));bufferDesc.Width = Width;bufferDesc.Height = Height;bufferDesc.RefreshRate.Numerator = 60;bufferDesc.RefreshRate.Denominator = 1;bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;//声明交换链DXGI_SWAP_CHAIN_DESC swapChainDesc;ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));swapChainDesc.BufferDesc = bufferDesc;swapChainDesc.SampleDesc.Count = 1;swapChainDesc.SampleDesc.Quality = 0;swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;swapChainDesc.BufferCount = 1;swapChainDesc.OutputWindow = hwnd;swapChainDesc.Windowed = TRUE;swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;//创建交换链D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);//创建后缓冲ID3D11Texture2D* BackBuffer;SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&BackBuffer);//创建渲染目标d3d11Device->CreateRenderTargetView(BackBuffer, NULL, &renderTargetView);BackBuffer->Release();//创建深度模板缓冲D3D11_TEXTURE2D_DESC depthStencilDesc;depthStencilDesc.Width = Width;depthStencilDesc.Height = Height;depthStencilDesc.MipLevels = 1;depthStencilDesc.ArraySize = 1;depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;depthStencilDesc.SampleDesc.Count = 1;depthStencilDesc.SampleDesc.Quality = 0;depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; //绑定到OMdepthStencilDesc.CPUAccessFlags = 0;depthStencilDesc.MiscFlags = 0;//创建深度模板视图d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);//设置渲染目标d3d11DevCon->OMSetRenderTargets(1, &renderTargetView, depthStencilView);return true;}void CleanUp(){SwapChain->Release();d3d11Device->Release();d3d11DevCon->Release();renderTargetView->Release();squareVertBuffer->Release();squareIndexBuffer->Release();//triangleVertBuffer->Release();VS->Release();PS->Release();VS_Buffer->Release();PS_Buffer->Release();vertLayout->Release();depthStencilView->Release();depthStencilBuffer->Release();//cbPerObjectBuffer->Release();//释放不裁剪对象noCull->Release();//释放混合对象#if 0Transparency->Release();CCWcullMode->Release();CWcullMode->Release();#endif//释放线框//WireFrame->Release();}void ReleaseObjects(){//释放创建的COM对象SwapChain->Release();d3d11Device->Release();d3d11DevCon->Release();}bool InitScene(){//编译着色器hr = D3DX11CompileFromFile("Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0);hr = D3DX11CompileFromFile("Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0);//创建着色器对象hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);hr = d3d11Device->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS);//设置顶点和像素着色器d3d11DevCon->VSSetShader(VS, 0, 0);d3d11DevCon->PSSetShader(PS, 0, 0);//创建顶点缓冲Vertex v[] = {#if 1// Front FaceVertex(-1.0f, -1.0f, -1.0f, 0.0f, 1.0f),Vertex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f),Vertex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f),Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 1.0f),// Back FaceVertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f),Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 1.0f),Vertex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f),Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f),// Top FaceVertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f),Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f),Vertex(1.0f, 1.0f, 1.0f, 1.0f, 0.0f),Vertex(1.0f, 1.0f, -1.0f, 1.0f, 1.0f),// Bottom FaceVertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f),Vertex(1.0f, -1.0f, -1.0f, 0.0f, 1.0f),Vertex(1.0f, -1.0f, 1.0f, 0.0f, 0.0f),Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 0.0f),// Left FaceVertex(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f),Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f),Vertex(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f),Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f),// Right FaceVertex(1.0f, -1.0f, -1.0f, 0.0f, 1.0f),Vertex(1.0f, 1.0f, -1.0f, 0.0f, 0.0f),Vertex(1.0f, 1.0f, 1.0f, 1.0f, 0.0f),Vertex(1.0f, -1.0f, 1.0f, 1.0f, 1.0f),#elseVertex(-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f),Vertex(-1.0f, +1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f),Vertex(+1.0f, +1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f),Vertex(+1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f),Vertex(-1.0f, -1.0f, +1.0f, 0.0f, 1.0f, 1.0f, 1.0f),Vertex(-1.0f, +1.0f, +1.0f, 1.0f, 1.0f, 1.0f, 1.0f),Vertex(+1.0f, +1.0f, +1.0f, 1.0f, 0.0f, 1.0f, 1.0f),Vertex(+1.0f, -1.0f, +1.0f, 1.0f, 0.0f, 0.0f, 1.0f),#endif};DWORD indices[] = {// Front Face0,  1,  2,0,  2,  3,// Back Face4,  5,  6,4,  6,  7,// Top Face8,  9, 10,8, 10, 11,// Bottom Face12, 13, 14,12, 14, 15,// Left Face16, 17, 18,16, 18, 19,// Right Face20, 21, 22,20, 22, 23};D3D11_BUFFER_DESC indexBufferDesc;ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;indexBufferDesc.ByteWidth = sizeof(DWORD) * 12 * 3;indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;indexBufferDesc.CPUAccessFlags = 0;indexBufferDesc.MiscFlags = 0;D3D11_SUBRESOURCE_DATA iinitData;iinitData.pSysMem = indices;d3d11Device->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);d3d11DevCon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);D3D11_BUFFER_DESC vertexBufferDesc;ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;vertexBufferDesc.ByteWidth = sizeof(Vertex) * 24;vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;vertexBufferDesc.CPUAccessFlags = 0;vertexBufferDesc.MiscFlags = 0;D3D11_SUBRESOURCE_DATA vertexBufferData;ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));vertexBufferData.pSysMem = v;hr = d3d11Device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer);//设置顶点缓冲UINT stride = sizeof(Vertex);UINT offset = 0;d3d11DevCon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);//创建输入布局d3d11Device->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),VS_Buffer->GetBufferSize(), &vertLayout);//设置输入布局d3d11DevCon->IASetInputLayout(vertLayout);//设置图元拓扑d3d11DevCon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);//创建视口D3D11_VIEWPORT viewport;ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));viewport.TopLeftX = 0;viewport.TopLeftY = 0;viewport.Width = Width;viewport.Height = Height;viewport.MinDepth = 0;viewport.MaxDepth = 1;//设置视口d3d11DevCon->RSSetViewports(1, &viewport);//创建缓冲用来发送到效果文件的cbufferD3D11_BUFFER_DESC cbbd;ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));cbbd.Usage = D3D11_USAGE_DEFAULT;cbbd.ByteWidth = sizeof(cbPerObject);cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;cbbd.CPUAccessFlags = 0;cbbd.MiscFlags = 0;hr = d3d11Device->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);//相机信息//相机信息camPosition = XMVectorSet(0.0f, 3.0f, -8.0f, 0.0f);//camPosition = XMVectorSet(0.0f, 0.0f, -0.5f, 0.0f);camTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);camUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);//设置视图矩阵camView = XMMatrixLookAtLH(camPosition, camTarget, camUp);//设置投影矩阵camProjection = XMMatrixPerspectiveFovLH(0.4f*3.14f, (float)Width / Height, 1.0f, 1000.0f);//加载图像纹理//hr = //#if 1hr = D3DX11CreateShaderResourceViewFromFile(d3d11Device, "Eye.png", NULL, NULL, &CubesTexture, NULL);//配置采样状态D3D11_SAMPLER_DESC sampDesc;ZeroMemory(&sampDesc, sizeof(sampDesc));sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;sampDesc.MinLOD = 0;sampDesc.MaxLOD = D3D11_FLOAT32_MAX;//创建采样状态hr = d3d11Device->CreateSamplerState(&sampDesc, &CubesTexSamplerState);//声明光栅化描述符D3D11_RASTERIZER_DESC rastDesc;ZeroMemory(&rastDesc, sizeof(D3D11_RASTERIZER_DESC));rastDesc.FillMode = D3D11_FILL_SOLID;rastDesc.CullMode = D3D11_CULL_NONE;d3d11Device->CreateRasterizerState(&rastDesc, &noCull);#if 0#if 1//定义混合方程式D3D11_BLEND_DESC blendDesc;ZeroMemory(&blendDesc, sizeof(blendDesc));D3D11_RENDER_TARGET_BLEND_DESC rtbd;ZeroMemory(&rtbd, sizeof(rtbd));rtbd.BlendEnable = true;rtbd.SrcBlend = D3D11_BLEND_SRC_COLOR;rtbd.DestBlend = D3D11_BLEND_BLEND_FACTOR;rtbd.BlendOp = D3D11_BLEND_OP_ADD;rtbd.SrcBlendAlpha = D3D11_BLEND_ONE;rtbd.DestBlendAlpha = D3D11_BLEND_ZERO;rtbd.BlendOpAlpha = D3D11_BLEND_OP_ADD;rtbd.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;blendDesc.AlphaToCoverageEnable = false;blendDesc.RenderTarget[0] = rtbd;d3d11Device->CreateBlendState(&blendDesc, &Transparency);//创建逆时针和顺时针状态D3D11_RASTERIZER_DESC cmdesc;ZeroMemory(&cmdesc, sizeof(D3D11_RASTERIZER_DESC));cmdesc.FillMode = D3D11_FILL_SOLID;cmdesc.CullMode = D3D11_CULL_BACK;cmdesc.FrontCounterClockwise = true;hr = d3d11Device->CreateRasterizerState(&cmdesc, &CCWcullMode);cmdesc.FrontCounterClockwise = false;hr = d3d11Device->CreateRasterizerState(&cmdesc, &CWcullMode);#else//设置线框D3D11_RASTERIZER_DESC wfdesc;ZeroMemory(&wfdesc, sizeof(D3D11_RASTERIZER_DESC));wfdesc.FillMode = D3D11_FILL_WIREFRAME;wfdesc.CullMode = D3D11_CULL_NONE;hr = d3d11Device->CreateRasterizerState(&wfdesc, &WireFrame);d3d11DevCon->RSSetState(WireFrame);#endif#endifreturn true;}void UpdateScene(){// 更新场景颜色//让立方体旋转起来rot += 0.00005f;if (rot > 6.26f)rot = 0.0f;//复位cube1Worldcube1World = XMMatrixIdentity();//定义cube1的世界空间矩阵XMVECTOR rotaxis = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);Rotation = XMMatrixRotationAxis(rotaxis, rot);Translation = XMMatrixTranslation(0.0f, 0.0f, 4.0f);//用转换设置cube1的世界空间cube1World = Translation* Rotation;//复位cube2Worldcube2World = XMMatrixIdentity();//定义cube2的世界空间矩阵Rotation = XMMatrixRotationAxis(rotaxis, -rot);Scale = XMMatrixScaling(1.3f, 1.3f, 1.3f);//设置cube2的世界空间矩阵cube2World = Rotation * Scale;#if 0red += colormodr * 0.00005f;green += colormodg * 0.00002f;blue += colormodb * 0.00001f;if (red >= 1.0f || red <= 0.0f)colormodr *= -1;if (green >= 1.0f || green <= 0.0f)colormodg *= -1;if (blue >= 1.0f || blue <= 0.0f)colormodb *= -1;#endif}void DrawScene(){//将更新的颜色填充后缓冲//D3DXCOLOR bgColor(red, green, blue, 1.0f);float bgColor[4] = {(0.0f, 0.0f, 0.0f, 0.0f)};d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);//刷新深度模板视图d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);//使能默认光栅化状态d3d11DevCon->RSSetState(NULL);//绘制使用背面裁剪的对象//关闭背面裁剪d3d11DevCon->RSSetState(noCull);#if 0//微调混合方程式float blendFactor[] = { 0.65f, 0.65f, 0.65f, 1.0f };//为不透明对象设置默认混合状态d3d11DevCon->OMSetBlendState(0, 0, 0xffffffff);//渲染不透明对象//为透明对象设置混合状态d3d11DevCon->OMSetBlendState(Transparency, blendFactor, 0xffffffff);//透明深度排序//找到哪一个透明对象离相机更远//所以能够以深度排序渲染对象到渲染目标//找到从第一个立方体到相机的距离XMVECTOR cubePos = XMVectorZero();cubePos = XMVector3TransformCoord(cubePos, cube1World);float distX = XMVectorGetX(cubePos) - XMVectorGetX(camPosition);float distY = XMVectorGetY(cubePos) - XMVectorGetY(camPosition);float distZ = XMVectorGetZ(cubePos) - XMVectorGetZ(camPosition);float cube1Dist = distX*distX + distY*distY + distZ*distZ;//找打第二个立方体到相机的距离cubePos = XMVectorZero();cubePos = XMVector3TransformCoord(cubePos, cube2World);distX = XMVectorGetX(cubePos) - XMVectorGetX(camPosition);distY = XMVectorGetY(cubePos) - XMVectorGetY(camPosition);distZ = XMVectorGetZ(cubePos) - XMVectorGetZ(camPosition);float cube2Dist = distX*distX + distY*distY + distZ*distZ;//若第一个立方体距离小于第二个立方体if (cube1Dist < cube2Dist){//切换要绘制立方体的顺序XMMATRIX tempMatrix = cube1World;cube1World = cube2World;cube2World = tempMatrix;}#endif//设置WVP矩阵并将它送到效果文件中的常量缓冲中WVP = cube1World * camView * camProjection;cbPerObj.WVP = XMMatrixTranspose(WVP);d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);///d3d11DevCon->PSSetShaderResources(0, 1, &CubesTexture);d3d11DevCon->PSSetSamplers(0, 1, &CubesTexSamplerState);//逆时针剪裁先是因为需要立方体后边首先被渲染,所以前面会和它混合//d3d11DevCon->RSSetState(CCWcullMode);//绘制第一个立方体d3d11DevCon->DrawIndexed(36, 0, 0);////d3d11DevCon->RSSetState(CWcullMode);//d3d11DevCon->DrawIndexed(36, 0, 0);//设置世界/视图/投影矩阵,随后发送到效果文件的常量缓冲中//World = XMMatrixIdentity();WVP = cube2World * camView * camProjection;cbPerObj.WVP = XMMatrixTranspose(WVP);d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);///d3d11DevCon->PSSetShaderResources(0, 1, &CubesTexture);d3d11DevCon->PSSetSamplers(0, 1, &CubesTexSamplerState);////d3d11DevCon->RSSetState(CCWcullMode);//绘制第二个立方体d3d11DevCon->DrawIndexed(36, 0, 0);//绘制三角形//d3d11DevCon->DrawIndexed(6, 0, 0);//画三角形//d3d11DevCon->Draw(3, 0);////d3d11DevCon->RSSetState(CWcullMode);//d3d11DevCon->DrawIndexed(36, 0, 0);//将后缓冲呈现到屏幕SwapChain->Present(0, 0);}int messageloop(){MSG msg;ZeroMemory(&msg, sizeof(MSG));//清除结构体被设为NULL。while (true){//使用PeekMessage()检查是否有消息传进来/*LPMSG lpMsg 消息结构体的指针*HWND hWnd 发送消息的窗口句柄。若设为NULL,那么它会从当前程序中接收来自任何一个窗口的消息*UINT wMsgFilterMin 指定消息范围内第一个要检查的消息的值。若wMsgFilterMin和wMsgFilterMax都设为0,那么PeekMessage将会检查素有的消息*UINT wMsgFilterMax 指定消息范围内最后一个要检测的消息的值*UINT wRemoveMsg 指定消息的处理方式。若设置为PM_REMOVE,则在读取之后会被删除*/if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){if (msg.message == WM_QUIT){break;}//若消息为窗口消息,则解析并分发它。TranslateMessage()将会让窗口做一些解析,类似键盘的虚拟键值转换到字符形式。//而DispatchMessage()则发送消息到窗口过程WndProc。TranslateMessage(&msg);DispatchMessage(&msg);}else //若没有窗口消息,则运行游戏{ // run game codeUpdateScene();DrawScene();}}return msg.wParam;}//窗口消息处理函数//HWND hwnd 获取消息的窗口句柄//UINT msg 消息的内容/**WM_ACTIVE 当窗口激活时发送的消息*WM_CLOSE 当窗口关闭时发送的消息*WM_CREATE 当窗口创建时发送的消息*WM_DESTROY 当窗口销毁时发送的消息*///wParam和lParam时消息的额外信息。使用wParam来检测键盘输入消息LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){// 这是事件检测消息的地方,若escape键被按下,会显示一个消息框,询问是否真的退出。若点击yes,则程序关闭。若不点击,则消息框关闭。若消息包含WM_DESTROY// 则意味着窗口正在被销毁,返回0并且程序关闭switch (msg){case WM_KEYDOWN:if (wParam == VK_ESCAPE){if (MessageBox(0, "Are you sure you want to exit?","Really?", MB_YESNO | MB_ICONASTERISK) == IDYES){DestroyWindow(hwnd);}return 0;}break;case WM_DESTROY:PostQuitMessage(0);break;default:break;}//调用默认窗口过程函数return DefWindowProc(hwnd,msg,wParam,lParam);}



eye.png图片如下:



效果如下:





参考网址