⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vectorvectoroperation.cpp

📁 PDE simulator on GPU.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////
//// New Version on GL_NV_fragment_program
//// Vector(result) = a.Vector(x) op b.Vector(y)
//// Here a and b are scalar numbers
//// start from 2003/9/3
//// Support TEX_2D & TEX_RECTANGLE
//////////////////////////////////////////////////////////////////////////////
void  clVecOpFP(OperationOnGPUEnum op, const float a, const float b, const CVectorOnGPU& x, const CVectorOnGPU& y, CVectorOnGPU& result)
{
	unsigned int ShaderID;
	//////////////////////////////////////////////
	///If the size is compatible, then error occurs
	if(x.GetVectorLength() != y.GetVectorLength())
	{
		AfxMessageBox("Error to Operate on these two vectors for different size!");
		return;
	}
	////////////Determine the Texture TARGET
	unsigned int _iTextureTarget = x.GetTextureTarget();
	int Width  = x.GetWidth();
	int Height = x.GetHeight(); 
	
	////// Incorporate a and b varibles into Fragment Program
	GLfloat Va[4],Vb[4];
	for(int i=0;i<4;i++)
	{
		Va[i] = a;
		Vb[i] = b;
	}
	float fTexCoord[2];

	ShaderID = GlobeShaderID[op].ShaderID;

	if(_iTextureTarget == GL_TEXTURE_2D)
	{
		fTexCoord[0] = 1.0;
		fTexCoord[1] = 1.0;
	}
	else
	{
		fTexCoord[0] = Width;
		fTexCoord[1] = Height;
	}
/*
	unsigned int IndexArray[4] = {0,1,2,3};
	int VertexArray[8];
	int TextureArray[8];
	VertexArray[0] = 0;			TextureArray[0] = 0;
	VertexArray[1] = 0;			TextureArray[1] = 0;
	VertexArray[2] = Width;     TextureArray[2] = fTexCoord[0];
	VertexArray[3] = 0;			TextureArray[3] = 0;
	VertexArray[4] = Width;     TextureArray[4] = fTexCoord[0];
	VertexArray[5] = Height;    TextureArray[5] = fTexCoord[1];
	VertexArray[6] = 0;         TextureArray[6] = 0;
	VertexArray[7] = Height;    TextureArray[7] = fTexCoord[1];

	glEnableClientState ( GL_VERTEX_ARRAY );   
	glVertexPointer(2, GL_INT, 0, VertexArray);
*/
	//////////////////////////////////////////////
	///// Clear the framebuffer firstly to avoid the previous computation
	///// This step is important to avoid computation errors
//	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
//	glDisable(GL_DEPTH_TEST);

	///// Bind the Fragment Program to current drawing
	glEnable(GL_FRAGMENT_PROGRAM_NV);

	//// Add coefficients effect, Note here the first parameter is target not ID.
	glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, ShaderID);
	glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV,  0, Va);
	glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV,  1, Vb);

	////// Input the x and y variables as textures
	glActiveTextureARB( GL_TEXTURE0_ARB );
	glBindTexture(_iTextureTarget, x.GetTextureID());
//	glEnableClientState( GL_TEXTURE_COORD_ARRAY );
//	glTexCoordPointer(2, GL_INT, 0, TextureArray);
	glActiveTextureARB( GL_TEXTURE1_ARB );
	glBindTexture(_iTextureTarget, y.GetTextureID());
//	glEnableClientState( GL_TEXTURE_COORD_ARRAY );
//	glTexCoordPointer(2, GL_INT, 0, TextureArray);
	glBegin( GL_QUADS );
		//glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);	
		//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);	
		glVertex2i( 0, 0);

		//glMultiTexCoord2fARB(GL_TEXTURE0_ARB, fTexCoord[0], 0);
		//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, fTexCoord[0], 0);	
		glVertex2i( 1, 0);

		//glMultiTexCoord2fARB(GL_TEXTURE0_ARB, fTexCoord[0], fTexCoord[1]);
		//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, fTexCoord[0], fTexCoord[1]);	
		glVertex2i( 1, 1);

		//glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, fTexCoord[1]);
		//glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, fTexCoord[1]);	
		glVertex2i( 0, 1);
	glEnd();

    // Now we need to copy the resulting pixels into the output
	// save the result texture into result
    glBindTexture(_iTextureTarget, result.GetTextureID());
    glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, Width, Height);

//	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, IndexArray);

	glActiveTextureARB( GL_TEXTURE0_ARB );
	glDisable(GL_FRAGMENT_PROGRAM_NV);

	return;
}

