www.pudn.com > GPUVision_5-13-05-2.zip > GPUVision.cpp


// gpuvision.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
#include "gpuvision.h" 
#include  
 
using namespace std; 
using namespace corona; 
 
#define ONLY_RED 0 
 
 
GPUVision::GPUVision(const char *strFileName, bool mipmapped) { 
	_ChooseProfiles(); 
	_LoadCgPrograms(); 
 
	_mipmapped = mipmapped; 
	_bound = false; 
	Image* image = OpenImage(strFileName,PF_R8G8B8A8,FF_AUTODETECT); 
	if(!image) { 
		throw "Error, could not load image"; 
		return; 
	} 
	int numImgPixels = image->getWidth()*image->getHeight(); 
	_dataFloats = new float[numImgPixels*4]; 
	ConvertByte2Float((byte*)image->getPixels(),numImgPixels,4,4,_dataFloats,1); 
	_width = image->getWidth(); 
	_height = image->getHeight(); 
	_textureID = UploadToTexture(_dataFloats); 
	_Init(); 
//	_packedInto = 4; 
} 
 
GPUVision::GPUVision(float* data, int width, int height, bool mipmapped) { 
	_mipmapped = mipmapped; 
	_width = width; 
	_height = height; 
 
	_ChooseProfiles(); 
	_LoadCgPrograms(); 
 
	_bound = false; 
	_textureID = UploadToTexture(data); 
	_Init(); 
 
	// don't use the passed in data directly.  Just create a new one 
	_dataFloats = new float[_width*_height*4]; 
} 
 
GPUVision::GPUVision(unsigned int textureID, int width, int height) { 
	_textureID = textureID; 
	_width = width; 
	_height = height; 
	// Just create a new data array for download purposes 
	_dataFloats = new float[_width*_height*4]; 
	_mipmapped = false; //IJ 
 
	_Init(); 
 
	_ChooseProfiles(); 
	_LoadCgPrograms(); 
	_bound = false; 
} 
 
GPUVision::~GPUVision() { 
	// should we destroy the context and the texture? 
	cgDestroyContext(_CGcontext); 
	glDeleteTextures(1,&_textureID); 
	delete _rt; 
	delete _dataFloats; 
} 
 
void GPUVision::DisplayCurrent() { 
	_ExecutePassThrough(IsReset()?GetTextureID():GetRenderedTextureID(), true); 
} 
 
void GPUVision::PassThrough(unsigned int aTextureID, bool shouldFlip) { 
	_ExecutePassThrough(aTextureID, shouldFlip); 
} 
void GPUVision::PassThrough(unsigned int aTextureID) { 
	_ExecutePassThrough(aTextureID, true); 
} 
void GPUVision::PassThrough() { 
	bool isReset = IsReset(); 
	int id = IsReset()?GetTextureID():GetRenderedTextureID(); 
	int texid = GetTextureID(); 
	int rtexid = GetRenderedTextureID(); 
	_ExecutePassThrough(IsReset()?GetTextureID():GetRenderedTextureID(), false); 
} 
 
 
// load up the texture stored in _textureID into the frontRT 
void GPUVision::LoadBase() { 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
	_ExecutePassThrough(_textureID, false); 
} 
float* GPUVision::DownloadTexture() {//IJ 
	_dataFloats = (GLfloat*)malloc(_width*_height*4*sizeof(GLfloat)); 
 
	Begin(); 
	glReadPixels(0,0,_width,_height,GL_RGBA,GL_FLOAT,_dataFloats); 
	End(); 
	return _dataFloats; 
} 
 
 
// if we are drawing to the screen then we need to flip the y values 
// so that it is upright =) 
void GPUVision::_ExecutePassThrough(unsigned int aTextureID, bool flip) { 
	cgGLBindProgram(_passThroughTextureProgram); 
	cgGLSetTextureParameter(_passThroughTextureParam, aTextureID); 
	cgGLEnableTextureParameter(_passThroughTextureParam);	 
	cgGLEnableProfile(_fragmentProfile); 
 
	if(flip) 
		_DrawFullFlip(); 
	else  
		_DrawFull(); 
 
 
	cgGLDisableTextureParameter(_passThroughTextureParam); 
	cgGLDisableProfile(_fragmentProfile); 
} 
 
void GPUVision::Flip() { 
	_frontBufferIndex = !_frontBufferIndex; 
	glDrawBuffer(glsurf[_frontBufferIndex]); 
	glReadBuffer(glsurf[!_frontBufferIndex]); 
	_rt->BindBuffer(wglsurf[!_frontBufferIndex]); 
	_isReset = false; 
} 
 
