Jump to content
  • Advertisement
Sign in to follow this  
jonssonj

set and get a pixel in directx

This topic is 3803 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello all! I'm a total beginner of directx so i hope that you can bear with my simple question. I'm certain that this question have arised before, but I can't seem to find any info about it when I try to search for it. I'm going to try to make a astronomy program and then I need the speed of my nvidia graphics card. But I have a little problem. I can't seem to figure out how to set and get a pixel in directx sdk. Can anyone point me in the right direction or can anyone share setpixel and getpixel code to me? I would be very thankful for all help you can give me on this subject. BR Jörgen Jönsson

Share this post


Link to post
Share on other sites
Advertisement
Setting or getting one pixel is an extremely expensive thing to do to a graphics card. The way to do it is to lock a texture or render target, read / write a value, and then unlock the texture / backbuffer.
Because of that, it's much better to lock the texture / backbuffer, draw all pixels, and then unlock it - even if it means having a copy of the pixel data in an array in memory.

Share this post


Link to post
Share on other sites
I'm relatively new myself, but I'm pretty sure that if you're using directx 8 or higher, you simply cannot. That was a feature of directdraw and directdraw has been removed. You will have to go through direct3d, which complicates things a little. I'm learning d3d10 at the moment and Microsoft's tutorial 3 for d3d10 should give you a good idea of how to use it for setting a pixel.

Share this post


Link to post
Share on other sites
Hello and thanks for your replies!

@Evil Steve
My idea was to have a copy of the pixels in an array in memory and update the screen from this buffer.


@kingdord
Could you give me a link to the tutorial that you are reading? is it on msdn?


@HellzGod
I have never used GDI/GDI+ either. Would that mean, that I need to learn both GDI/GDI+ and directx?

@all
If you have more suggestions, keep them coming... :)

BR
Jörgen Jönsson

Share this post


Link to post
Share on other sites
I'd stay away from D3D10 for something like this unless you really only want it to run obn Vista with a DX10 card (Unlike DX9, DX10 will only run with a DX10 card - e.g. a GeForce 8, and only on Vista).

GDI/GDI+ might be a possible option, but won't be as fast as using pure DirectX, although it is pretty easy to learn.

What exactly do you need to draw? Is it just individual points for stars? If so, the simplest way would be to render a series of points. If you need to render more than a few thousand points, or you need to render more complex shapes, then drawing directly to a texture or the backbuffer might be better.

Share this post


Link to post
Share on other sites
Quote:
Original post by jonssonj
I'm going to try to make a astronomy program and then I need the speed of my nvidia graphics card. But I have a little problem. I can't seem to figure out how to set and get a pixel in directx sdk.


An NVIDIA graphics card is very fast for certain kinds of operations. You cannot simply take an existing program, connect it to a graphics card, and expect it to run faster: you need to actually change your program so that it does the things that graphics cards are good at. Accessing individual pixels is not a good idea, while running a shader on all pixels at once is a good idea, for example.

Share this post


Link to post
Share on other sites
Quote:
Original post by jonssonj
@HellzGod
I have never used GDI/GDI+ either. Would that mean, that I need to learn both GDI/GDI+ and directx?
Jörgen Jönsson


Hi,
Like Steve says, GDI/GDI+ might be slower. But here is a code snippet for getting a pixel:


HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "SomeImage.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HDC hdc = GetDC(NULL);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hMemDC, hBmp);
....
COLORREF color = GetPixel(hMemDC, x, y);
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
...
SelectObject( hMemDC,hBmpOld);



Lookup msdn/internet. It's very simple.
hth,
M

Share this post


Link to post
Share on other sites
Yes, that tutorial is on MSDN (full source can be installed with the dx SDK). I do agree with Evil Steve, dx10 is kind of a prohibitive platform at them moment, so if you don't have the hardware or want to redistribute the product, staying away is probably the best option for the time being.

Share this post


Link to post
Share on other sites
Hello all!

I now have this code, but I can't seem to get anything on the window. I guess that I'm doing things in the wrong order on in the wrong places. Can anyone help me to sort this code out.


// win32_test.cpp : Defines the entry point for the application.
//


#include "stdafx.h"
#include "win32_test.h"
#include <D3D9.h>

#define MAX_LOADSTRING 100



bool Init3D(HWND hWnd);
void render();

// Global Variables:
LPDIRECT3D9 g_pD3D;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DSURFACE9 g_Surface = NULL;
LPDIRECT3DSURFACE9 BackBuffer = NULL;

D3DPRESENT_PARAMETERS d3dpp;
D3DSURFACE_DESC surfaceDesc; // Get the surface description.
D3DLOCKED_RECT lockedRect; // Get a pointer to the surface pixel data.

HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name



// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32_TEST, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32_TEST));

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {


render(); // If there are no messages to process then render some DIRECTX stuff.


}
}

return (int) msg.wParam;
}



//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32_TEST));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32_TEST);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

Init3D(hWnd); // Init directx
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);


return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HRESULT result = NULL;
DWORD *imageData = NULL;


switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

bool Init3D(HWND hWnd) {
HDC result_hdc = NULL;
UINT width = 0;
UINT height = 0;
RECT rect;
LPRECT lpRect = &rect;

GetWindowRect(hWnd,lpRect);
width = lpRect->right - lpRect->left;
height = lpRect->bottom - lpRect->top;

if( NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) {
return FALSE;
}

ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;

if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) ) {
return FALSE;
}


HRESULT result = NULL;

UINT availMem = g_pd3dDevice->GetAvailableTextureMem();

D3DCAPS9 caps;
D3DCAPS9 *pCaps = &caps;
ZeroMemory( pCaps, sizeof(D3DCAPS9));
result = g_pd3dDevice->GetDeviceCaps(pCaps); // Just for debugging purpose

D3DDISPLAYMODE mode;
D3DDISPLAYMODE *pMode = &mode;
ZeroMemory(pMode, sizeof(D3DDISPLAYMODE));
result = g_pd3dDevice->GetDisplayMode(0, pMode);

result = g_pd3dDevice->CreateOffscreenPlainSurface(width, height,pMode->Format,D3DPOOL_DEFAULT,&g_Surface,NULL);

return TRUE;

}

void render() {
HRESULT result = NULL;

// g_pd3dDevice->SetRenderTarget(1,g_Surface); // This one I don't know if it is needed

// Just for testing purpose, to see if something is happening at all, but there is'nt.
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,255,255), 1.0f, 0);

result = g_Surface->GetDesc(&surfaceDesc);
result = g_Surface->LockRect(&lockedRect, // pointer to receive locked data
0, // lock entire surface
0); // no lock flags specified

DWORD *imageData = (DWORD*)lockedRect.pBits;
imageData = (DWORD*)lockedRect.pBits;

// My thought here was to set a pixel to red at the position 200, 100 in my window.
imageData[(int) (200*lockedRect.Pitch / 4 + 100)] = 0xffff0000; // red

g_Surface->UnlockRect();


if(SUCCEEDED(g_pd3dDevice->BeginScene( ) ) ) {
g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, &BackBuffer);
g_pd3dDevice->UpdateSurface(g_Surface, NULL, BackBuffer, NULL);
if(BackBuffer != NULL)
BackBuffer->Release();

g_pd3dDevice->EndScene();
}

g_pd3dDevice->Present(NULL,NULL,NULL,NULL);

}




Very thankful for all help that I can get to sort this code out.

BR
Jörgen Jönsson

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!