This tutorial is part of a Collection: 02. DirectX 10 - Braynzar Soft Tutorials
1962
views
13. Blending
In this lesson, we will go over how to create a simple transparent cube in DirectX.
In this lessons, we will learn how to create a simple rotating transparent cube using blending. This lessons modifies the Textures lesson. First we render our opaque objects onto the back buffer. After we have rendered those, we render our transparent objects, the ones that use blending, so the transparent objects pixels can be combined with the pixels already on the back buffer. That's how blending works In just a minute i will explain more about the blending equation. I'm just going to quickly point out a couple values i changed, i've already covered these values in previous lessons, so if you don't understand them, just play around with them. Position = D3DXVECTOR3( 0.0f, 0.0f, -8.0f ); D3DXVECTOR3 rotaxis(0.3f, 1.0f, 0.6f); rot += .0002f; So first off, you can see we are initializing a couple new interfaces, one for our transparency (blend state), and two rasterizer states (one for clockwise culling, and the other for counter-clockwise culling, we'll explain when we get a little further). ID3D10BlendState* Transparency; ID3D10RasterizerState* CCWcullMode; ID3D10RasterizerState* CWcullMode; Now jump down to the bottom of our initialize scene function, and you will see some new code. This is where we will fill our our blending description, so direct3d knows how we should be combining the pixels to create the transparency effect. The Direct3D Blending Equation: I will explain the equation direct3d uses to combine the source pixel (SP) (pixel currently being rasterized) and the destination pixel (DP) (pixel already on the back buffer). (FC) - Final Color (SP) - Source Pixel (DP) - Destination Pixel (SBF) - Source Blend Factor (DBF) - Destination Blend Factor (FA) - Final Alpha (SA) - Source Alpha (DA) - Destination Alpha (+) - Binaray Operator described below (X) - Cross Multiply Matrices Direct3d uses two different blending equations. One for color, and one for alpha. There are two different equations for color and alpha because we are able to process them both differently if we want using different operators and different blend factors. The two equationes are as follows: (FC) = (SP) (X) (SBF) (+) (DP) (X) (DPF) (FA) = (SA)(SBF) (+) (DA)(DBF) The binary (+) operator can be one of the following: typedef enum D3D10_BLEND_OP { D3D10_BLEND_OP_ADD = 1, D3D10_BLEND_OP_SUBTRACT = 2, D3D10_BLEND_OP_REV_SUBTRACT = 3, D3D10_BLEND_OP_MIN = 4, D3D10_BLEND_OP_MAX = 5 } D3D10_BLEND_OP; Play with them to get an idea of the different effects they cause. We use the blend factors to achieve different effects when blending. The set the blend factors with the D3D10_BLEND enumerated type. Play with the following to see the different effects we can get when blending: typedef enum D3D10_BLEND { D3D10_BLEND_ZERO = 1, D3D10_BLEND_ONE = 2, D3D10_BLEND_SRC_COLOR = 3, D3D10_BLEND_INV_SRC_COLOR = 4, D3D10_BLEND_SRC_ALPHA = 5, D3D10_BLEND_INV_SRC_ALPHA = 6, D3D10_BLEND_DEST_ALPHA = 7, D3D10_BLEND_INV_DEST_ALPHA = 8, D3D10_BLEND_DEST_COLOR = 9, D3D10_BLEND_INV_DEST_COLOR = 10, D3D10_BLEND_SRC_ALPHA_SAT = 11, D3D10_BLEND_BLEND_FACTOR = 14, D3D10_BLEND_INV_BLEND_FACTOR = 15, D3D10_BLEND_SRC1_COLOR = 16, D3D10_BLEND_INV_SRC1_COLOR = 17, D3D10_BLEND_SRC1_ALPHA = 18, D3D10_BLEND_INV_SRC1_ALPHA = 19 } D3D10_BLEND; **D3D10_BLEND_ZERO** - The data source is the color black (0, 0, 0, 0). No pre-blend operation. **D3D10_BLEND_ONE** - The data source is the color white (1, 1, 1, 1). No pre-blend operation. **D3D10_BLEND_SRC_COLOR** - The data source is color data (RGB) from a pixel shader. No pre-blend operation. **D3D10_BLEND_INV_SRC_COLOR** - The data source is color data (RGB) from a pixel shader. The pre-blend operation inverts the data, generating 1 - RGB. **D3D10_BLEND_SRC_ALPHA** - The data source is alpha data (A) from a pixel shader. No pre-blend operation. **D3D10_BLEND_INV_SRC_ALPHA** - The data source is alpha data (A) from a pixel shader. The pre-blend operation inverts the data, generating 1 - A. **D3D10_BLEND_DEST_ALPHA** - The data source is alpha data from a rendertarget. No pre-blend operation. **D3D10_BLEND_INV_DEST_ALPHA** - The data source is alpha data from a rendertarget. The pre-blend operation inverts the data, generating 1 - A. **D3D10_BLEND_DEST_COLOR** - The data source is color data from a rendertarget. No pre-blend operation. **D3D10_BLEND_INV_DEST_COLOR** - The data source is color data from a rendertarget. The pre-blend operation inverts the data, generating 1 - RGB. **D3D10_BLEND_SRC_ALPHA_SAT** - The data source is alpha data from a pixel shader. The pre-blend operation clamps the data to 1 or less. **D3D10_BLEND_BLEND_FACTOR** - The data source is the blend factor set with ID3D10Device::OMSetBlendState. No pre-blend operation. **D3D10_BLEND_INV_BLEND_FACTOR** - The data source is the blend factor set with ID3D10Device::OMSetBlendState. The pre-blend operation inverts the blend factor, generating 1 - blend_factor. **D3D10_BLEND_SRC1_COLOR** - The data sources are both color data output by a pixel shader. There is no pre-blend operation. This options supports dual-source color blending. **D3D10_BLEND_INV_SRC1_COLOR** - The data sources are both color data output by a pixel shader. The pre-blend operation inverts the data, generating 1 - RGB. This options supports dual-source color blending. **D3D10_BLEND_SRC1_ALPHA** - The data sources are alpha data output by a pixel shader. There is no pre-blend operation. This options supports dual-source color blending. **D3D10_BLEND_INV_SRC1_ALPHA** - The data sources are alpha data output by a pixel shader. The pre-blend operation inverts the data, generating 1 - A. This options supports dual-source color blending. ^^^From msdn^^^ Now we need to create a blend description, which tells direct3d how we will be blending our pixels. To create a blend description, we need to fill out a D3D10_BLEND_DESC structure: typedef struct D3D10_BLEND_DESC { BOOL AlphaToCoverageEnable; BOOL BlendEnable[8]; D3D10_BLEND SrcBlend; D3D10_BLEND DestBlend; D3D10_BLEND_OP BlendOp; D3D10_BLEND SrcBlendAlpha; D3D10_BLEND DestBlendAlpha; D3D10_BLEND_OP BlendOpAlpha; UINT8 RenderTargetWriteMask[8]; } D3D10_BLEND_DESC; **AlphaToCoverageEnable** - Multisampling technique usefull for things like wire fences and stuff, we'll talk about this more in a later lesson, specify true to enable. **BlendEnable[8]** - Specify true to enable blending. It is an array, one for each of the render targets it is possible to bind to the output-merger stage. **SrcBlend** - This is our source blend factor (SBF). We can set this to any of the enumerated D3D10_BLEND types. **DestBlend** - This is our destination blend factor (DBF). We can set this to any of the enumerated D3D10_BLEND types. **BlendOp** - Here is where we specify the blending operation to use which we discussed earlier. Set this to any of the D3D10_BLEND_OP enumerated types. **SrcBlendAlpha** - This is our source blend factor for the alpha channel (SBF). We can set this to any of the enumerated D3D10_BLEND types. **DestBlendAlpha** - This is our destination blend factor for the alpha channel (SBF). We can set this to any of the enumerated D3D10_BLEND types. **BlendOpAlpha** - Here we specify the blending operation to use for the alpha channels. set this to any of the D3D10_BLEND_OP enumerated types. RenderTargetWriteMask[8] - This is where we specify which channel to blend. We are able to choose R, G, B, A, All of them, or a combination of them by specifying one of the following flags: (As you can see it is another array of 8, corresponding to each of the possible render targets currently bound to the output merger stage of the pipeline. typedef enum D3D10_COLOR_WRITE_ENABLE { D3D10_COLOR_WRITE_ENABLE_RED = 1, D3D10_COLOR_WRITE_ENABLE_GREEN = 2, D3D10_COLOR_WRITE_ENABLE_BLUE = 4, D3D10_COLOR_WRITE_ENABLE_ALPHA = 8, D3D10_COLOR_WRITE_ENABLE_ALL = ( D3D10_COLOR_WRITE_ENABLE_RED | D3D10_COLOR_WRITE_ENABLE_GREEN | D3D10_COLOR_WRITE_ENABLE_BLUE | D3D10_COLOR_WRITE_ENABLE_ALPHA ) } D3D10_COLOR_WRITE_ENABLE; D3D10_BLEND_DESC blendDesc = {0}; blendDesc.AlphaToCoverageEnable = false; blendDesc.BlendEnable[0] = true; blendDesc.SrcBlend = D3D10_BLEND_SRC_COLOR; blendDesc.DestBlend = D3D10_BLEND_BLEND_FACTOR; blendDesc.BlendOp = D3D10_BLEND_OP_ADD; blendDesc.SrcBlendAlpha = D3D10_BLEND_ONE; blendDesc.DestBlendAlpha = D3D10_BLEND_ZERO; blendDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; blendDesc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; After we have defined our blend description, we need to create it using the ID3D10Device::CreateBlendState interface HRESULT CreateBlendState( [in] const D3D10_BLEND_DESC *pBlendStateDesc, [out] ID3D10BlendState **ppBlendState ); **pBlendStateDesc** - Pointer to our blend description ppBlendState - Pointer to store our blend state in d3dDevice->CreateBlendState(&blendDesc, &Transparency); Next, we are going to create our two rasterizer states, one for counter clockwise culling, and the other for clockwise culling. The reason we are doing this is because we are trying to make a transparent cube, and be able to see the backside of the cube as it spins around. We will need to draw two cubes to do this, one with CCW culling, and the other with CW culling. If you try to draw just one cube, turning off backface culling, you will see that it does not render correctly, some of the faces on the backside of the cube will dissapear as it spins around, and the front face of the cube is not transparent at all. We have already covered rasterizer states in a previous lessons, so I will not explain this part of the code. D3D10_RASTERIZER_DESC cmdesc; ZeroMemory(&cmdesc, sizeof(D3D10_RASTERIZER_DESC)); cmdesc.FillMode = D3D10_FILL_SOLID; cmdesc.CullMode = D3D10_CULL_BACK; cmdesc.FrontCounterClockwise = true; hr = d3dDevice->CreateRasterizerState(&cmdesc, &CCWcullMode); if(FAILED(hr)) { MessageBox(0, L"RS STATE Creation - Failed", L"Error", MB_OK); return false; } cmdesc.FrontCounterClockwise = false; hr = d3dDevice->CreateRasterizerState(&cmdesc, &CWcullMode); if(FAILED(hr)) { MessageBox(0, L"RS STATE Creation - Failed", L"Error", MB_OK); return false; } Now lets jump down to our draw scene function. The new line here is the blend factor we will use in our blending equation. Note that we do not need this if we do not specify D3D10_BLEND_INV_BLEND_FACTOR or D3D10_BLEND_BLEND_FACTOR in our blend description. What this blend factor we have created will do is make our object 75% transparent, because of the blend description we have created. float blendFactor[] = {0.75f, 0.75f, 0.75f, 1.0f}; To bind our blend state object to the output merget stage, we will call the ID3D10Device::OMSetBlendState method. void OMSetBlendState( [in] ID3D10BlendState *pBlendState, [in] const FLOAT BlendFactor[4], [in] UINT SampleMask ); **pBlendState** - This is a pointer to our created blend state interface from above. Setting this to null tells direct3d to use the default blending state. **BlendFactor[4]** - This is the array of four floats we created at the beginning of the draw scene function specifying the blend factor to use. This is only used when we specify D3D10_BLEND_BLEND_FACTOR or D3D10_BLEND_INV_BLEND_FACTOR as the blend factor in our blend description. **SampleMask** - This is used to disable one or more bits of multisampling if we are using multisampling. Usually we use the default of 0xffffffff which doesn't turn off any of the multisampling bits. The line below will set our blend state to null, so direct3d knows that we are not blending at this point. All your opaque objects (objects that are not transparent) will be drawn after this line, until we turn on blending, which then we will draw all our transparent objects. We need to draw our non transparent objects first, so that our transparent objects know which objects to blend with. d3dDevice->OMSetBlendState(0, 0, 0xffffffff); Here we bind our created blend state to the output merger using the blendFactor array we created at the beginning of the draw scene function. d3dDevice->OMSetBlendState(Transparency, blendFactor, 0xffffffff); Now we finally draw our transparent stuff. First we set our rasterizer state to CCW culling, so that geometry drawn counterclockwise will be the front side, and the other side will be culled (not shown). then we draw our first cube. After that set our rasterizer state to CW culling, so that geometry drawn clockwise will be the front side, and the other side will be culled (not shown). Doing this will enable us to see the backside of the cube as it rotates. If this does not make sense go ahead and send me a message and i'll elaborate. d3dDevice->RSSetState(CCWcullMode); for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } d3dDevice->RSSetState(CWcullMode); for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } Thats all we have for blending, we can do many cool things with blending, and in the next lesson i'll show you how to mask using blending. see you then! Here's the final code: main.cpp #include <Windows.h> #include <d3d10.h> #include <d3dx10.h> #include <string> #pragma comment(lib, "D3D10.lib") #pragma comment(lib, "d3dx10d.lib") LPCTSTR WndClassName = L"firstwindow"; HWND hwnd = NULL; const int Width = 800; const int Height = 600; bool InitializeWindow(HINSTANCE hInstance, int ShowWnd, int width, int height, bool windowed); HRESULT hr; ID3D10Device* d3dDevice; IDXGISwapChain* SwapChain; ID3D10RenderTargetView* RenderTargetView; ID3D10Effect* FX; ID3D10InputLayout* VertexLayout; ID3D10Buffer* VertexBuffer; ID3D10Buffer* IndexBuffer; ////////////////////new////////////////////////////////////////////////////////////////////// ID3D10BlendState* Transparency; ID3D10RasterizerState* CCWcullMode; ID3D10RasterizerState* CWcullMode; ////////////////////new////////////////////////////////////////////////////////////////////// ID3D10EffectTechnique* Technique; ID3D10DepthStencilView* DepthStencilView; ID3D10Texture2D* DepthStencilBuffer; ID3D10ShaderResourceView* DiffuseMapResourceView; ID3D10EffectShaderResourceVariable* fxDiffuseMapVar; ID3D10EffectMatrixVariable* fxWVPVar; D3DXMATRIX WVP; D3DXMATRIX World; D3DXMATRIX View; D3DXMATRIX Projection; D3DXVECTOR3 Position; D3DXVECTOR3 Target; D3DXVECTOR3 Up; D3DXMATRIX Rotation; D3DXMATRIX Scale; D3DXMATRIX Translation; D3DXMATRIX Transformations; float rot = 0.01f; bool InitializeDirect3dApp(HINSTANCE hInstance); bool InitScene(); void DrawScene(); bool ReleaseObjects(); int messageloop(); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); struct Vertex { Vertex(){} Vertex(float x, float y, float z, float u, float v) : pos(x,y,z), texCoord(u,v){} D3DXVECTOR3 pos; D3DXVECTOR2 texCoord; }; int WINAPI WinMain(HINSTANCE hInstance, //Main windows function HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true)) { MessageBox(0, L"Window Initialization - Failed", L"Error", MB_OK); return 0; } if(!InitializeDirect3dApp(hInstance)) { MessageBox(0, L"Direct3D Initialization - Failed", L"Error", MB_OK); return 0; } if(!InitScene()) { MessageBox(0, L"Scene Initialization - Failed", L"Error", MB_OK); return 0; } messageloop(); if(!ReleaseObjects()) { MessageBox(0, L"Object Releasing - Failed", L"Error", MB_OK); return 0; } return 0; } 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); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2); wc.lpszMenuName = NULL; wc.lpszClassName = WndClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx(&wc)) { MessageBox(NULL, L"Error registering class", L"Error", MB_OK | MB_ICONERROR); return 1; } hwnd = CreateWindowEx( NULL, WndClassName, L"Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL ); if (!hwnd) { MessageBox(NULL, L"Error creating window", L"Error", MB_OK | MB_ICONERROR); return 1; } ShowWindow(hwnd, ShowWnd); UpdateWindow(hwnd); return true; } bool InitializeDirect3dApp(HINSTANCE hInstance) { UINT createDeviceFlags = 0; D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC scd; scd.BufferDesc.Width = Width; scd.BufferDesc.Height = Height; scd.BufferDesc.RefreshRate.Numerator = 60; scd.BufferDesc.RefreshRate.Denominator = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //no multisampling scd.SampleDesc.Count = 1; scd.SampleDesc.Quality = 0; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 1; scd.OutputWindow = hwnd; scd.Windowed = true; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Flags = 0; D3D10CreateDeviceAndSwapChain(0, D3D10_DRIVER_TYPE_HARDWARE, 0, 0, D3D10_SDK_VERSION, &scd, &SwapChain, &d3dDevice); ID3D10Texture2D* backBuffer; SwapChain->GetBuffer(0, _uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)); d3dDevice->CreateRenderTargetView(backBuffer, 0, &RenderTargetView); backBuffer->Release(); D3D10_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 = D3D10_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; d3dDevice->CreateTexture2D(&depthStencilDesc, NULL, &DepthStencilBuffer); d3dDevice->CreateDepthStencilView(DepthStencilBuffer, NULL, &DepthStencilView); d3dDevice->OMSetRenderTargets(1, &RenderTargetView, DepthStencilView); // Setup the viewport D3D10_VIEWPORT vp; vp.Width = Width; vp.Height = Height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; d3dDevice->RSSetViewports( 1, &vp ); D3DXMatrixIdentity( &World ); Position = D3DXVECTOR3( 0.0f, 0.0f, -8.0f ); Target = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); Up = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &View, &Position, &Target, &Up ); return true; } bool InitScene() { Vertex v[24]; // Front Face v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 1.0f); v[1] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f); v[2] = Vertex( 1.0f, 1.0f, -1.0f, 1.0f, 0.0f); v[3] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 1.0f); // Back Face v[4] = Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f); v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 1.0f); v[6] = Vertex( 1.0f, 1.0f, 1.0f, 0.0f, 0.0f); v[7] = Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f); // Top Face v[8] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f); v[9] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f); v[10] = Vertex( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f); v[11] = Vertex( 1.0f, 1.0f, -1.0f, 1.0f, 1.0f); // Bottom Face v[12] = Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f); v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 1.0f); v[14] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f); v[15] = Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 0.0f); // Left Face v[16] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f); v[17] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f); v[18] = Vertex(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f); v[19] = Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f); // Right Face v[20] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 1.0f); v[21] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 0.0f); v[22] = Vertex( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f); v[23] = Vertex( 1.0f, -1.0f, 1.0f, 1.0f, 1.0f); D3D10_BUFFER_DESC vbd; vbd.Usage = D3D10_USAGE_IMMUTABLE; vbd.ByteWidth = sizeof(Vertex) * 24; vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER; vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA vinitData; vinitData.pSysMem = v; d3dDevice->CreateBuffer(&vbd, &vinitData, &VertexBuffer); DWORD i[36]; // Front Face i[0] = 0; i[1] = 1; i[2] = 2; i[3] = 0; i[4] = 2; i[5] = 3; // Back Face i[6] = 4; i[7] = 5; i[8] = 6; i[9] = 4; i[10] = 6; i[11] = 7; // Top Face i[12] = 8; i[13] = 9; i[14] = 10; i[15] = 8; i[16] = 10; i[17] = 11; // Bottom Face i[18] = 12; i[19] = 13; i[20] = 14; i[21] = 12; i[22] = 14; i[23] = 15; // Left Face i[24] = 16; i[25] = 17; i[26] = 18; i[27] = 16; i[28] = 18; i[29] = 19; // Right Face i[30] = 20; i[31] = 21; i[32] = 22; i[33] = 20; i[34] = 22; i[35] = 23; D3D10_BUFFER_DESC ibd; ibd.Usage = D3D10_USAGE_IMMUTABLE; ibd.ByteWidth = sizeof(DWORD) * 36; ibd.BindFlags = D3D10_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; ibd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = i; d3dDevice->CreateBuffer(&ibd, &iinitData, &IndexBuffer); UINT stride = sizeof( Vertex ); UINT offset = 0; d3dDevice->IASetVertexBuffers( 0, 1, &VertexBuffer, &stride, &offset ); d3dDevice->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); D3D10_INPUT_ELEMENT_DESC layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0} }; ID3D10Blob* compilationErrors = 0; HRESULT hr = 0; hr = D3DX10CreateEffectFromFile( L"vertex.fx", NULL, NULL, "fx_4_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, d3dDevice, NULL, NULL, &FX, &compilationErrors, NULL ); if(FAILED(hr)) { MessageBoxA(0, (char*)compilationErrors->GetBufferPointer(), 0, 0); compilationErrors->Release(); return false; } D3DX10CreateShaderResourceViewFromFile(d3dDevice, L"braynzar.jpg", 0, 0, &DiffuseMapResourceView, 0 ); Technique = FX->GetTechniqueByName( "Tech" ); fxWVPVar = FX->GetVariableByName("WVP")->AsMatrix(); fxDiffuseMapVar = FX->GetVariableByName("DiffuseMap")->AsShaderResource(); D3D10_PASS_DESC PassDesc; Technique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); d3dDevice->CreateInputLayout( layout, 2, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &VertexLayout ); d3dDevice->IASetInputLayout( VertexLayout ); d3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); ////////////////////new////////////////////////////////////////////////////////////////////// D3D10_BLEND_DESC blendDesc = {0}; blendDesc.AlphaToCoverageEnable = false; blendDesc.BlendEnable[0] = true; blendDesc.SrcBlend = D3D10_BLEND_SRC_COLOR; blendDesc.DestBlend = D3D10_BLEND_BLEND_FACTOR; blendDesc.BlendOp = D3D10_BLEND_OP_ADD; blendDesc.SrcBlendAlpha = D3D10_BLEND_ONE; blendDesc.DestBlendAlpha = D3D10_BLEND_ZERO; blendDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; blendDesc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; d3dDevice->CreateBlendState(&blendDesc, &Transparency); D3D10_RASTERIZER_DESC cmdesc; ZeroMemory(&cmdesc, sizeof(D3D10_RASTERIZER_DESC)); cmdesc.FillMode = D3D10_FILL_SOLID; cmdesc.CullMode = D3D10_CULL_BACK; cmdesc.FrontCounterClockwise = true; hr = d3dDevice->CreateRasterizerState(&cmdesc, &CCWcullMode); if(FAILED(hr)) { MessageBox(0, L"RS STATE Creation - Failed", L"Error", MB_OK); return false; } cmdesc.FrontCounterClockwise = false; hr = d3dDevice->CreateRasterizerState(&cmdesc, &CWcullMode); if(FAILED(hr)) { MessageBox(0, L"RS STATE Creation - Failed", L"Error", MB_OK); return false; } ////////////////////new////////////////////////////////////////////////////////////////////// return true; } bool ReleaseObjects() { if( d3dDevice ) d3dDevice->ClearState(); if( VertexBuffer ) VertexBuffer->Release(); if( IndexBuffer ) IndexBuffer->Release(); if( VertexLayout ) VertexLayout->Release(); if( FX ) FX->Release(); if( RenderTargetView ) RenderTargetView->Release(); if( SwapChain ) SwapChain->Release(); if( d3dDevice ) d3dDevice->Release(); if( DiffuseMapResourceView ) DiffuseMapResourceView->Release(); ////////////////////new////////////////////////////////////////////////////////////////////// if( Transparency ) Transparency->Release(); ////////////////////new////////////////////////////////////////////////////////////////////// return true; } void DrawScene() { //Draw Scene Here D3DXCOLOR bgColor( 0.0f, 0.0f, 0.0f, 1.0f); ////////////////////new////////////////////////////////////////////////////////////////////// float blendFactor[] = {0.75f, 0.75f, 0.75f, 1.0f}; ////////////////////new////////////////////////////////////////////////////////////////////// d3dDevice->ClearRenderTargetView( RenderTargetView, bgColor ); d3dDevice->ClearDepthStencilView(DepthStencilView, D3D10_CLEAR_DEPTH|D3D10_CLEAR_STENCIL, 1.0f, 0); D3DXMatrixPerspectiveFovLH(&Projection, 0.4f*3.14f, Width/Height, 1.0f, 1000.0f); D3DXVECTOR3 rotaxis(0.3f, 1.0f, 0.6f); D3DXMatrixRotationAxis(&Rotation, &rotaxis, rot); D3DXMatrixTranslation( &Translation, 0.0f, 0.0f, 4.0f ); Transformations =Translation * Rotation; rot += .0002f; WVP = World * Transformations * View * Projection; fxWVPVar->SetMatrix((float*)&WVP); fxDiffuseMapVar->SetResource(DiffuseMapResourceView); D3D10_TECHNIQUE_DESC techDesc; Technique->GetDesc( &techDesc ); ////////////////////new////////////////////////////////////////////////////////////////////// d3dDevice->OMSetBlendState(0, 0, 0xffffffff); //Draw opaque objects here ////////////////////new////////////////////////////////////////////////////////////////////// D3DXMatrixRotationAxis(&Rotation, &rotaxis, -rot); D3DXMatrixScaling( &Scale, 1.3f, 1.3f, 1.3f ); Transformations = Rotation * Scale; WVP = World * Transformations * View * Projection; fxWVPVar->SetMatrix((float*)&WVP); ////////////////////new////////////////////////////////////////////////////////////////////// d3dDevice->OMSetBlendState(Transparency, blendFactor, 0xffffffff); d3dDevice->RSSetState(CCWcullMode); //draw second cube for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } d3dDevice->RSSetState(CWcullMode); for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } ////////////////////new////////////////////////////////////////////////////////////////////// SwapChain->Present( 0, 0 ); } int messageloop(){ MSG msg; ZeroMemory(&msg, sizeof(MSG)); while(true) { BOOL PeekMessageL( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ); if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else{ // run game code DrawScene(); } } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_KEYDOWN: if( wParam == VK_ESCAPE ){ if(MessageBox(0, L"Are you sure you want to exit?", L"Really?", MB_YESNO | MB_ICONQUESTION) == IDYES) DestroyWindow(hwnd); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } vertex.fx cbuffer cbPerObject { float4x4 WVP; }; Texture2D DiffuseMap; SamplerState TriLinearSample { Filter = MIN_MAG_MIP_LINEAR; }; struct VS_OUTPUT //output structure for vertex shader { float4 Pos : SV_POSITION; float2 texCoord : TEXCOORD; }; // Vertex Shader VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD) { VS_OUTPUT output = (VS_OUTPUT)0; output.Pos = mul(inPos, WVP); output.texCoord = inTexCoord; return output; //send color and position to pixel shader } // Pixel Shader float4 PS(VS_OUTPUT input) : SV_Target { float4 diffuse = DiffuseMap.Sample( TriLinearSample, input.texCoord ); return diffuse; // Set the color of the pixel to the corresponding texel in the loaded image is. } technique10 Tech { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Sign in to comment