示例#1
0
bool World::drawImage(RenderFrame* pRenderFrame,RenderMesh* pRenderMesh)
{
	//デバイスの状況チェック
	if(!isDeviceActive())
		return false;
	IDirect3DDevice9* pd3dDevice = Device::getInterface();
	if(!pd3dDevice)
		return false;

	Mesh* mesh = pRenderMesh->mesh;
	if(!mesh)
		return false;

	RenderFrame* renderFrame = pRenderMesh->renderFrame;

	Vertex* vertex = mesh->getVertexBuffer();
	if(!vertex)
		return false;
	IDirect3DVertexBuffer9* pVertexBuffer = vertex->getInterface();
	if(!pVertexBuffer)
		return false;
	Index* index = mesh->getIndexBuffer();
	IDirect3DIndexBuffer9* pIndexBuffer = index?index->getInterface():NULL;
	

	RenderUnit* renderUnit = renderFrame->renderUnit;
	Unit* unit = renderUnit->unit;
	bool shaderFlag = mesh->isShader();

	//ビュークリップ
	if(unit->isViewClip())
	{
		RECT& viewRect = renderFrame->renderUnit->clipRect;
		if(viewRect.top >= viewRect.bottom || viewRect.left >= viewRect.right)
			return true;

		NVector box1 = {(FLOAT)viewRect.left,(FLOAT)viewRect.top,0,1};
		NVector	box2 = {(FLOAT)viewRect.right,(FLOAT)viewRect.top,0,1};
		NVector	box3 = {(FLOAT)viewRect.left,(FLOAT)viewRect.bottom,0,1};
		NVector out1 = box1.transformCoord(renderFrame->matrix);
		NVector out2 = box2.transformCoord(renderFrame->matrix);
		NVector out3 = box3.transformCoord(renderFrame->matrix);

		Device::setClipper(
			out1.x,out1.y,out1.z,
			out2.x,out2.y,out2.z,
			out3.x,out3.y,out3.z);
	}

	//座標の設定
	if(shaderFlag)
	{
		VertexShader* vertexShader = mesh->getVertexShader();
		Device::getInterface()->SetVertexShader(*vertexShader);
		//シェーダ
		NMatrix matrix[100];	
		NMatrix* matView;
		NMatrix* matProj;
		NMatrix matWork;
		if(m_camera)
		{
			if(unit->isView2D())
			{
				matView = &m_camera->getBaseView();
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
			}
			else
			{
				matView = &m_camera->getView();
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,m_camera->getCull());
			}
			matProj = &m_camera->getProjection();
		}
		vertexShader->setDefaultParam();

		Material* material = mesh->getMaterial();
		vertexShader->setParam("MaterialDiffuse",&material->Diffuse);
		vertexShader->setParam("MaterialAmbient",&material->Ambient);
		vertexShader->setParam("View",matView);
		vertexShader->setParam("Proj",matProj);
		vertexShader->setParam("World",&renderFrame->matrix);
		
		if(vertexShader->isParam("LightDir"))
		{
			if(unit->isLight())
			{
				NVector v = {0.1f,-0.5f,-0.5f,0.0f};
				vertexShader->setParam("LightDir",&v);
			}
			else
			{
				static NVector v = {0,0,0};
				vertexShader->setParam("LightDir",&v);
			}
		}
		if(vertexShader->isParam("WorldView") || vertexShader->isParam("WorldViewProj"))
		{
			
			matWork = renderFrame->matrix * *matView;
			vertexShader->setParam("WorldView",&matWork);
			if(vertexShader->isParam("WorldViewProj"))
			{
				matWork *= *matProj;
				vertexShader->setParam("WorldViewProj",&matWork);
			}
			
		}
		if(vertexShader->isParam("ViewProj"))
		{
			matWork = *matView * *matProj;
			vertexShader->setParam("ViewProj",&matWork);
		}
		if(pRenderMesh->boneCount > 0)
		{
			INT i;
			BONEMATRIX* boneMatrixs = &(*mesh->getBoneMatrix())[0];
			for(i=0;i<pRenderMesh->boneCount;i++)
			{
				matrix[i] = boneMatrixs[i].matrix * pRenderFrame[pRenderMesh->boneData[i]].matrix;
			}
			vertexShader->setParam("WorldMatrixArray",matrix,pRenderMesh->boneCount);
		}
	}
	else
	{
		//固定機能
		if(pRenderMesh->boneCount == 0)
		{
			pd3dDevice->SetSoftwareVertexProcessing(false);
			pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND ,D3DVBF_DISABLE);
			pd3dDevice->SetTransform(D3DTS_WORLD ,(D3DMATRIX*)&renderFrame->matrix);
		}
		else
		{
			//ハードウエアの能力が足りるかどうか
			const D3DCAPS9* desc = Device::getCaps();
			if(Device::getCaps()->MaxVertexBlendMatrixIndex < 3
				||(INT)Device::getCaps()->MaxVertexBlendMatrices < pRenderMesh->boneCount)
				pd3dDevice->SetSoftwareVertexProcessing(true);
			pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE,TRUE);
			pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND ,D3DVBF_3WEIGHTS );

			INT i;
			std::vector<BONEMATRIX>* boneMatrixs = mesh->getBoneMatrix();
			for(i=0;i<pRenderMesh->boneCount;i++)
			{
				pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(i) ,(D3DMATRIX*)&pRenderFrame[pRenderMesh->boneData[i]].matrix);
				pd3dDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i) ,(D3DMATRIX*)&(*boneMatrixs)[i].matrix);
			}
		}
		//ビュー設定
		if(m_camera)
		{
			if(unit->isView2D())
			{
				pd3dDevice->SetTransform( D3DTS_VIEW, (D3DMATRIX*)&m_camera->getBaseView());
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
			}
			else
			{
				pd3dDevice->SetTransform( D3DTS_VIEW, (D3DMATRIX*)&m_camera->getView());
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,m_camera->getCull());
			}
		}
		//----------------------------
		//ライティング
		if(unit->isLight())
			pd3dDevice->SetRenderState(D3DRS_LIGHTING,true);
		else
			pd3dDevice->SetRenderState(D3DRS_LIGHTING,false);
		//----------------------------
		Material* material = pRenderMesh->mesh->getMaterial();
		if(unit->isLight())
		{
			if(material)
			{
				pd3dDevice->SetMaterial((D3DMATERIAL9*)material);
				pd3dDevice->SetRenderState(D3DRS_COLORVERTEX,true);
				pd3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_COLOR1);
				pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
				pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
			}
		}
	}	
	

	Texture* pTexture = pRenderMesh->mesh->getTexture();
	IDirect3DTexture9* pITexture = NULL;
	if(pTexture)
	{
		if(renderUnit->alpha != 100)
		{
			DWORD alpha = (0xff * renderUnit->alpha / 100) << 24;
			pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,alpha);
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
		}
		else
		{
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
			pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
		}
		pITexture = pTexture->getInterface();
	}




	//----------------------------
	//Zバッファの設定
	if(unit->isZBuffer())
	{
		pd3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
		pd3dDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
	}
	else
	{
		pd3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);
	//	pd3dDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
	//	pd3dDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS);
	}

	D3DTEXTUREFILTERTYPE filter = unit->getTextureFilter();
	pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,filter);
	pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,filter);
	pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,filter);
	if(filter == D3DTEXF_ANISOTROPIC)
	{
		pd3dDevice->SetSamplerState(0,D3DSAMP_MAXANISOTROPY,16);
	}

	//クリッピングの設定
	if(unit->getClipWidth() || unit->getClipHeight() || unit->getClipDepth())
	{
		Device::setClipper(unit->getClipX(),unit->getClipY(),unit->getClipZ(),
			unit->getClipWidth(),unit->getClipHeight(),unit->getClipDepth());

	}
	if(pRenderMesh->shadow)
	{
		pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
		pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
	}
	else if(renderUnit->alpha != 100 && !pTexture)
	{
		BYTE a = (BYTE)(0xff * renderUnit->alpha / 100);
		BYTE alpha[4] = {a,a,a,0};
		pd3dDevice->SetRenderState(D3DRS_BLENDFACTOR,*(LPDWORD)&alpha);
		pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR);
		pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVBLENDFACTOR);
		pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
		pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 8);
	}
	else
	{
		switch(unit->getBlendMode())
		{
		case 0: //ブレンド設定
			pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
			pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
			pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
			pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 8);
			break;
		case 1:
			pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE);
			pd3dDevice->SetRenderState( D3DRS_DESTBLEND,  D3DBLEND_ONE);
			break;
		case 2:
			pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
			pd3dDevice->SetRenderState( D3DRS_DESTBLEND,  D3DBLEND_SRCALPHA);
			pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL);
			pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 247);
			break;
		}
	}

	if(shaderFlag)
	{
		Device::getInterface()->SetVertexDeclaration(mesh->getDeclaration());
	}

		
	//描画
	pd3dDevice->SetTexture(0,pITexture);

	INT iPrimitiveCount;
	INT iVertexCount = vertex->getStrideCount();

	if(index)
	{
		if(mesh->getPrimitiveType() == D3DPT_TRIANGLELIST)
			iPrimitiveCount = index->getCount() / 3;
		else
			iPrimitiveCount = index->getCount() / 2;
	}
	else
	{
		if(mesh->getPrimitiveType() == D3DPT_TRIANGLELIST)
			iPrimitiveCount = iVertexCount / 3;
		else
			iPrimitiveCount = iVertexCount / 2;
	}

	pd3dDevice->SetStreamSource(0,pVertexBuffer,0,vertex->getStrideSize());
	if(!shaderFlag)
		pd3dDevice->SetFVF(vertex->getFVF());
	pd3dDevice->SetIndices(pIndexBuffer);
	if(pRenderMesh->shadow)
	{
		if(Device::getCaps()->StencilCaps)
		{
			pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);

			//pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, false);
			pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_FLAT);
			pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);
			pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);

			if(false && Device::getCaps()->StencilCaps & D3DSTENCILCAPS_TWOSIDED)
			{
				//両面可能
				pd3dDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE,true);
				pd3dDevice->SetRenderState(D3DRS_CCW_STENCILFUNC,D3DCMP_ALWAYS);
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
				pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);
				pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_DECR);
				pd3dDevice->SetRenderState(D3DRS_CCW_STENCILPASS,D3DSTENCILOP_KEEP);
				pd3dDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL,D3DSTENCILOP_INCR);
				pd3dDevice->DrawIndexedPrimitive(mesh->getPrimitiveType() ,0,0 ,iVertexCount,0,iPrimitiveCount);
				pd3dDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE,false);
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
			}
			else
			{
				pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);
				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
				pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_INCR);
				pd3dDevice->DrawIndexedPrimitive(mesh->getPrimitiveType() ,0,0 ,iVertexCount,0,iPrimitiveCount);

				pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
				pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_DECR);
				pd3dDevice->DrawIndexedPrimitive(mesh->getPrimitiveType() ,0,0 ,iVertexCount,0,iPrimitiveCount);

			}
			pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,false);
			pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
			pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);
			//pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, true);
		}

	}
	else
	{
	//pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);


		pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
		pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
		pd3dDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL,D3DSTENCILOP_KEEP);
		pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
		if(pIndexBuffer)
			pd3dDevice->DrawIndexedPrimitive(mesh->getPrimitiveType() ,0,0 ,iVertexCount,0,iPrimitiveCount);
		else
			pd3dDevice->DrawPrimitive(mesh->getPrimitiveType() ,0,iPrimitiveCount);

	//	pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,false);
	}

	if(shaderFlag)
	{
		Device::getInterface()->SetVertexShader(NULL);
		Device::getInterface()->SetPixelShader(NULL);
		Device::getInterface()->SetVertexDeclaration(NULL);
	}
	else
		pd3dDevice->SetFVF(NULL);

	Device::getInterface()->SetRenderState( D3DRS_SCISSORTESTENABLE, false );

	//クリッピングの解除
	if(unit->isViewClip() || unit->getClipWidth() || unit->getClipHeight() || unit->getClipDepth())
	{
		Device::setClipper(0,0,0,0,0,0);
	}
	return true;
}