none
Drawing pixels

    Question

  • Hi,

    I need to draw a bunch of pixels on the screen (it could be thousands of them). I'm wondering what would be the most efficient method to draw pixels using C++ and DirectX 11.1. I know I could use the method DrawEllipse of ID2D1DeviceContext but it would not be very efficient I guess.

    Is there anything similar to "point primitives" in DX 11.1 (I'm a DX9 guy) so I could fill out a buffer and just throw them on the screen?

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Friday, November 01, 2013 3:10 AM

Answers

  • Nigel Wright said: "I create a texture, write shapes into the pixel array then send it to the screen via a shader resource"

    I can see from the code you are using the Mappable texture Chuck mentioned about. I understand your code is just a snippet from a bigger piece. What is the type of m_sprites and what are sx and sy values? I guess these are the elements of your pixel array and the sprite is a single pixel, right?

    -----

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com


    sx and sy are the top left hand side cords to centre the screen.

    M_sprites is set up earlier.

    Its all part of a couple of games I wrote.

    The pixel buffer is dead easy to work with. You use map, update the texture pixels then unmap.

     

    void Renderer::CreateDeviceResources()
    {
    	Direct3DBase::CreateDeviceResources();
    
        // Create DirectXTK objects
        auto device = m_d3dDevice.Get();
        m_states.reset( new CommonStates( device ) );
    //    m_fxFactory.reset( new MyEffectFactory( device ) );
    
        auto context = m_d3dContext.Get();
        m_sprites.reset( new SpriteBatch( context ) );
        m_batch.reset( new PrimitiveBatch<VertexPositionColor>( context ) );
    
        m_batchEffect.reset( new BasicEffect( device ) );
        m_batchEffect->SetVertexColorEnabled(true);
    
        {
            void const* shaderByteCode;
            size_t byteCodeLength;
    
            m_batchEffect->GetVertexShaderBytecode( &shaderByteCode, &byteCodeLength );
    
            DX::ThrowIfFailed(
                device->CreateInputLayout( VertexPositionColor::InputElements,
                                            VertexPositionColor::InputElementCount,
                                            shaderByteCode, byteCodeLength,
                                            m_batchInputLayout.ReleaseAndGetAddressOf() ) 
                             );
        }
    	
        m_font.reset( new SpriteFont( device, L"assets\\italic.spritefont" ) );
    	/*
    	m_shape = GeometricPrimitive::CreateTeapot( context, 4.f, 8 );
    
        // SDKMESH has to use clockwise winding with right-handed coordinates, so textures are flipped in U
        m_model = Model::CreateFromSDKMESH( device, L"assets\\tiny.sdkmesh", *m_fxFactory );
    	*/
    
    }


    n.Wright

    Saturday, November 02, 2013 2:16 AM

All replies

  • As you are using C++ -- have a lot at CUDA, that is the most efficient on nVidia cards. Are you printing to a control on the screen or writing directly to Video Memory?

    We kind of need more information on how you would like to do it!

    look at the SetPixel function on Win32


    Digital Forensic Software Developer
    http:\\ccs-labs.com Mark as Answer or Vote up if useful thank you!
    Volunteer Developers Required to work on free systems that can be used to reduce online child abuse and bullying! contact: dave@ccs-labs.com if you are interested.


    Friday, November 01, 2013 11:06 AM
  • Thanks Dave for your answer. The program is using Windows Runtime (it's a Windows Store App) so the Win32 SetPixel function is out of question. I'm aware of CUDA but I was wondering if DirectX has some built-in mechanism to draw pixels.

    This is how the App works:

    1. The IFrameworkView::Run method is called by the CoreApplication.

    2. The IFrameworkView::Run calls a Render method on my custom renderer.

    3. In the Render method I draw a rectangle:

    context->DrawRectangle(
      D2D1::RectF(100.0, 100.0, 200.0, 200.0),
      brush.Get(),
      4.0);

    The context variable is of type ID2D1DeviceContext and the brush is of type ID2D1SolidColorBrush.

    Now, I'd also like to draw some (actually a lot of) pixels. I need something like context->DrawPixel(x,y,color). Unfortunately ID2D1DeviceContext does not offer such a method.

    What are my alternatives other than CUDA?

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com



    • Edited by ata6502 Friday, November 01, 2013 2:38 PM
    Friday, November 01, 2013 2:29 PM
  • Draw into a pixel buffer then call CopyFromMemory to copy your bitmap into an ID2D1Bitmap. http://msdn.microsoft.com/en-us/library/dd371155(v=vs.85).aspx

    --Rob

    Friday, November 01, 2013 2:52 PM
  • Drawing a single pixel rectangle is the same performance as drawing individual pixels through Direct2D, which is why there isn't a DrawPixel method.

    RE: Direct3D 11 options

    If you are going to draw 'lots of pixels' do the work in a Mappable texture and then use sprite rendering to get it onto the screen. See DirectXTK's SpriteClass if you want to do this with Direct3D 11.

    Alternatively, you could use dynamic geometry submission and draw individual points with the view transform setup to 1:1. See DirectXTK's PrimitiveBatch if you want to do this with Direct3D 11.

    http://go.microsoft.com/fwlink/?LinkId=248929

    Friday, November 01, 2013 5:37 PM
  • I create a texture, write shapes into the pixel array then send it o the screen via a shader resource,

    
    		m_d3dContext->ClearRenderTargetView(
    			m_renderTargetView.Get(),
    			Colors::Green
    			);
    		
    	m_d3dContext->ClearDepthStencilView(
    		m_depthStencilView.Get(),
    		D3D11_CLEAR_DEPTH,
    		1.0f,
    		0
    		);
    
    	m_d3dContext->OMSetRenderTargets(
    		1,
    		m_renderTargetView.GetAddressOf(),
    		m_depthStencilView.Get()
    		);
    
    
    
    
    	UINT fred;
    	m_d3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 16, &fred);
    
    	D3D11_TEXTURE2D_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
    	desc.ArraySize = 1;
    	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    	desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    	desc.MipLevels = 1;
    	desc.MiscFlags = 0;
    	desc.SampleDesc.Count = 1;
    	desc.SampleDesc.Quality = fred;
    	desc.Usage = D3D11_USAGE_DYNAMIC;
    	desc.Width = screenwidth;
    	desc.Height = screenheight;
    	desc.MiscFlags = 0;
    
    
    	D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDescription;
    	ZeroMemory(&renderTargetViewDescription, sizeof(renderTargetViewDescription));
    	renderTargetViewDescription.Format = desc.Format;
    	renderTargetViewDescription.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; // MS;
    
    
    
    	////////////////////////////////////////////////////////////////////////////
    	D3D11_SUBRESOURCE_DATA tbsd;
    	tbsd.pSysMem = (void *) buf;
    	tbsd.SysMemPitch = screenwidth * 4;
    	tbsd.SysMemSlicePitch = screenwidth*screenheight * 4; // Not needed since this is a 2d texture
    
    	if (initedq == 0)
    	{
    		if (FAILED(m_d3dDevice->CreateTexture2D(&desc, &tbsd, &pTexture)))
    			return;
    		initedq = 1;
    	}
    
    	else
    	{
    		D3D11_MAPPED_SUBRESOURCE dd;
    		dd.pData = (void *) buf;
    		dd.RowPitch = screenwidth * 4;
    		dd.DepthPitch = screenwidth* screenheight * 4;
    
    		//		m_d3dDevice->CreateTexture2D(&desc, &tbsd, &pTexture);
    
    		m_d3dContext->Map(pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &dd);
    
    		memcpy(dd.pData, buf, screenwidth*screenheight * 4);
    
    
    		m_d3dContext->Unmap(pTexture, 0);
    	}
    
    
    
    	///////////////////////////////////////////////////////////////////////////////
    	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    	D3D11_RESOURCE_DIMENSION type;
    	pTexture->GetType(&type);
    	pTexture->GetDesc(&desc);
    	srvDesc.Format = desc.Format;
    	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    	srvDesc.Texture2D.MipLevels = desc.MipLevels;
    	srvDesc.Texture2D.MostDetailedMip = desc.MipLevels - 1;
    
    	ID3D11ShaderResourceView *pSRView = NULL;
    	m_d3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &pSRView);
    
    
    	D3D11_RENDER_TARGET_VIEW_DESC rtDesc;
    	rtDesc.Format = desc.Format;
    	rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    	rtDesc.Texture2D.MipSlice = 0;
    
    
    
    
    
    
    
    
    
    	////////////////////////////////////////////////////////////////////////////
    
    	
    
    
    
    
    
    
    
    
    
    
    
    	// Draw sprite
    	m_sprites->Begin();
    
    
    
    	m_sprites->Draw(pSRView, XMFLOAT2(sx, sy), nullptr, Colors::White);
    
    	
    
    
    	m_sprites->End();
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    		
    
    
    
    
    
    
    
    
    
    
    


    n.Wright

    Friday, November 01, 2013 10:31 PM
  • Thanks everyone for the answers. I will address them one by one:

    -----

    Rob Caplan said: "Draw into a pixel buffer then call CopyFromMemory to copy your bitmap into an ID2D1Bitmap".

    I have found information on CopyFromMemory and ID2D1Bitmap but I don't see anything regarding the pixel buffer you mentioned. Does DirectX 11.1 have the pixel buffer? I know the WriteableBitmap class has the PixelBuffer property but it is available only from XAML (or am I wrong?). I'm not using XAML for my UI.

    -----

    Chuck Walbourn said: "Drawing a single pixel rectangle is the same performance as drawing individual pixels through Direct2D..."

    Wow! I did not realize there is no difference in performance. I conducted a few tests and it turned out the DrawRectangle is *much* slower than FillRectangle. I will have a look at the Mappable textures. Also, I have found the PrimitiveBatch class in DirectXTK but I don't see the Sprite class. Did you mean the SpriteBatch class?

    -----

    Nigel Wright said: "I create a texture, write shapes into the pixel array then send it to the screen via a shader resource"

    I can see from the code you are using the Mappable texture Chuck mentioned about. I understand your code is just a snippet from a bigger piece. What is the type of m_sprites and what are sx and sy values? I guess these are the elements of your pixel array and the sprite is a single pixel, right?

    -----

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com




    • Edited by ata6502 Saturday, November 02, 2013 2:59 AM
    Saturday, November 02, 2013 2:11 AM
  • Nigel Wright said: "I create a texture, write shapes into the pixel array then send it to the screen via a shader resource"

    I can see from the code you are using the Mappable texture Chuck mentioned about. I understand your code is just a snippet from a bigger piece. What is the type of m_sprites and what are sx and sy values? I guess these are the elements of your pixel array and the sprite is a single pixel, right?

    -----

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com


    sx and sy are the top left hand side cords to centre the screen.

    M_sprites is set up earlier.

    Its all part of a couple of games I wrote.

    The pixel buffer is dead easy to work with. You use map, update the texture pixels then unmap.

     

    void Renderer::CreateDeviceResources()
    {
    	Direct3DBase::CreateDeviceResources();
    
        // Create DirectXTK objects
        auto device = m_d3dDevice.Get();
        m_states.reset( new CommonStates( device ) );
    //    m_fxFactory.reset( new MyEffectFactory( device ) );
    
        auto context = m_d3dContext.Get();
        m_sprites.reset( new SpriteBatch( context ) );
        m_batch.reset( new PrimitiveBatch<VertexPositionColor>( context ) );
    
        m_batchEffect.reset( new BasicEffect( device ) );
        m_batchEffect->SetVertexColorEnabled(true);
    
        {
            void const* shaderByteCode;
            size_t byteCodeLength;
    
            m_batchEffect->GetVertexShaderBytecode( &shaderByteCode, &byteCodeLength );
    
            DX::ThrowIfFailed(
                device->CreateInputLayout( VertexPositionColor::InputElements,
                                            VertexPositionColor::InputElementCount,
                                            shaderByteCode, byteCodeLength,
                                            m_batchInputLayout.ReleaseAndGetAddressOf() ) 
                             );
        }
    	
        m_font.reset( new SpriteFont( device, L"assets\\italic.spritefont" ) );
    	/*
    	m_shape = GeometricPrimitive::CreateTeapot( context, 4.f, 8 );
    
        // SDKMESH has to use clockwise winding with right-handed coordinates, so textures are flipped in U
        m_model = Model::CreateFromSDKMESH( device, L"assets\\tiny.sdkmesh", *m_fxFactory );
    	*/
    
    }


    n.Wright

    Saturday, November 02, 2013 2:16 AM