الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Blending

مغلق
بدأه justnow في 12 نوفمبر 2004 · 5 رد · 1,942 مشاهدة · في DirectX
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

فى هذه المشاركة اريد ان القى الضوء على موضوع جيد هو Blending

ترجمتى الشخصية لهذه الكلمة "الدمج" (لاننا ندمج اكثر من لون حتى نحصل على

اللون المطلوب).

تخيل انك تقف فى النقطة 0,0,0 و تنظر فى اتجاه النقطة 0,0,1 و كان هناك ابريق

يقع على النقطة 0,0,5 و اخر فى النقطة 0,0,3.

فى عملية الرسم لهذا المشهد, يمكن ان نرسم الابريق الاول فى الاول و الابريق الثانى فى النهاية

او العكس. فاذا رسمنا الاول فى الاول و الثانى فى النهايةفى هذه الحالة سوف يحدث الاتى:-

يتم رسم الابريق الاول و يطبق نوع ال Culling و الاضاءات .... الى بقية ال pipeline الى ان يوضع

فى شكل pixels على ال Back Buffer.

و عند رسم الابريق الثانى, فى البداية ترسم كل الpixels التى لا تقاطع اى pixel نتج من رسم الابريق الاول.

كل الpixels التى تقع فى الابريق الاول (التى رسمها فى ال BackBuffer الابريق الاول)و التى يغطيها اخوه

الثانى, سوف يتم استبدالها بالاخرى التى تتبع للابريق الثانى.

اذا تم عكس العملية و تم رسم الا بريق الثانى فى الاول و الابريق الاول فى الثانى

(قد تبدو هذه الجملة مربكة قليلا) سيتم:-

رسم الابريق الثانى كاملا.

عند رسم الابريق الاول يتم رسم النقاط pixels التى تقع على الاول و لا تتقاطع مع الابريق الثانى.

اما ال pixels التى تتقاطع مع الابريق الثانى(و التى هى اساسا جذء من الابريق الاول " تذكر انه لايمكن ان نراها

لانها تقع ال الخلف منه على حسب موقع الكاميرا و موقع كل من الابريقين" ) لن يتم رسمها

لان الZ-Buffer Test سوف يفشل و لن ترسم نهائيا.

هذا جميل اليس كذلك. فى كل من هاتين الحالتين ستكون النتيجة هى نفسها ( الشئ الذى يقوله المنطق).

انا احبذ الطريقة الاولى و التى يمكن ان نستعمل ال Blending فيها.

ييمكنك الملاحظة بكل سهولة ان هناك عملية كتابة pixels فوق الاخرى. هذه العملية تمت فى ال pixels

التى كانت فى الابريق الاوال و غطاها الابريق الثانى قد استبدلت بال pixles الجديدة الاتية من الابريق الثانى.

اى ان

ال pixel النهائى و لنعطه الرمز C الناتج من رسم ال pixel A فى نقطة كانت تحوى ال pixel B.

لنرى كيف تم ذلك فى الحالة الاوالى.

C = A

اعتقد ان هذا واضح فقد استبدلت ال pixels التى كانت للابريق الاول بالاخرى التى جاءت من الابريق الثانى.

اى ان الpixel القديم لا وجود له فى المعادلة اى انه لا يؤثر.

الصيغة العامة لهذه المعادلة.

C = a*A + b*B

فى حالتنا هذه a = 1 و b = 0

هذان المعاملان هما اساس عملية ال blending و بالتحكم فى قيم هذه المعاملات نستطيع ان ننتج تاثيرات

رائعة و جميلة. من البديهى ان تكون الشفافية هى المع هذه التاثيرات و من اجمل ما يمكن ان ينجزه ال blending

يعنى مثلا اذا استطعنا تغيير قيم الثابتين a , b

حيث

a = b = 0.50

سوف نحصل على شفافية لا باس بها اليس كذلك؟

لكن الموضوع ليس بهذه البساطة ف Direct3D لا يسمح بتعيين قيم مباشرة لكل من الثابتين كما فعلنا للتو.

و كل الاحتمالات لقيم aوb محددة فى ال enum D3DBLEND . من الوهلة الاولى قد تظن ان هذا يقييد

البرمجة الى حد كبير و كل المسات الجمالية التى تود ان تنتجها بهذه التقنية البسيطة الرائعة. لكن العكس هو

الصحيح, على سبيل المثال مع القيم الموجودة فى D3DBLEND يمكنك ان تحور المعادلة الى الاتى:-

C = A*B

الشئ الذى يستحيل تنفيذه مع لمعاملين aوb اليس كذلك؟

لنتحدث بالاكواد و نترك الكلام الكثير الذى قد لا يدخل الراس.

لكى تقوم بعملية blending نا جحة عليك بالاتى

1/ تفعيل ال belnding :-

فى الحالة الافتراضية يكون غير مفعل, اى انه لن يتم عمل معادلة و سوف نطبق C = A و نحن مغمضين.

و لتفعيل هذه العمليه عليك ب السطر التالى:-

g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);

