Related
I'm working on a code to capture the desktop using Desktop duplication and encode the same to h264 using Intel hardwareMFT. The encoder only accepts NV12 format as input. I have got a DXGI_FORMAT_B8G8R8A8_UNORM to NV12 converter(https://github.com/NVIDIA/video-sdk-samples/blob/master/nvEncDXGIOutputDuplicationSample/Preproc.cpp) that works fine, and is based on DirectX VideoProcessor.
The problem is that the VideoProcessor on certain intel graphics hardware supports conversions only from DXGI_FORMAT_B8G8R8A8_UNORM to YUY2 but not NV12, I have confirmed the same by enumerating the supported formats through GetVideoProcessorOutputFormats. Though the VideoProcessor Blt succeeded without any errors, and I could see that the frames in the output video are pixelated a bit, I could notice it if I look at it closely.
I guess, the VideoProcessor has simply failed over to the next supported output format (YUY2) and I'm unknowingly feeding it to the encoder that thinks that the input is in NV12 as configured. There is no failure or major corruption of frames due to the fact that there is little difference like byte order and subsampling between NV12 and YUY2. Also, I don't have pixelating problems on hardware that supports NV12 conversion.
So I decided to do the color conversion using pixel shaders which is based on this code(https://github.com/bavulapati/DXGICaptureDXColorSpaceConversionIntelEncode/blob/master/DXGICaptureDXColorSpaceConversionIntelEncode/DuplicationManager.cpp). I'm able make the pixel shaders work, I have also uploaded my code here(https://codeshare.io/5PJjxP) for reference (simplified it as much as possible).
Now, I'm left with two channels, chroma, and luma respectively
(ID3D11Texture2D textures). And I'm really confused about efficiently
packing the two separate channels into one ID3D11Texture2D texture so
that I may feed the same to the encoder. Is there a way to efficiently
pack the Y and UV channels into a single ID3D11Texture2D in GPU? I'm
really tired of CPU based approaches due to the fact that it's costly,
and doesn't offer the best possible frame rates. In fact, I'm
reluctant to even copy the textures to CPU. I'm thinking of a way to
do it in GPU without any back and forth copies between CPU and GPU.
I have been researching this for quite some time without any progress, any help would be appreciated.
/**
* This method is incomplete. It's just a template of what I want to achieve.
*/
HRESULT CreateNV12TextureFromLumaAndChromaSurface(ID3D11Texture2D** pOutputTexture)
{
HRESULT hr = S_OK;
try
{
//Copying from GPU to CPU. Bad :(
m_pD3D11DeviceContext->CopyResource(m_CPUAccessibleLuminanceSurf, m_LuminanceSurf);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
HRESULT hr = m_pD3D11DeviceContext->Map(m_CPUAccessibleLuminanceSurf, subresource, D3D11_MAP_READ, 0, &resource);
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptrY = nullptr; // point to the address of Y channel in output surface
//Store Image Pitch
int m_ImagePitch = resource.RowPitch;
int height = GetImageHeight();
int width = GetImageWidth();
for (int i = 0; i < height; i++)
{
memcpy_s(dptrY, m_ImagePitch, sptr, m_ImagePitch);
sptr += m_ImagePitch;
dptrY += m_ImagePitch;
}
m_pD3D11DeviceContext->Unmap(m_CPUAccessibleLuminanceSurf, subresource);
//Copying from GPU to CPU. Bad :(
m_pD3D11DeviceContext->CopyResource(m_CPUAccessibleChrominanceSurf, m_ChrominanceSurf);
hr = m_pD3D11DeviceContext->Map(m_CPUAccessibleChrominanceSurf, subresource, D3D11_MAP_READ, 0, &resource);
sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptrUV = nullptr; // point to the address of UV channel in output surface
m_ImagePitch = resource.RowPitch;
height /= 2;
width /= 2;
for (int i = 0; i < height; i++)
{
memcpy_s(dptrUV, m_ImagePitch, sptr, m_ImagePitch);
sptr += m_ImagePitch;
dptrUV += m_ImagePitch;
}
m_pD3D11DeviceContext->Unmap(m_CPUAccessibleChrominanceSurf, subresource);
}
catch(HRESULT){}
return hr;
}
Draw NV12:
//
// Draw frame for NV12 texture
//
HRESULT DrawNV12Frame(ID3D11Texture2D* inputTexture)
{
HRESULT hr;
// If window was resized, resize swapchain
if (!m_bIntialized)
{
HRESULT Ret = InitializeNV12Surfaces(inputTexture);
if (!SUCCEEDED(Ret))
{
return Ret;
}
m_bIntialized = true;
}
m_pD3D11DeviceContext->CopyResource(m_ShaderResourceSurf, inputTexture);
D3D11_TEXTURE2D_DESC FrameDesc;
m_ShaderResourceSurf->GetDesc(&FrameDesc);
D3D11_SHADER_RESOURCE_VIEW_DESC ShaderDesc;
ShaderDesc.Format = FrameDesc.Format;
ShaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
ShaderDesc.Texture2D.MostDetailedMip = FrameDesc.MipLevels - 1;
ShaderDesc.Texture2D.MipLevels = FrameDesc.MipLevels;
// Create new shader resource view
ID3D11ShaderResourceView* ShaderResource = nullptr;
hr = m_pD3D11Device->CreateShaderResourceView(m_ShaderResourceSurf, &ShaderDesc, &ShaderResource);
IF_FAILED_THROW(hr);
m_pD3D11DeviceContext->PSSetShaderResources(0, 1, &ShaderResource);
// Set resources
m_pD3D11DeviceContext->OMSetRenderTargets(1, &m_pLumaRT, nullptr);
m_pD3D11DeviceContext->PSSetShader(m_pPixelShaderLuma, nullptr, 0);
m_pD3D11DeviceContext->RSSetViewports(1, &m_VPLuminance);
// Draw textured quad onto render target
m_pD3D11DeviceContext->Draw(NUMVERTICES, 0);
m_pD3D11DeviceContext->OMSetRenderTargets(1, &m_pChromaRT, nullptr);
m_pD3D11DeviceContext->PSSetShader(m_pPixelShaderChroma, nullptr, 0);
m_pD3D11DeviceContext->RSSetViewports(1, &m_VPChrominance);
// Draw textured quad onto render target
m_pD3D11DeviceContext->Draw(NUMVERTICES, 0);
// Release shader resource
ShaderResource->Release();
ShaderResource = nullptr;
return S_OK;
}
Init shaders:
void SetViewPort(D3D11_VIEWPORT* VP, UINT Width, UINT Height)
{
VP->Width = static_cast<FLOAT>(Width);
VP->Height = static_cast<FLOAT>(Height);
VP->MinDepth = 0.0f;
VP->MaxDepth = 1.0f;
VP->TopLeftX = 0;
VP->TopLeftY = 0;
}
HRESULT MakeRTV(ID3D11RenderTargetView** pRTV, ID3D11Texture2D* pSurf)
{
if (*pRTV)
{
(*pRTV)->Release();
*pRTV = nullptr;
}
// Create a render target view
HRESULT hr = m_pD3D11Device->CreateRenderTargetView(pSurf, nullptr, pRTV);
IF_FAILED_THROW(hr);
return S_OK;
}
HRESULT InitializeNV12Surfaces(ID3D11Texture2D* inputTexture)
{
ReleaseSurfaces();
D3D11_TEXTURE2D_DESC lOutputDuplDesc;
inputTexture->GetDesc(&lOutputDuplDesc);
// Create shared texture for all duplication threads to draw into
D3D11_TEXTURE2D_DESC DeskTexD;
RtlZeroMemory(&DeskTexD, sizeof(D3D11_TEXTURE2D_DESC));
DeskTexD.Width = lOutputDuplDesc.Width;
DeskTexD.Height = lOutputDuplDesc.Height;
DeskTexD.MipLevels = 1;
DeskTexD.ArraySize = 1;
DeskTexD.Format = lOutputDuplDesc.Format;
DeskTexD.SampleDesc.Count = 1;
DeskTexD.Usage = D3D11_USAGE_DEFAULT;
DeskTexD.BindFlags = D3D11_BIND_SHADER_RESOURCE;
HRESULT hr = m_pD3D11Device->CreateTexture2D(&DeskTexD, nullptr, &m_ShaderResourceSurf);
IF_FAILED_THROW(hr);
DeskTexD.Format = DXGI_FORMAT_R8_UNORM;
DeskTexD.BindFlags = D3D11_BIND_RENDER_TARGET;
hr = m_pD3D11Device->CreateTexture2D(&DeskTexD, nullptr, &m_LuminanceSurf);
IF_FAILED_THROW(hr);
DeskTexD.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
DeskTexD.Usage = D3D11_USAGE_STAGING;
DeskTexD.BindFlags = 0;
hr = m_pD3D11Device->CreateTexture2D(&DeskTexD, NULL, &m_CPUAccessibleLuminanceSurf);
IF_FAILED_THROW(hr);
SetViewPort(&m_VPLuminance, DeskTexD.Width, DeskTexD.Height);
HRESULT Ret = MakeRTV(&m_pLumaRT, m_LuminanceSurf);
if (!SUCCEEDED(Ret))
return Ret;
DeskTexD.Width = lOutputDuplDesc.Width / 2;
DeskTexD.Height = lOutputDuplDesc.Height / 2;
DeskTexD.Format = DXGI_FORMAT_R8G8_UNORM;
DeskTexD.Usage = D3D11_USAGE_DEFAULT;
DeskTexD.CPUAccessFlags = 0;
DeskTexD.BindFlags = D3D11_BIND_RENDER_TARGET;
hr = m_pD3D11Device->CreateTexture2D(&DeskTexD, nullptr, &m_ChrominanceSurf);
IF_FAILED_THROW(hr);
DeskTexD.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
DeskTexD.Usage = D3D11_USAGE_STAGING;
DeskTexD.BindFlags = 0;
hr = m_pD3D11Device->CreateTexture2D(&DeskTexD, NULL, &m_CPUAccessibleChrominanceSurf);
IF_FAILED_THROW(hr);
SetViewPort(&m_VPChrominance, DeskTexD.Width, DeskTexD.Height);
return MakeRTV(&m_pChromaRT, m_ChrominanceSurf);
}
HRESULT InitVertexShader(ID3D11VertexShader** ppID3D11VertexShader)
{
HRESULT hr = S_OK;
UINT Size = ARRAYSIZE(g_VS);
try
{
IF_FAILED_THROW(m_pD3D11Device->CreateVertexShader(g_VS, Size, NULL, ppID3D11VertexShader));;
m_pD3D11DeviceContext->VSSetShader(m_pVertexShader, nullptr, 0);
// Vertices for drawing whole texture
VERTEX Vertices[NUMVERTICES] =
{
{ XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f) },
{ XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f) },
{ XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f) },
{ XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f) },
{ XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f) },
{ XMFLOAT3(1.0f, 1.0f, 0), XMFLOAT2(1.0f, 0.0f) },
};
UINT Stride = sizeof(VERTEX);
UINT Offset = 0;
D3D11_BUFFER_DESC BufferDesc;
RtlZeroMemory(&BufferDesc, sizeof(BufferDesc));
BufferDesc.Usage = D3D11_USAGE_DEFAULT;
BufferDesc.ByteWidth = sizeof(VERTEX) * NUMVERTICES;
BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
BufferDesc.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
RtlZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = Vertices;
// Create vertex buffer
IF_FAILED_THROW(m_pD3D11Device->CreateBuffer(&BufferDesc, &InitData, &m_VertexBuffer));
m_pD3D11DeviceContext->IASetVertexBuffers(0, 1, &m_VertexBuffer, &Stride, &Offset);
m_pD3D11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
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);
hr = m_pD3D11Device->CreateInputLayout(Layout, NumElements, g_VS, Size, &m_pVertexLayout);
m_pD3D11DeviceContext->IASetInputLayout(m_pVertexLayout);
}
catch (HRESULT) {}
return hr;
}
HRESULT InitPixelShaders()
{
HRESULT hr = S_OK;
// Refer https://codeshare.io/5PJjxP for g_PS_Y & g_PS_UV blobs
try
{
UINT Size = ARRAYSIZE(g_PS_Y);
hr = m_pD3D11Device->CreatePixelShader(g_PS_Y, Size, nullptr, &m_pPixelShaderChroma);
IF_FAILED_THROW(hr);
Size = ARRAYSIZE(g_PS_UV);
hr = m_pD3D11Device->CreatePixelShader(g_PS_UV, Size, nullptr, &m_pPixelShaderLuma);
IF_FAILED_THROW(hr);
}
catch (HRESULT) {}
return hr;
}
I am experimenting this RGBA conversion to NV12 in the GPU only, using DirectX11.
This is a good challenge. I'm not familiar with Directx11, so this is my first experimentation.
Check this project for updates : D3D11ShaderNV12
In my current implementation (may not be the last), here is what I do:
Step 1: use a DXGI_FORMAT_B8G8R8A8_UNORM as input texture
Step 2: make a 1st pass shader to get 3 textures (Y:Luma, U:ChromaCb and V:ChromaCr): see YCbCrPS2.hlsl
Step 3: Y is DXGI_FORMAT_R8_UNORM, and is ready for final NV12 texture
Step 4: UV needs to be downsampled in a 2nd pass shader: see ScreenPS2.hlsl (using linear filtering)
Step 5: a third pass shader to sample Y texture
Step 6: a fourth pass shader to sample UV texture using a shift texture (I think other technique could be use)
My final texture is not DXGI_FORMAT_NV12, but a similar DXGI_FORMAT_R8_UNORM texture. My computer is Windows7, so DXGI_FORMAT_NV12 is not handled. I will try later on a another computer.
The process with pictures:
How can I flipped the SharpDX.Databox without converting it to bitmap?
I'm making a screen recording using SharpDX and Media foundation. Below is the code on how I get the Databox.
mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0,SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
But when I passed the mapSource in mediafoundation.net I produced a vertical video.
IMFSample sample = null;
IMFMediaBuffer buffer = null;
IntPtr data = new IntPtr();
int bufferMaxLength;
int bufferCurrentLength;
int hr = (int)MFExtern.MFCreateMemoryBuffer(frameSizeBytes, out buffer);
if (Succeeded(hr)) hr = (int)buffer.Lock(out data, out bufferMaxLength, out bufferCurrentLength);
if (Succeeded(hr))
{
hr = (int)MFExtern.MFCopyImage(data, videoWidth * BYTES_PER_PIXEL, mapSource.DataPointer, videoWidth * BYTES_PER_PIXEL, videoWidth * BYTES_PER_PIXEL, videoHeight);
}
if (Succeeded(hr)) hr = (int)buffer.Unlock();
if (Succeeded(hr)) hr = (int)buffer.SetCurrentLength(frameSizeBytes);
if (Succeeded(hr)) hr = (int)MFExtern.MFCreateSample(out sample);
if (Succeeded(hr)) hr = (int)sample.AddBuffer(buffer);
if (Succeeded(hr)) hr = (int)sample.SetSampleTime(frame.prevRecordingDuration.Ticks);//(TICKS_PER_SECOND * frames / VIDEO_FPS);
if (Succeeded(hr)) hr = (int)sample.SetSampleDuration((frame.recordDuration-frame.prevRecordingDuration).Ticks);
if (Succeeded(hr)) hr = (int)sinkWriter.WriteSample(streamIndex, sample);
if (Succeeded(hr)) frames++;
COMBase.SafeRelease(sample);
COMBase.SafeRelease(buffer);
enter image description here
In your code there is a mistake in code with MFCopyImage. According MFCopyImage function you must set
_In_ LONG lDestStride,
_In_ const BYTE *pSrc,
_In_ LONG lSrcStride, - lDestStride and lSrcStride - is width of memory for storing one line of pixels - your computing videoWidth * BYTES_PER_PIXEL is not correct, because for Windows RGB format stride can be widther than videoWidth * BYTES_PER_PIXEL. You must compute destination stride by function MFGetStrideForBitmapInfoHeader, source stride you can get from you image source code - I do not know you code, but for my project I used
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
ctx->Map(mDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
LOG_INVOKE_MF_FUNCTION(MFCopyImage,
aPtrData,
mStride,
(BYTE*)resource.pData,
resource.RowPitch,
RowPitch.
Regards.
P.S. Destination stride mStride can be negative - it means that it needs write from last line to the first. It can done by the next changing of destination pointer - aPtrData += (mHeight - 1)*mStride;
I have an object and I can render it but I want to use its vertices twice but I don't know how to.
Edit: I wan them to translate independently during the game.
this is my code reading object from txt:
fin.open("piyon.txt");
fin >> vertexCountpiyon;
verticespiyon = new SimpleVertex[vertexCountpiyon];
for(int i=0; i<vertexCountpiyon; i++)
{
fin >> verticespiyon[i].Pos.x >> verticespiyon[i].Pos.y >> verticespiyon[i].Pos.z;
fin >> verticespiyon[i].Tex.x >> verticespiyon[i].Tex.y;
fin >> verticespiyon[i].Normal.x >> verticespiyon[i].Normal.y >> verticespiyon[i].Normal.z;
}
fin.close();
bd.ByteWidth = sizeof( SimpleVertex ) * vertexCountpiyon;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = verticespiyon;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer_piyon );
if( FAILED( hr ) ) return hr;
and my render code:
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer_piyon, &stride, &offset );
cBuffer.vMeshColor = XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f );
XMMATRIX mTranslateBeyazPiyon = XMMatrixTranslation( -17.5F, 0, -12.5F );
cBuffer.mWorld = XMMatrixTranspose( mTranslateBeyazPiyon );
g_World_Piyon = mTranslateBeyazPiyon;
g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cBuffer, 0, 0 );
g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
g_pImmediateContext->VSSetConstantBuffers( 2, 1, &g_pConstantBuffer );
g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
g_pImmediateContext->PSSetConstantBuffers( 2, 1, &g_pConstantBuffer );
g_pImmediateContext->Draw( 7050, 0 );
If you want to just draw the same object in a different place, you only need to change your world matrix and then draw again. So, using parts of your code for reference, something like this:
// set world matrix for first object ...
XMMATRIX mTranslateBeyazPiyon = XMMatrixTranslation( -17.5F, 0, -12.5F );
cBuffer.mWorld = XMMatrixTranspose( mTranslateBeyazPiyon );
g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cBuffer, 0, 0 );
// ... set any other common state
// draw first object
g_pImmediateContext->Draw( 7050, 0 );
// set world matrix for second object ... for example, translated somewhere else
mTranslateBeyazPiyon = XMMatrixTranslation( -34.5F, 0, -24.5F );
cBuffer.mWorld = XMMatrixTranspose( mTranslateBeyazPiyon );
g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cBuffer, 0, 0 );
// draw second object
g_pImmediateContext->Draw( 7050, 0 );
I am trying to build a simple 2D game using 2D sprites with DirectX 9, and I'm having problems getting the images to come out cleanly. I'd like to load bmp images and display them on the screen as is (no interpolation, no magnification, no filtering or anti-aliasing, etc).
I'm sure I'm missing something, but when I try and render a 100x100 bmp to the screen, it looks choppy and distorted, like a pixel art image would normally look when shrunken slightly. I want the bmp to look exactly as it does when loaded in MS Paint.
Does anyone have any idea why this might be the case? My code is shown below:
Initialization code:
g_DxCom = Direct3DCreate9( D3D_SDK_VERSION );
if ( g_DxCom == NULL )
{
return false;
}
D3DDISPLAYMODE d3dDisplayMode;
if ( FAILED( g_DxCom->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3dDisplayMode ) ) )
{
return false;
}
D3DPRESENT_PARAMETERS d3dPresentParameters;
::ZeroMemory( &d3dPresentParameters, sizeof(D3DPRESENT_PARAMETERS) );
d3dPresentParameters.Windowed = FALSE;
d3dPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPresentParameters.BackBufferFormat = d3dDisplayMode.Format; // D3DFMT_X8R8G8B8
d3dPresentParameters.BackBufferWidth = d3dDisplayMode.Width;
d3dPresentParameters.BackBufferHeight = d3dDisplayMode.Height;
d3dPresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dPresentParameters,
&pd3dDevice ) ) )
{
if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dPresentParameters,
&pd3dDevice ) ) )
{
return false;
}
}
texture = NULL;
bg_texture = NULL;
Render code:
LPDIRECT3DDEVICE9 g_dxDevice;
float float1 = 99.5f; // I'd like to render my 100x100 sprite from screen coordinates 100, 100 to 200, 200
float float2 = 198.5f;
CUSTOMVERTEX OurVertices[] =
{
{ float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
{ float1, float1, 1.0f, 1.0f, 0.0f, 0.0f },
{ float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
{ float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
{ float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
{ float2, float2, 1.0f, 1.0f, 1.0f, 1.0f }
};
LPDIRECT3DVERTEXBUFFER9 v_buffer;
g_dxDevice->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL );
VOID* pVoid;
// Lock the vertex buffer into memory
v_buffer->Lock( 0, 0, &pVoid, 0 );
// Copy our vertex buffer to memory
::memcpy( pVoid, OurVertices, sizeof(OurVertices) );
// Unlock buffer
v_buffer->Unlock();
LPDIRECT3DTEXTURE9 g_texture;
HRESULT hError;
DWORD dwTextureFilter = D3DTEXF_NONE;
g_dxDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, dwTextureFilter );
g_dxDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
hError = D3DXCreateTextureFromFile( g_dxDevice, L"Test.bmp", &g_texture ); // 100x100 sprite
g_dxDevice->SetTexture( 0, g_texture );
g_dxDevice->Clear( 0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB( 0, 40, 100 ),
1.0f,
0 );
g_dxDevice->BeginScene();
// Do rendering on the back buffer here
g_dxDevice->SetFVF( CUSTOMFVF );
g_dxDevice->SetStreamSource( 0, v_buffer, 0, sizeof(CUSTOMVERTEX) );
g_dxDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 6 );
g_dxDevice->EndScene();
g_dxDevice->Present( NULL, NULL, NULL, NULL );
g_texture->Release();
v_buffer->Release();
Okay, so I've finally figured it out, and I should have known this was the case.
It looks like DirectX9 only works with textures with sizes that are multiples of 2. If I change the texture so that the sprite square is 128 x 128 (just adding some transparency) and run the application with float2 changed appropriately, there is no distortion in the rendered image.
Hurrah...
Basically I made a .x file model class with animations and all and each model class has a pointer for an effect file class,so i make a bunch of different models and i make them all use a single effect like a glow for example, so around DrawSubset() in the render function of each model are Begin() and End() for the effect.The problem is 90% of my .fx files(I tried making in FX composer and Rendermonkey,I tried loading samples,even simple ones)they don't load and it says the effect is null and if something manages to load,it makes all the geometry grey or slices parts of it off.This is basically my code(oh and the d3d device pointer is properly set,don't worry,the problem is not there):
***FXfileEntity.h***
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
class CFXFileEntity{
private:
LPDIRECT3DDEVICE9 m_d3dDevice;
LPD3DXBUFFER pBufferErrors;
D3DXEFFECT_DESC pEffectDesc;
DWORD dwShaderFlags;
D3DXHANDLE ambient, attenuation, bbmax, bbmin, bbsize, bcenter, bssize, bsmin, bsmax, diffuse,
elapsed, emissive, envNormal, height, joint, jointW, jointWI, jointWIT, jointWV,
jointWVI, jointWVIT, jointWVP, jointWVPI, jointWVPIT, last, normal, opacity,
position, proj, projI, projIT, random, refraction, renderCT, renderDST, renderTC,
renderTD, specular, specularP, standarGlob, TextureMat, time, UnitsScale, view,
viewI, viewIT, viewP, viewPI, viewPIT, world, worldI, worldIT, worldV, worldVI,
worldVIT, worldVP, worldVPI, worldVPIT;
D3DXVECTOR4 amb4, att4, diff, emis, join, nor2, opa4, posit, ref4, rtc, spec, specP4;
D3DXVECTOR3 att3, bbMax, bbMin, bbSiz, bCen, nor1, opa3, ref3, specP3;
D3DXVECTOR2 opa2, ref2, rtd, specP2;
float bsSiz, bsMin, bsMax, elapTime, heigtMap1, lasTime, opa1, ran, ref1, specP1, tim, unit;
LPDIRECT3DTEXTURE9 envNorm, heightMapT, nor3, opa5, ref5, rct, rdst, stdG;
D3DXMATRIX jWor, jWI, jWIT, jWV, jWVI, jWVIT, jWVP, jWVPI, jWVPIT, pro, proI, proIT, texM,
vie, vieI, vieIT, vieP, viePI, viePIT, wor, worI, worIT, worV, worVI, worVIT, worVP, worVPI,
worVPIT;
public:
LPD3DXEFFECT anEffect;
UINT cPasses;
CFXFileEntity(LPDIRECT3DDEVICE9 d3dDevice);
~CFXFileEntity();
HRESULT Load(LPCTSTR path);
void Set();
};
and for the function bodies:
#include "FXfileEntity.h"
#include <iostream>
CFXFileEntity::CFXFileEntity(LPDIRECT3DDEVICE9 d3dDevice) : m_d3dDevice(d3dDevice)
{
anEffect = NULL;
pBufferErrors = NULL;
dwShaderFlags = 0;
cPasses = 0;
}
CFXFileEntity::~CFXFileEntity(void)
{
anEffect = NULL;
pBufferErrors = NULL;
dwShaderFlags = 0;
cPasses = 0;
}
HRESULT CFXFileEntity::Load(LPCTSTR path)
{
HRESULT hr;
hr=D3DXCreateEffectFromFile(m_d3dDevice,path,NULL,NULL,0,NULL,&anEffect,NULL);
if(!anEffect)
{
MessageBox(NULL, "fail", "f", MB_OK);
}
if(FAILED(hr))
{
MessageBox(NULL, "hr failed", "hrf", MB_OK);
}
ambient = anEffect->GetParameterBySemantic( NULL, "Ambient" );
attenuation = anEffect->GetParameterBySemantic( NULL, "Attenuation" );
bbmax = anEffect->GetParameterBySemantic( NULL, "BoundingBoxMax" );
bbmin = anEffect->GetParameterBySemantic( NULL, "BoundingBoxMin" );
bbsize = anEffect->GetParameterBySemantic( NULL, "BoundingBoxSize" );
bcenter = anEffect->GetParameterBySemantic( NULL, "BoundingCenter" );
bssize = anEffect->GetParameterBySemantic( NULL, "BoundingSphereSize" );
bsmin = anEffect->GetParameterBySemantic( NULL, "BoundingSphereMin" );
bsmax = anEffect->GetParameterBySemantic( NULL, "BoundingSphereMax" );
diffuse = anEffect->GetParameterBySemantic( NULL, "Diffuse" );
elapsed = anEffect->GetParameterBySemantic( NULL, "ElapsedTime" );
emissive = anEffect->GetParameterBySemantic( NULL, "Emissive" );
envNormal = anEffect->GetParameterBySemantic( NULL, "EnviromentNormal" );
height = anEffect->GetParameterBySemantic( NULL, "Height" );
joint = anEffect->GetParameterBySemantic( NULL, "Joint" );
jointW = anEffect->GetParameterBySemantic( NULL, "JointWorld" );
jointWI = anEffect->GetParameterBySemantic( NULL, "JointWorldInverse" );
jointWIT = anEffect->GetParameterBySemantic( NULL, "JointWorldInverseTranspose" );
jointWV = anEffect->GetParameterBySemantic( NULL, "JointWorldView" );
jointWVI = anEffect->GetParameterBySemantic( NULL, "JointWorldViewInverse" );
jointWVIT = anEffect->GetParameterBySemantic( NULL, "JointWolrdViewInverseTranspose" );
jointWVP = anEffect->GetParameterBySemantic( NULL, "JointWorldViewProjection" );
jointWVPI = anEffect->GetParameterBySemantic( NULL, "JointWorldViewProjectionInverse" );
jointWVPIT = anEffect->GetParameterBySemantic( NULL, "JointWorldViewProjectionTranspose" );
last = anEffect->GetParameterBySemantic( NULL, "LastTime" );
normal = anEffect->GetParameterBySemantic( NULL, "Normal" );
opacity = anEffect->GetParameterBySemantic( NULL, "Opacity" );
position = anEffect->GetParameterBySemantic( NULL, "Position" );
proj = anEffect->GetParameterBySemantic( NULL, "Projection" );
projI = anEffect->GetParameterBySemantic( NULL, "ProjectionInverse" );
projIT = anEffect->GetParameterBySemantic( NULL, "ProjectionInverseTranspose" );
random = anEffect->GetParameterBySemantic( NULL, "Random" );
refraction = anEffect->GetParameterBySemantic( NULL, "Refraction" );
renderCT = anEffect->GetParameterBySemantic( NULL, "RenderColorTarget" );
renderDST = anEffect->GetParameterBySemantic( NULL, "RenderDepthStencilTarget" );
renderTC = anEffect->GetParameterBySemantic( NULL, "RenderTargetClipping" );
renderTD = anEffect->GetParameterBySemantic( NULL, "RenderTargetDimension" );
specular = anEffect->GetParameterBySemantic( NULL, "Specular" );
specularP = anEffect->GetParameterBySemantic( NULL, "SpecularPower" );
standarGlob = anEffect->GetParameterBySemantic( NULL, "StandardGlobal" );
TextureMat = anEffect->GetParameterBySemantic( NULL, "TextureMatrix" );
time = anEffect->GetParameterBySemantic( NULL, "Time" );
UnitsScale = anEffect->GetParameterBySemantic( NULL, "UnitsScale" );
view = anEffect->GetParameterBySemantic( NULL, "View" );
viewI = anEffect->GetParameterBySemantic( NULL, "ViewInverse" );
viewIT = anEffect->GetParameterBySemantic( NULL, "ViewInverseTranspose" );
viewP = anEffect->GetParameterBySemantic( NULL, "ViewProjection" );
viewPI = anEffect->GetParameterBySemantic( NULL, "ViewProjectionInverse" );
viewPIT = anEffect->GetParameterBySemantic( NULL, "ViewProjectionInverseTranspose" );
world = anEffect->GetParameterBySemantic( NULL, "World" );
worldI = anEffect->GetParameterBySemantic( NULL, "WorldInverse" );
worldIT = anEffect->GetParameterBySemantic( NULL, "WorldInverseTranspose" );
worldV = anEffect->GetParameterBySemantic( NULL, "WorldView" );
worldVI = anEffect->GetParameterBySemantic( NULL, "WorldViewInverse" );
worldVIT = anEffect->GetParameterBySemantic( NULL, "WorldViewInverseTranspose" );
worldVP = anEffect->GetParameterBySemantic( NULL, "WorldViewProjection" );
worldVPI = anEffect->GetParameterBySemantic( NULL, "WorldViewProjectionInverse" );
worldVPIT = anEffect->GetParameterBySemantic( NULL, "WorldViewProjectionInverseTranspose" );
D3DXHANDLE hTech;
anEffect->FindNextValidTechnique( NULL, &hTech );
anEffect->SetTechnique( hTech );
return hr;
}
void CFXFileEntity::Set()
{
m_d3dDevice->GetTransform( D3DTS_WORLD, &wor );
m_d3dDevice->GetTransform( D3DTS_PROJECTION, &pro );
m_d3dDevice->GetTransform( D3DTS_VIEW, &vie );
D3DXMatrixInverse( &proI, NULL, &pro );
D3DXMatrixTranspose( &proIT, &proI );
D3DXMatrixInverse( &vieI, NULL, &vie );
D3DXMatrixTranspose( &vieIT, &vieI );
vieP = vie * pro;
D3DXMatrixInverse( &viePI, NULL, &vieP );
D3DXMatrixTranspose( &viePIT, &viePI );
D3DXMatrixInverse( &worI, NULL, &wor );
D3DXMatrixTranspose( &worIT, &worI );
worV = wor * vie;
D3DXMatrixInverse( &worVI, NULL, &worV );
D3DXMatrixTranspose( &worVIT, &worVI );
worVP= wor * vie * pro;
D3DXMatrixInverse( &worVPI, NULL, &worVP );
D3DXMatrixTranspose( &worVPIT, &worVPI );
tim = (float)GetTickCount()/1000.0f;
anEffect->SetFloat( time, tim );
anEffect->SetMatrix( proj, &pro );
anEffect->SetMatrix( projI, &proI );
anEffect->SetMatrix( projIT, &proIT );
anEffect->SetMatrix( view, &vie );
anEffect->SetMatrix( viewI, &vieI );
anEffect->SetMatrix( viewIT, &vieIT );
anEffect->SetMatrix( viewP, &vieP );
anEffect->SetMatrix( viewPI, &viePI );
anEffect->SetMatrix( viewPIT, &viePIT );
anEffect->SetMatrix( world, &wor );
anEffect->SetMatrix( worldI, &worI );
anEffect->SetMatrix( worldIT, &worIT );
anEffect->SetMatrix( worldV, &worV );
anEffect->SetMatrix( worldVI, &worVI );
anEffect->SetMatrix( worldVIT, &worVIT );
anEffect->SetMatrix( worldVP, &worVP );
anEffect->SetMatrix( worldVPI, &worVPI );
anEffect->SetMatrix( worldVPIT, &worVPIT );
}
and in the model class it renders here:
this->Effect->Set();
this->Effect->cPasses = 0;
if( SUCCEEDED( Effect->anEffect->Begin(&this->Effect->cPasses, 0) ) ){
for (DWORD i = 0; i < this->Effect->cPasses; i++)
{
Effect->anEffect->BeginPass(i);
pDrawMesh->DrawSubset(iMaterial);
Effect->anEffect->EndPass();
}
Effect->anEffect->End();
}
I tried different values on cPasses depending on what I see in the .fx file,it doesn't really make a difference.Without the .fx files my .x files render perfectly with textures and animations...I never thought .fx files would be so hard,it's like the most confusing part of DirectX by far!
Ok, looking at "EdgeFuzz.fx" *please maybe post the file for everybody to see
The Shader uses the following for Vertex Input.
/* data from application vertex buffer */
struct appdata {
float3 Position : POSITION;
float4 UV : TEXCOORD0;
float4 Normal : NORMAL;
float4 Tangent : TANGENT0;
float4 Binormal : BINORMAL0;
};
I do not see a Vertex Buffer in your code, that matches the above semantics? i.e you will need to create a vertex buffer, matching the information vertex (semantic: POSITION), texturecoord: semantic: TEXCOORD0, normal (for lighting, semantic: NORMAL), (tangent and binormal for bump mapping)
The vertex buffer must then be filled with your mesh geometry in the structure as above (you will need to create a c++ struct to match the above hlsl struct)
Or is there more code you perhaps exlcluded from the post?
I hope this will be helpful to you, as that vertex shader will then take that geometry information, and do it's thing , when you invoke the technique (Main) (defined in the "EdgeFuzz.fx" shader)