void GPUVision::Begin() { 
	_bound = true; 
	_rt->BeginCapture(); 
	// make sure that everything is set to what we left it 
	// if this isn't done then you can't do multiple begin/ends 
	glDrawBuffer(glsurf[_frontBufferIndex]); 
	glReadBuffer(glsurf[!_frontBufferIndex]); 
	_rt->BindBuffer(wglsurf[!_frontBufferIndex]); 
} 
// a bit more efficient because if chaining then 
// do not need to call End 
void GPUVision::Begin(GPUVision *currentlyBound) { 
	currentlyBound->_bound = false; 
	_bound = true; 
	_rt->BeginCapture(currentlyBound->_rt); 
	// make sure that everything is set to what we left it 
	// if this isn't done then you can't do multiple begin/ends 
	glDrawBuffer(glsurf[_frontBufferIndex]); 
	glReadBuffer(glsurf[!_frontBufferIndex]); 
	_rt->BindBuffer(wglsurf[!_frontBufferIndex]); 
} 
void GPUVision::End() { 
	_bound = false; 
	_rt->EndCapture(); 
} 
 
void GPUVision::Clear() { 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
	Flip(); 
} 
void GPUVision::ConvertByte2Float(byte* data, int data_pixels, int data_offset, int output_offset, float* output, float fill) { 
	int i,j; 
	byte* td; 
	float* to; 
	// fill in the difference with the fill value 
	td = data; 
	to = output; 
	if(data_offset < output_offset) { 
		for(i = 0; i < data_pixels; i++,to+=output_offset) { 
			for(j = data_offset; j < output_offset; j++) { 
				to[j] = fill; 
			} 
		} 
	} 
	td = data; 
	to = output; 
	for(i = 0; i < data_pixels; i++, td+=data_offset, to += output_offset) { 
		for(j = 0; j < data_offset; j++) { 
			to[j] = ((float)td[j])/255.; 
		} 
	} 
	bool ok = true; 
} 
 
