[HGE]-源码分析-5 core里的graphics(b)

本文深入探讨了游戏开发领域的核心技术,包括游戏引擎、编程语言、图像处理、音视频技术等,旨在帮助开发者从基础知识到高级技能全面提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  接着上次说

下一个函数

全转换函数(自己起的名。。。)

void CALL HGE_Impl::Gfx_SetTransform(float x, float y, float dx, float dy, float rot, float hscale, float vscale)
{
	D3DXMATRIX tmp;

	if(vscale==0.0f) D3DXMatrixIdentity(&matView);
	else
	{
		D3DXMatrixTranslation(&matView, -x, -y, 0.0f);
		D3DXMatrixScaling(&tmp, hscale, vscale, 1.0f);
		D3DXMatrixMultiply(&matView, &matView, &tmp);
		D3DXMatrixRotationZ(&tmp, -rot);
		D3DXMatrixMultiply(&matView, &matView, &tmp);
		D3DXMatrixTranslation(&tmp, x+dx, y+dy, 0.0f);
		D3DXMatrixMultiply(&matView, &matView, &tmp);
	}

	_render_batch();
	pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
}

看代码就能看出,这是对DX的矩阵变换函数做了个封装,不管怎么变都用这一个搞定了。

和上一个函数不同的是,这里变的是视图矩阵,就是摄像机的位置,上次那个投影矩阵是摄像机能看到的范围,

在3d世界里,我们感觉到一个东西在动,其实是摄像机在动,因此要有什么变化的话动摄像机就行,方向设相反的,就像这里的-x,-y

函数默认参数是0(vscale垂直变换比例,这个值不可为0,自己用的时候要注意这些值都要有实参),如果有参数为0则将视图矩阵单位化

这里没有做全部判断的检查,自己使用要注意。

 

开始渲染图像

bool CALL HGE_Impl::Gfx_BeginScene(HTARGET targ)
{
	LPDIRECT3DSURFACE8 pSurf=0, pDepth=0;//用法略神奇,dx9已经不这么干了,这里是声明了两个表面,一个用来显示(主缓冲),一个当作Z缓存
	D3DDISPLAYMODE Mode;//显示模式  里面有范围,刷新频率,表面格式等等
	CRenderTargetList *target=(CRenderTargetList *)targ;//链式结构的渲染目标

	HRESULT hr = pD3DDevice->TestCooperativeLevel();//检测设备
	if (hr == D3DERR_DEVICELOST) return false;
	else if (hr == D3DERR_DEVICENOTRESET)
	{
		if(bWindowed)
		{
			if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) 
			{
				_PostError("Can't determine desktop video mode");
				return false;
			}
                            //窗口化时的设定,设定后被缓冲格式,位深
			d3dppW.BackBufferFormat = Mode.Format;
			if(_format_id(Mode.Format) < 4) nScreenBPP=16;
			else nScreenBPP=32;
		}
                   //全屏应该是默认有设置所以没有操作
	    if(!_GfxRestore()) return false; 
	}
    
	if(VertArray)
	{
		_PostError("Gfx_BeginScene: Scene is already being rendered");
		return false;
	}
	
	if(target != pCurTarget)
	{
		if(target)
		{
			target->pTex->GetSurfaceLevel(0, &pSurf);//得到一个相应等级的表面,0为最上层,这里因为pSurf是主表面,将要被渲染肯定得在最上层
			pDepth=target->pDepth;//直接获得z深度
		}
		else
		{
			pSurf=pScreenSurf;
			pDepth=pScreenDepth;
		}
		if(FAILED(pD3DDevice->SetRenderTarget(pSurf, pDepth)))//设置渲染目标,一个是主表面,一个是对应的z深度,现在这种用法dx9已经木有了
		{
			if(target) pSurf->Release();
			_PostError("Gfx_BeginScene: Can't set render target");
			return false;
		}
		if(target)
		{
			pSurf->Release();//用完释放   
			if(target->pDepth) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); 
			else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );//根据判断看要不要开z缓冲 
			_SetProjectionMatrix(target->width, target->height);
		}
		else
		{         //同上
			if(bZBuffer) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); 
			else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
			_SetProjectionMatrix(nScreenWidth, nScreenHeight);
		}

		pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
		D3DXMatrixIdentity(&matView);
		pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

		pCurTarget=target;
	}

	pD3DDevice->BeginScene();//开始渲染
	pVB->Lock( 0, 0, (BYTE**)&VertArray, 0 );//这里应该起的事一个标记作用,标记已经渲染,只是给VertArray一个初识地址,让它不空,没有锁一点内存

	return true;
}

 