و لكن لا تكتب هذا السطر فى ال RestoreDeviceObjects لان عملية ال belnding يكمن ان تكون

مكلفة الى حد لا نريد ان تكون مفعلة طوال الوقت. لذلك اذا و فقط اذا احتجت الى ال blending يسمح لك

ان تكتب هذا السطر. بشرط ان تكتب السطر التالى لايقاف ال blending عند انتهائك منه.

g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);

اى ان كل من السطرين يجب ان يكونا داخل الدالة Render.

سيكون ذلك واضحا اذا تابعت المثال المرفق.

2/ الشئ الثانى و هو الذى يمثل جوهر عملية ال belnding هو المعملات التى تتحكم فى المعادلة.

المعامل الذى قمنا بتسميته a يسمى Source Blend Factor و b يسمى Destination Blend Factor.

يمكننا ضبط العملين بالسطرين التاليين على التوالى.

g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,Source);

g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND,Destination);

3/ الشئ الثالث هو انه لا يوجد هناك شئ فقط قم بقراءة المثال و تلاعب به جيدا فقد تركت لك

الكثير لكى تجربه وحدك.

نصيحة:

فكر معى جيدا, حيث اننا لو غيرنا الترتيب فى عملية الRendering فستحدث اشياء غير متوقعة

اى ان ال Z-BufferTest يسبق عملية الBlending فى الترتيب فى ال pipeline. لذلك يمكن ان يسبب

دوران الكاميرا فى اى لحظة فى تعطيل عملية ال blending. مما يجبرك ان تقوم بترتيب عملية الرسم لكل

من الابريقين على حسب موقع الكاميرا الان (اى بعدها من كل ابريق).

ملاحظة: استخدام ال blending فى الصور قد يعطى تاثيرات جميلة و لكن من مساوئه انه يستهلك زمن

كبيرلتكرار الرسم. مما يرشح استخدام multiple stages لانجاز هذه التاثيرات. لكن لا غنى عن ال blending ابدا.

فكر معى, لما؟

ملاحظة اخرى:

يبو ان ملاجظاتى قد كثرت لكن استحملنى ليها القارئ!

كان من المفترض ايقاف ال culling حتى يبدو الشكل الطبيعى, اى ان الشفافية التى نحصل عليها تقل

كلما زاد عدد الطبقات (ال culling سوف يقوم بحذف الطبقات الخلفية), لكن التجربة العملية تثبت العكس,

لانه عند ايقاف ال culling تضيع الشفافية. هذا من الاجذاء التى تركت للمناقشة بعد طرح الموضوع.

#2
#include "windows.h"
#include "d3d9.h"
#include "d3dx9.h"
#include "dxerr9.h"

/*******************************************************/
/***************Direct3D Objects Here*******************/
LPDIRECT3D9 g_pD3D                = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice    = NULL;

LPD3DXMESH     g_pMesh            = NULL;
/*******************************************************/
/*******************************************************/


/*******************************************************/
/***************ALL Normal Variables *******************/
HWND g_hApplicationWindow;

/*******************************************************/
/*******************************************************/

void    AppLoop();
void    AppShutDown();


HRESULT InitD3D();
HRESULT Render();
HRESULT ValidateDevice();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();

HRESULT D3DError(HRESULT hrCode, int nLine, char* szFile, char* szExtraInfo);

#define SAFE_RELEASE(X) (X)->Release(); (X) = NULL

