📄 vectorvectoroperation.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
//// 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 + -