函数用的接口比较老,但是原理还是一样的,把要渲染的内容放在主表面里,然后渲染出来

 

void CALL HGE_Impl::Gfx_EndScene()
{
	_render_batch(true);//后面说这个
	pD3DDevice->EndScene();
	if(!pCurTarget) pD3DDevice->Present( NULL, NULL, NULL, NULL );//拉一下交换链,把下一个替换上来,NULL参数是剩余所有的表面,这里只开了两个表面
}

结束渲染,直接调用接口就行。

 

画线函数,在(x1,y1)(x2,y2)之间画一条深度为z的color颜色的线

void CALL HGE_Impl::Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color, float z)
{
	if(VertArray)
	{
		if(CurPrimType!=HGEPRIM_LINES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_LINES || CurTexture || CurBlendMode!=BLEND_DEFAULT)
		{
			_render_batch();

			CurPrimType=HGEPRIM_LINES;
			if(CurBlendMode != BLEND_DEFAULT) _SetBlendMode(BLEND_DEFAULT);
			if(CurTexture) { pD3DDevice->SetTexture(0, 0); CurTexture=0; }
		}

		int i=nPrim*HGEPRIM_LINES;
		VertArray[i].x = x1; VertArray[i+1].x = x2;
		VertArray[i].y = y1; VertArray[i+1].y = y2;
		VertArray[i].z     = VertArray[i+1].z = z;
		VertArray[i].col   = VertArray[i+1].col = color;
		VertArray[i].tx    = VertArray[i+1].tx =
		VertArray[i].ty    = VertArray[i+1].ty = 0.0f;

		nPrim++;
	}
}

绘制工作是由dx的函数完成的,HGE有3种基本的图元绘制,除了线之外还有三角形和四边形

具体的绘制工作都是由_render_batch这货完成的,它判断要绘制的内容,完成绘制,还要控制渲染状态(开始和结束)

最后在定点列表里记录下直线的起始和结束点

 

void CALL HGE_Impl::Gfx_RenderTriple(const hgeTriple *triple)
{
	if(VertArray)
	{
		if(CurPrimType!=HGEPRIM_TRIPLES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_TRIPLES || CurTexture!=triple->tex || CurBlendMode!=triple->blend)
		{
			_render_batch();

			CurPrimType=HGEPRIM_TRIPLES;
			if(CurBlendMode != triple->blend) _SetBlendMode(triple->blend);
			if(triple->tex != CurTexture) {
				pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)triple->tex );
				CurTexture = triple->tex;
			}
		}

		memcpy(&VertArray[nPrim*HGEPRIM_TRIPLES], triple->v, sizeof(hgeVertex)*HGEPRIM_TRIPLES);
		nPrim++;
	}
}

void CALL HGE_Impl::Gfx_RenderQuad(const hgeQuad *quad)
{
	if(VertArray)
	{
		if(CurPrimType!=HGEPRIM_QUADS || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_QUADS || CurTexture!=quad->tex || CurBlendMode!=quad->blend)
		{
			_render_batch();

			CurPrimType=HGEPRIM_QUADS;
			if(CurBlendMode != quad->blend) _SetBlendMode(quad->blend);
			if(quad->tex != CurTexture)
			{
				pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)quad->tex );
				CurTexture = quad->tex;
			}
		}

		memcpy(&VertArray[nPrim*HGEPRIM_QUADS], quad->v, sizeof(hgeVertex)*HGEPRIM_QUADS);
		nPrim++;
	}
}

其他的两个原始图元都一个德行。

 

hgeVertex* CALL HGE_Impl::Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim)
{
	if(VertArray)
	{
		_render_batch();

		CurPrimType=prim_type;
		if(CurBlendMode != blend) _SetBlendMode(blend);
		if(tex != CurTexture)
		{
			pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE8)tex );
			CurTexture = tex;
		}

		*max_prim=VERTEX_BUFFER_SIZE / prim_type;
		return VertArray;
	}
	else return 0;
}

void CALL HGE_Impl::Gfx_FinishBatch(int nprim)
{
	nPrim=nprim;
}


批量绘制图元,还有停止绘制图元,绘制还是依靠_rander_batch,会有一个混合类型判断

用指针传入的int来记录数量,这里的数量指定点缓存里能容纳的最大数量。



 


 

 

 

 


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值