struct D3DCURRENTSETTINGS
{
	int                   m_nDeviceHeight;
	int                   m_nDeviceWidth;
	float                 m_fScreenAspect;
	BOOL                  m_bWindowed;
	BOOL                  m_bMultiSampling;
	D3DFORMAT             m_D3DFormat;
	D3DPRESENT_PARAMETERS m_PresentParams;
	BOOL                  m_bPaused;

	BOOL SetAspect()
	{
  if(m_nDeviceHeight == 0) return FALSE;

  m_fScreenAspect = (float)m_nDeviceWidth/(float)m_nDeviceHeight;
  return TRUE;
	}

};

D3DCURRENTSETTINGS g_D3DSettings;


LRESULT CALLBACK MsgProc(HWND hWnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{

	case WM_CLOSE:
  ::DestroyWindow(hWnd);
  return 0;
  break;


	case WM_DESTROY:
  ::PostQuitMessage(0);
  return 0;

	case WM_SIZE:
  {
 	 //////Resizing without minimizing
 	 if( g_pD3DDevice != NULL && wParam != SIZE_MINIMIZED )
 	 {
    InvalidateDeviceObjects();

    g_D3DSettings.m_PresentParams.BackBufferWidth  = LOWORD(lParam);
    g_D3DSettings.m_PresentParams.BackBufferHeight = HIWORD(lParam);

    g_D3DSettings.m_nDeviceWidth  = LOWORD(lParam);
    g_D3DSettings.m_nDeviceHeight = HIWORD(lParam);
    g_D3DSettings.SetAspect();
    
    g_D3DSettings.m_bPaused = FALSE;

    HRESULT rslt = g_pD3DDevice->Reset( &g_D3DSettings.m_PresentParams );
                if( FAILED(rslt) )
                {
                    D3DError(rslt,__LINE__,__FILE__,"Failed To Reset the device during resizing");
   	 ::PostQuitMessage(0);
                }

    RestoreDeviceObjects();
 	 }

 	 /////Window has been minimized
 	 if( g_pD3DDevice != NULL && wParam == SIZE_MINIMIZED )
    g_D3DSettings.m_bPaused = TRUE;

 	 
 	 
 	 return DefWindowProc(hWnd,uMsg,wParam,lParam);
  }
  break;
	case WM_ACTIVATE:
  {

 	 switch(wParam)
 	 {
 	 case WA_ACTIVE:
    g_D3DSettings.m_bPaused = FALSE;
    break;
 	 case WA_INACTIVE:
    g_D3DSettings.m_bPaused = TRUE;
    break;
 	 }
 	 return DefWindowProc(hWnd,uMsg,wParam,lParam);
  }
  break;


	default:
  return DefWindowProc(hWnd,uMsg,wParam,lParam);
  
	}

}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
      // Register the window class
      WNDCLASSEX wc;

      ZeroMemory(&wc, sizeof(WNDCLASSEX));
      wc.cbSize=sizeof(WNDCLASSEX);                       // size of the window struct in bytes
      wc.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;        // window styles to use
      wc.lpfnWndProc=MsgProc;                             // function name of event handler
      wc.hInstance=hInstance;                             // handle to this apps instance
      wc.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);// background colour of window
      wc.hIcon= LoadIcon(NULL, IDI_APPLICATION);          // icon for the app window
      wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);         // icon when minimized to taskbar
      wc.hCursor=LoadCursor(NULL, IDC_ARROW);             // cursor to use for this window
      wc.lpszClassName="MY_WINDOW_CLASS_NAME";            // name for this class

      RegisterClassEx( &wc );

      // Create the application's window
   g_D3DSettings.m_nDeviceWidth = 800;
   g_D3DSettings.m_nDeviceHeight= 600;
   g_D3DSettings.m_bPaused   = FALSE;

   g_D3DSettings.SetAspect();


      g_hApplicationWindow = CreateWindow("MY_WINDOW_CLASS_NAME", "MY WINDOW TITLE",
          WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,
          NULL, NULL, wc.hInstance, NULL );

      // Show the window
      ShowWindow( g_hApplicationWindow, nCmdShow );
      UpdateWindow( g_hApplicationWindow );

  HRESULT rslt = InitD3D();
  if(FAILED(rslt))
  {
   D3DError(rslt,__LINE__,__FILE__,"InitD3D Failed");
   UnregisterClass( "MY_CLASS_NAME", wc.hInstance );
   return rslt;
  }

      // Enter the message loop
      MSG msg;
      ZeroMemory( &msg, sizeof(msg) );
      while( msg.message!=WM_QUIT )
      {
          if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
          {
              TranslateMessage( &msg );
              DispatchMessage( &msg );
          }
          else
          {
              AppLoop();
          }
      }

   AppShutDown();
   

      UnregisterClass( "MY_CLASS_NAME", wc.hInstance );
      return 0;

}


HRESULT InitD3D()
{
	g_pD3D=Direct3DCreate9(D3D_SDK_VERSION);

	if(g_pD3D==NULL)
	{
  return E_FAIL;
	}


	// Populate our struct with how we want to set up D3D...
	g_D3DSettings.m_bWindowed=0;
	g_D3DSettings.m_bMultiSampling=FALSE;
	g_D3DSettings.m_D3DFormat=D3DFMT_X8R8G8B8;

	////////////////////////////////////////////////////
	/////////////Time To Prepare Our Device/////////////

	D3DPRESENT_PARAMETERS d3dpp;
	D3DDISPLAYMODE        d3ddm;

	g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm);

	ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
	d3dpp.BackBufferWidth  = g_D3DSettings.m_nDeviceWidth;
	d3dpp.BackBufferHeight  = g_D3DSettings.m_nDeviceHeight;
	d3dpp.BackBufferFormat = g_D3DSettings.m_bWindowed ? d3ddm.Format : g_D3DSettings.m_D3DFormat;
	d3dpp.hDeviceWindow=g_hApplicationWindow;
	d3dpp.Windowed=g_D3DSettings.m_bWindowed;
	d3dpp.BackBufferCount=1;	
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;


	if(g_D3DSettings.m_bMultiSampling)
	{
  
  if( SUCCEEDED(g_pD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
                d3dpp.BackBufferFormat, 
                g_D3DSettings.m_bWindowed, 
                D3DMULTISAMPLE_2_SAMPLES, NULL)))
  {
 	 d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
  }
  else
 	 d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
	}
	else
  d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;

	d3dpp.EnableAutoDepthStencil=TRUE;
	d3dpp.AutoDepthStencilFormat=D3DFMT_D16;
	d3dpp.FullScreen_RefreshRateInHz=0;
	d3dpp.PresentationInterval = g_D3DSettings.m_bWindowed ? 0 : D3DPRESENT_INTERVAL_IMMEDIATE;
	d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

	HRESULT rslt=g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hApplicationWindow,
       D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice);
	if(FAILED(rslt))
	{
  rslt=g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hApplicationWindow,
           D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice);
  if(FAILED(rslt))
  {
 	 return E_FAIL;
  }
	}

	g_D3DSettings.m_PresentParams=d3dpp;
	if(g_D3DSettings.m_bWindowed)
  g_D3DSettings.m_D3DFormat=d3dpp.BackBufferFormat;


	return RestoreDeviceObjects();

}
HRESULT Render()
{
	if(!g_pD3DDevice) return E_FAIL;
	HRESULT rslt = ValidateDevice();
	if(FAILED(rslt)) return rslt;


	g_pD3DDevice->Clear(0,0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(1,0,0,55), 1.0f, 0);

	rslt = g_pD3DDevice->BeginScene();
	if(FAILED(rslt)) return rslt;

	D3DXMATRIX matWorld,matRotation;
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixRotationY(&matRotation,timeGetTime()/500.0f);

	matWorld = matWorld * matRotation;

	matWorld._43 = 7;

	g_pD3DDevice->SetTransform(D3DTS_WORLD,&matWorld);

	g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);



	g_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
	g_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );



	g_pMesh->DrawSubset(0);


	D3DXMatrixRotationY(&matWorld,timeGetTime()/300.0f);
	matWorld._43 = 5;	
	matWorld._41 = -1;
	g_pD3DDevice->SetTransform(D3DTS_WORLD,&matWorld);
	g_pMesh->DrawSubset(0);

	g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);


	g_pD3DDevice->EndScene();

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

	return S_OK;
}

HRESULT ValidateDevice()
{
	HRESULT rslt = g_pD3DDevice->TestCooperativeLevel();
	if(FAILED(rslt))
	{
  if(rslt == D3DERR_DEVICELOST)
 	 return E_FAIL;

  if(rslt == D3DERR_DEVICENOTRESET)
  {
 	 InvalidateDeviceObjects();

 	 g_pD3DDevice->Reset(&g_D3DSettings.m_PresentParams);

 	 RestoreDeviceObjects();
  }
	}
	return S_OK;
}

HRESULT RestoreDeviceObjects()
{

	g_pD3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
	g_pD3DDevice->SetRenderState(D3DRS_SPECULARENABLE,TRUE);
	//g_pD3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NULL);

	D3DXMATRIX matView;
	D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0,2,0),&D3DXVECTOR3(0,0,5),&D3DXVECTOR3(0,1,0));
	g_pD3DDevice->SetTransform(D3DTS_VIEW,&matView);




	D3DXMATRIX matProjection;
	D3DXMatrixPerspectiveFovLH( &matProjection, D3DX_PI/4, g_D3DSettings.m_fScreenAspect, 0.1f, 500.0f );
    g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProjection );



	D3DXCreateTeapot(g_pD3DDevice,&g_pMesh,NULL);

	D3DMATERIAL9 material;
	ZeroMemory(&material,sizeof(material));
	material.Diffuse.r = material.Diffuse.g = material.Diffuse.b = material.Diffuse.a = 0.2f;
	material.Ambient = material.Diffuse;
	material.Specular.r = 1;
	material.Specular.g = 1;
	material.Specular.b = 1;
	material.Specular.a = 0.5;

	material.Power = 30.0f;

	g_pD3DDevice->SetMaterial(&material);



	D3DLIGHT9 light;
	ZeroMemory(&light,sizeof(light));
	light.Type = D3DLIGHT_DIRECTIONAL;
	light.Direction = D3DXVECTOR3(1,0,1);

	light.Diffuse.r = light.Diffuse.g = light.Diffuse.b = light.Diffuse.a = 1;
	light.Ambient = light.Specular = light.Diffuse;

	g_pD3DDevice->SetLight(0,&light);
	g_pD3DDevice->LightEnable(0,TRUE);








	return S_OK;
}

HRESULT InvalidateDeviceObjects()
{
	return S_OK;
}


void AppLoop()
{
	if(g_D3DSettings.m_bPaused)  return;


	HRESULT rslt;
	rslt = Render();
	if(FAILED(rslt)) D3DError(rslt,__LINE__,__FILE__,"Render() Has Failed");
}

void AppShutDown()
{
	InvalidateDeviceObjects();

	SAFE_RELEASE(g_pD3D);
	SAFE_RELEASE(g_pD3DDevice);
  
}


HRESULT D3DError(HRESULT hrCode, int nLine, char* szFile, char* szExtraInfo)
{
	::OutputDebugString("--------------------------D3DError Has  Been Called---------------------------\n");
	char pszError[256];
	wsprintf(pszError, "The following error occurred on line %d of %s\n", nLine, szFile);
	::OutputDebugString(pszError);
	::OutputDebugString(DXGetErrorString9(hrCode));
	::OutputDebugString("\n");
	if(szExtraInfo)
	{
  ::OutputDebugString("Extra information: ");
  ::OutputDebugString(szExtraInfo);
  ::OutputDebugString("\n");
	}

	return hrCode;
}
#3

ياسلام عليك يا justnow ,, والله أحلى عيدية :)

خليتني أنشط الذاكرة بتاعت ال Stack عندي الخاصة ب Direct3D ,, لأنو لي فترة لم أتعامل بال Direct3D !!

عموما أتمنى أن نعود بشكل أفضل بعد العيد بإذن الله .

==========================

بالنسبة للمزج يوجد شيء غريب بما أنك قلت أنك تحبذ طريقة ترتيب عمل Rendring بترتيب معين وهو الأول بالنسبة لكلامك .

هل للمزج علاقة بالترتيب ؟

أعتقد أن النتيجة ستكون واحدة في كلا الحالتين وإعذرني إن تحدثت دون أن أجرب فD3d لم أثبته بعد لأن الوندوز جديد :)

وفعلا كما قلت المزج يأخذ من سرعة ال Rendring بكمية لابأس بها ,,

وبالنسبة للغربلة Culling ,, فعلا شيء غريب إذا لم نقم برسم المضلعات الخلفية أيضا يفترض أن تظهر الشفافية :huh: لم أجربها ,, لكن أتحدث عن المنطق ,,

عموما Direct3D لايمكن تعلمه بأخوي وأخوك ,, يحتاج لتجارب قاسية وسهر ليالي لتصبح متقدم فيه .

وأذكر أنني كنت أعمل على مشروع في أسبوع الكلية عندنا وهي مناسبة سنوية في الكلية ,, المهم كنت في بدايات تعلم Direct3D وكنت أود أن أصمم برنامج رسم 3D ,, يتعامل مع ال Objects برسم مكعبات وكرات وأشكال منتظمة وتحميل نماذج وإختيار Texturing للنماذج وإضاءة وإضفت بعض الضباب للمشهد مع عمل إمكانية لتحريك المشهد والكائنات بالماوس وأرض متعرجة بشكل عشوائي ,, وأخيرا أضفت إمكانية لتصميم النماذج بعمل دوران على محور Y لرسم في بعدين بحيث يظهر النموذج المدار في النهاية ,, الخلاصة أن المشروع كان بشع !!

كل ماأردت قوله أن هناك أمور لن تتوقعها في Direct3D وستبحث كثيرا ولن تجد شيئا ,, ولن ينقذك سوى أن تجد مثال جاهز فيه هذه الجزئية وتقوم بمتابعة المثال الجاهز الذي يعمل وتعرف سبب المشكلة منه عندك أو أن يتغمدك الله برحمته (a)

المشروع الذي أنجزته قمت بتسليمه قبل العرض بساعتين فقط ,, وكنت أعمل عليه لمدة 4 أيام :| :blink: مع أنه كان يستحق وقت أقل ,, ولم يكن بالنتيجة المطلوبة ويفعل بعض الأمور أحيانا بشكل صائب وأحيانا لا :huh:

المهم كانت تجربتي الأولى ومن يومها وأنا أحاول وأحاول لكن يبدو أنا الموضوع صعب فعلا :) ولنا عودة بعد العيد بحول الله .

آسف على الإطالة فقط أردت أن أعطي تجربتي عسى أن تنفع :mellow:

وتشكر على العيدية يا justnow مرة أخرى :)

banner_60_468.gif

NOTHING IS IMPOSSIBLE

#4

تشكر الاخ المشرف على هذا الاطراء الذى اثلج قلبى

اريد ان ارد على بعض تلك الاستفهامات التى و ضعتها فى وجهى؟؟؟؟؟

بالنسبة لعلاقة المزج بالترتيب:-

فى الحقيقة ولا حتى انا جربت ان اعمل العكس. و كان يمكننى ببساطة

ان لا اذكر اى سيرة عن اهمية عملية الترتيب. لكن بينما كنت اقراء احد الكتب على ما

اظن ان اسمه Advanced DirectX او شئ من هذا القبيل (لسؤ الحظ انا لست فى البيت

حتى استطيع ان اعطيك الاسم صحيحا). كان الكتاب يتحدث عن ال Z-Buffer و اكد على

انك لن تحتاج الى عملية ترتيب فى الرسم الا اذا كنت تستعمل ال Blending.

وحتى لا ادخل نفسى فى نقطة حرجة استخدمت هذا الموضوع كمدخل

اما بالنسبة لل Culling فلن اتحدث فى هذا الموضوع حتى يقوم الجميع بتجربة المثال.

عدم تحدثى بالموضوع ليس سرا لكن ما تراه العين يمكن ان يكون ابلغ من الكلام.

#5

السلام عليكم و رحمة الله

فى الحقيقة توقعت ان اجد المزيد من الردود و المناقشات الحادة فى الموضوع

و لكن يبدو ان الجميع يستمتعون بالعيد و ليس هنا المتسع من الوقت حتى يردوا

لكنى مصمم على ان اضيف على الموضوع, الشئ ولو القليل.

بالنسبة لردى السابق حول عملية الترتيب:-

كما يرى القارئ انى قلت يجب مراعاة الترتيب بحيث يتم رسم البعيد اولا ثم القريب

و ها انا ذا اعود لاكرر نفس الكلام ولكن بصيغة مختلفة.

لو قرات الموضوع الاساسى اولا لوجدت العبارة التالية

اى ان ال Z-BufferTest يسبق عملية الBlending فى الترتيب فى ال pipeline

هذا حقيقى ولكن تبدو هناك نقطة ضعيفة فى هذه الجملة تسمح لنا بالاختراق.

نعم هناك ثغرة (ثغرة قانونية كما يسميها المحامون) يمكن ان نناقض بها اهمية

الترتيب.

ترى ماهى, لكى اوضح هذه الثغرة ساثرثر كثيرا لانى لا انوى اضافة سطرين

من الكود و اقول لكم يمكن ان تعمل الان.

هل تعرف كيف يعمل ال Z-Buffer ؟ هنا يكمن الحل. باختصار فان ال Z-Buffer هو

ليس الا سطح ثنائى الابعاد كما هو الحال مع الFrame Buffer .

تأمل معى هذا السطر

g_pD3DDevice->Clear(0,0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(1,0,0,55), 1.0f, 0);

فى بداية عملية الرسم نقوم بمسح ال Z-Buffer. الان و بعد ذلك لو قمنا برسم

مثلث, و لنفترض ان كل ال pipiline قد مر و نحن فى الجذء الخاص بالZ-Buffer, بما

انه ليس هناك اى شئ قبل الثلث, سيرسل المثلث مباشرة الى ال Frame Buffer ويرسم كاملا عليه.

و لكن ماذا اذا رسمنا مثلث اخر يتقاطع مع مثلثنا الاول, سيقومZ-Buffer

بمقارنة كل نقطة تابعة الى المثلث الثانى و يتاكد انها اقرب الى الكاميرا

من سابقتها التى جاءت من المثلث الاول(تذكر ان المثلثين يتقاطعان)

. من المفترض ان ترسم على ال Frame Buffer اذا كانت اقرب او تساوى بعد النقطة

التى قورنت بها. وهكذا يمكن ان ننجذ كل التعقيدات بطريقة بسيطة و لكن تكلف الكثير.

فى الاغلب ان لم يكن الاعم تتم هذه العملية داخل بطاقة الشاشة Hardware

من ما يضمن السرعة الكبيرة.

اين انا الان من الابريقين. لقد صرفت الكثير من الكلام. ولكن تذكر معى العبارة الخضراء

عملية المقرنه تضمن مرور النقطة اذا كانت اقرب او تساوى النقطة التى يفترض ان تغطيها

فى ال Frame Bufer. اذا امكننا ان نعدل هذا الشرط (اقل من او يساوي) يمكننا التلاعب

كثيرا.

Direct3D يسمح بذلك فقط راجع الدالة SetRenderState و معملها الاول D3DRS_ZFUNC

يمكننا ان نفعل شئ بسيط. ولكن سادعه للبقية حتى يقوموا به :)

#6
اقتباس
عملية المقرنه تضمن مرور النقطة اذا كانت اقرب او تساوى النقطة التى يفترض ان تغطيها

فى ال Frame Bufer. اذا امكننا ان نعدل هذا الشرط (اقل من او يساوي) يمكننا التلاعب

كثيرا.

كلام وزنه ذهب فعلا ,,

مختصر مفيد لعملية المزج وستريحنا مستقبلا من الدخول في متاهات وعلامات إستفهام .

وبالنسبة لل Z Buffer فهذا ماوجدته عن الموضوع :

D3DRS_ZWRITEENABLE
TRUE to enable the application to write to the depth buffer. The default value is TRUE. This member enables an application to prevent the system from updating the depth buffer with new depth values. If FALSE, depth comparisons are still made according to the render state D3DRS_ZFUNC, assuming that depth buffering is taking place, but depth values are not written to the buffer.

banner_60_468.gif

NOTHING IS IMPOSSIBLE

هذا الموضوع مغلق.

مواضيع مشابهة