RenderTexture* GPUVision::CreateRenderTexture(const char *strMode) { 
	RenderTexture *output = new RenderTexture(); 
	output->Reset(strMode); 
	if (!output->Initialize((int)_width, (int)_height)) 
	{ 
		fprintf(stderr, "RenderTexture Initialization failed!\n"); 
	} 
 
	output->BeginCapture(); 
	{ 
		if (output->IsDoubleBuffered()) output->BindBuffer(WGL_BACK_LEFT_ARB); 
		output->Bind(); 
 
		glEnable(GL_DEPTH_TEST); 
		glViewport(0, 0, _width, _height);     
		glMatrixMode(GL_PROJECTION); 
		glLoadIdentity(); 
		glOrtho(0,_width,0,_height,0,-1); 
		glMatrixMode(GL_MODELVIEW); 
		glLoadIdentity(); 
		glClearColor(0, 0, 0, 0); 
	} 
	output->EndCapture(); 
 
	output->Bind(); 
	glTexParameteri(output->GetTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameteri(output->GetTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
 
	output->BindDepth(); 
	glTexParameteri(output->GetTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameteri(output->GetTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	return output; 
} 
void GPUVision::SetData(float* data) { 
	SetData(data,_width,_height,GL_RGBA,_textureID); 
} 
 
void GPUVision::SetData(float* data, int width, int height, unsigned int inputDataFormat, unsigned int textureID) { 
	int no_components; //IJ, let's suppose 4 channel or 1 channel 
	no_components=(inputDataFormat==GL_RGBA)?GL_FLOAT_RGBA32_NV:GL_FLOAT_R32_NV; 
 
	glDisable(GL_TEXTURE_2D); 
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
	glBindTexture(GL_TEXTURE_RECTANGLE_NV, textureID); 
//	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
//	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
//	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
 
	if(_mipmapped) { 
		gluBuild2DMipmaps(GL_TEXTURE_RECTANGLE_NV, no_components, width, height, inputDataFormat, GL_FLOAT, data); 
	} else {		 
		glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0, no_components, width, height, 0, inputDataFormat, GL_FLOAT, data); 
	} 
} 
 
unsigned int GPUVision::UploadToTexture(float *data) { 
	return UploadToTexture(data,_width,_height, GL_RGBA); 
} 
unsigned int GPUVision::UploadToTexture(float *data, int width, int height, unsigned int inputDataFormat) { 
	unsigned int textureID; 
	glGenTextures(1,&textureID); 
	SetData(data, width, height, inputDataFormat, textureID); 
	return textureID; 
} 
 
void GPUVision::_Init() { 
#if ONLY_RED  
	_rt = CreateRenderTexture("r=32f doublebuffer texRECT rtt"); 
#else 
	_rt = CreateRenderTexture("rgba=32f doublebuffer texRECT rtt"); 
#endif 
	_frontBufferIndex = 0; 
} 
 
void GPUVision::_DrawFull() { 
	glBegin(GL_QUADS);  
	glTexCoord2f(0,		  0);		glVertex2f(0,		0); 
	glTexCoord2f(_width,  0);		glVertex2f(_width,	0); 
	glTexCoord2f(_width,  _height); glVertex2f(_width,  _height); 
	glTexCoord2f(0,		  _height);	glVertex2f(0,		_height); 
	glEnd(); 
} 
 
void GPUVision::_DrawIntoCoords(int width, int height) { 
	glBegin(GL_QUADS);  
	glTexCoord2f(0,		  0);		glVertex2f(0,		0); 
	glTexCoord2f(_width,  0);		glVertex2f(width,	0); 
	glTexCoord2f(_width,  _height); glVertex2f(width,   height); 
	glTexCoord2f(0,		  _height);	glVertex2f(0,		height); 
	glEnd(); 
} 
 
// for display purposes we need to flip the image around for 
// some reason 
void GPUVision::_DrawFullFlip() { 
	glBegin(GL_QUADS);  
	glTexCoord2f(0,		  0);		glVertex2f(0,		_height); 
	glTexCoord2f(_width,  0);		glVertex2f(_width,	_height); 
	glTexCoord2f(_width,  _height); glVertex2f(_width,	0); 
	glTexCoord2f(0,		  _height); glVertex2f(0,		0); 
	glEnd(); 
} 
 
void GPUVision::_ChooseProfiles() 
{ 
	_CGcontext = cgCreateContext(); 
	// try ARBFP1 
	if (cgGLIsProfileSupported(CG_PROFILE_FP30)) 
		_fragmentProfile = CG_PROFILE_FP30; 
	else if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1)) 
		_fragmentProfile = CG_PROFILE_ARBFP1; 
	else { 
		fprintf(stderr, "Neither arbfp1 or fp30 fragment profiles supported on this system.\n"); 
		exit(1); 
	} 
} 
 
 
void GPUVision::_LoadCgPrograms() 
{ 
	assert(cgIsContext(_CGcontext)); 
 
	cgGLEnableProfile(_fragmentProfile); 
 
	char* strPassThrough =  
		"void main(float2	iCoords   : TEX0,\n" 
		"          uniform   samplerRECT	texture,\n" 
		"          out float3 oColor : COLOR) { \n" 
		"     oColor = f3texRECT(texture, iCoords);\n" 
		"}\n"; 
 
 
	_passThroughTextureProgram = cgCreateProgram(_CGcontext, CG_SOURCE, strPassThrough, 
											_fragmentProfile, NULL, NULL); 
 
	if (!cgIsProgramCompiled(_passThroughTextureProgram)) 
		cgCompileProgram(_passThroughTextureProgram); 
 
	cgGLLoadProgram(_passThroughTextureProgram); 
	_passThroughTextureParam = cgGetNamedParameter(_passThroughTextureProgram, "texture"); 
	cgGLDisableProfile(_fragmentProfile); 
} 
 
// copy the rendered  
void GPUVision::CopyRenderedToSource() { 
	bool unBind = !_bound; 
	if(unBind) Begin(); 
	CopyRenderedToTexture(_textureID); 
	if(unBind) End(); 
} 
void GPUVision::CopyRenderedToTexture(unsigned int textureID){ 
	glEnable(GL_TEXTURE_RECTANGLE_NV); 
	glBindTexture(GL_TEXTURE_RECTANGLE_NV, textureID); 
	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_NV,0, GL_FLOAT_RGBA32_NV, 0,0,_width, _height, 0); 
	glDisable(GL_TEXTURE_RECTANGLE_EXT); 
	glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0); // unbind it 
} 
 
// When making a copy it will simply 
GPUVision* GPUVision::Copy(){ 
//	return this; 
/*	unsigned int textureID; 
	glGenTextures(1,&textureID); 
	GPUVision *output = new GPUVision(textureID, _width,_height); 
	this->UploadToTexture(this->_dataFloats,_width,_height, GL_RGBA); 
	this->Reset(); 
	this->Begin(); 
	this->PassThrough(); 
	//this->Flip(); 
	CopyRenderedToTexture(output->_textureID); 
	this->End(); 
	this->Reset(); 
	return output; 
*/ 
	GPUVision *output = new GPUVision(_dataFloats, _width,_height); 
	return output; 
} 
int GPUVision::BackUpToTexture(){ // IJ 
	unsigned int textureID; 
	glGenTextures(1,&textureID); 
	bool unBind = !_bound; 
	if(unBind) Begin(); 
	CopyRenderedToTexture(textureID); 
	if(unBind) End(); 
	return textureID; 
} 
unsigned int GPUVision::generateTextureID(){ //IJ 
	unsigned int textureID; 
	glGenTextures(1,&textureID); 
	return textureID; 
} 
 
void GPUVision::deleteTextureID(const unsigned int textureID){ //IJ 
	glDeleteTextures(1,&textureID); 
}