////////////////////////////////////////////////////////////////////////////////
/// Use Fragment Program to determine the max or min or abs of Vector x 
/// in Fragment Program Mode
/// Reduce a vector into a scalar number
////////////////////////////////////////////////////////////////////////////////
float clVecReduceFP(OperationOnGPUEnum cmb, const CVectorOnGPU& x)
{
	int i;	
	unsigned int ShaderID;
	unsigned int _iTextureTarget = x.GetTextureTarget();
	if(_iTextureTarget == GL_TEXTURE_2D)
	{
		AfxMessageBox("Not support GL_TEXTURE_2D in current system(clVecReduceFP) for the reason of float precision!");
		return 0;
	}

	int Width  = x.GetWidth();
	int Height = x.GetHeight();

	/// Here verify whether this vector is or not suitable to do reduction
	if((Width != Height) || !IsPowerOfTwo(Width))
	{
		AfxMessageBox("The vector is not suitable to do reduction!\nHere need to be square and size to be pow of 2!");
		return 0;
	}

	int RenderPass = PowOf2(Width);

	unsigned char strTexOffset[] = "TexOffset";
	int len = strlen((const char*)strTexOffset);
	float TexelOffset[4]={0,0,0,0};
	TexelOffset[0] = Width;

	ShaderID = GlobeShaderID[cmb].ShaderID;

	/// Here introduce Vector result to avoid destroying the content of x
	CVectorOnGPU result;
	bool isready = false;
	if(isready == false)
	{
		result.SetData(NULL, x.GetVectorLength());
		//result.CopyData(x);
		isready = true;
	}

	//////////////////////////////////////////////
	///// Clear the framebuffer firstly to avoid the previous computation
	///// This step is important to avoid computation errors
	//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	//glDisable(GL_DEPTH_TEST);
	glEnable(GL_FRAGMENT_PROGRAM_NV);

	/// Bind the predefined fragment program object 
	glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, ShaderID);

	///// The input textures as texture0 
	///// x----TEX0
	glActiveTextureARB( GL_TEXTURE0_ARB );
	glBindTexture(_iTextureTarget, x.GetTextureID());
	float SqureSize = 1.0;
	for(i=0; i<RenderPass; i++)
	{
		SqureSize = SqureSize*0.5;

		/// Set Texture Coordiantes acoording to Texture Target
		TexelOffset[0] = TexelOffset[0]*0.5;
		glProgramNamedParameter4fvNV(ShaderID, len, strTexOffset, TexelOffset);

		glBegin( GL_QUADS );			
			glVertex2f( 0, 0);
			glVertex2f( SqureSize, 0);
			glVertex2f( SqureSize, SqureSize);
			glVertex2f( 0, SqureSize);
		glEnd();

		///////////////////////////////////////////////////////
		//// Here, result texture is the mid-term result.
		//// According to the fragment program read in, we
		//// must bind it to TEX0
		glActiveTextureARB( GL_TEXTURE0_ARB );
		glBindTexture(_iTextureTarget, result.GetTextureID());
		////// Use this function to initialize the texture into zero
		////// Otherwise, the previous data will still be there which cause errors
		//glTexImage2D( _iTextureTarget, 0, GL_FLOAT_R32_NV, SqureSize, SqureSize, 0, GL_RED, GL_FLOAT, NULL);
		//glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, TexelOffset[0], TexelOffset[0]);
		glCopyTexImage2D(_iTextureTarget, 0, GL_FLOAT_R32_NV, 0, 0, TexelOffset[0], TexelOffset[0], 0);
	}

	glDisable(GL_FRAGMENT_PROGRAM_NV);

	float final;
	glGetTexImage(_iTextureTarget, 0, GL_RED, GL_FLOAT, &final);

	return final;
}

////////////////////////////////////////////////////////////////////////////////
/// Using the exiting method to compute the inner product of two vectors 
/// return inner-product of x@y 
/// in Fragment Program Mode
////////////////////////////////////////////////////////////////////////////////
float clInnerProductFP(const CVectorOnGPU& x, const CVectorOnGPU& y)
{
	float sum;
	CVectorOnGPU result;
	result.SetData(NULL, x.GetVectorLength());
	
	/// result = x*y
	clVecOpFP(CL_VECT_MULT_VECT_RECT, 1.0, 1.0, x, y, result);
	/// then reduce into a scalar number
	sum = clVecReduceFP(CL_VECT_NORMAL_RECT, result);
	return sum;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -