Jump to content



[Solved]glCopyTexImage alternative?

  • You cannot reply to this topic
2 replies to this topic

#1 thecoast47   Members   -  Reputation: 102

Like
0Likes
Like

Posted 25 February 2012 - 05:23 PM

Hello gamedev.net!
I'm making a 2D soft shadow engine and i am currently experiencing a speed problem with glCopyTexImage.

Here is a quick summary of what happens during rendering:
step 1: I fill the stencil buffer with shadow regions for each convexhull.
step 2: I render a radial gradient while the stencil buffer is enabled so that It stencils away areas of the radial gradient that were previously covering the shadow region
step 3: for each light, I render shadow fins, that are within the radius of each light. I use the stencil buffer to make sure that the shadows are within the lights radius.
step 4: I needed a way to save each lighting pass so i decided that i would copy the framebuffer as a texture using glCopyTexImage and then I clear the framebuffer each Iteration/Pass.
step 5: I iterate through all lighting passes,and render a fullscreen quad with additive blending enabled.Yielding Soft-looking edges for shadows.

Here is the rendering routine as code:
unsigned int K= 0;
extern Wrapper BindedClasses;
bool loaded = false;
GLuint ID[50];
int RecsFilled = 0;
void Frame::OnRender(){
	//void RenderParticles(std::vector<Particle> & ParticleList);
	//void RenderParticles(std::vector<Particle> & ParticleList,float R,float G,float B);
	void RenderConvexHulls(std::vector<Convex_Hull*> & ActiveBodies);
	//void RenderPositionList(std::vector<Particle> & TempVertexList);
	void RenderShadows(std::vector<Convex_Hull*> & ActiveBodies,Light & CL);
	void OpenStencil();
	void CloseStencil();
	void ClearStencil();
	void ClearAlphaChannel(float TranslateX,float TranslateY);
	void RenderFins(std::vector<Convex_Hull*> & ActiveBodies, Light & CL);
	void CloseStencilUnlocked();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glLoadIdentity();
	glScalef(Scale.X,Scale.Y,1.0f);
	glTranslatef(Translate.X,Translate.Y,0.0f);

	glEnable(GL_BLEND);
	ClearAlphaChannel(0,0);
	for(unsigned int K = 0; K < LightList.size();K++){
		Light & CL = LightList[K];
		OpenStencil();
		RenderShadows(ActiveBodies,CL);
		CloseStencil();
		glBlendFunc(GL_ONE, GL_ONE);
		CL.RenderLight();
		ClearStencil();
		OpenStencil();
			TextureProcedures::FillRect(0,0,10000,10000,1,1,1,1);
			CL.RenderLight();
		CloseStencilUnlocked();
		glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		RenderFins(ActiveBodies,CL);
		ClearStencil();
	  
		//Save shadow pass as a texture
		glEnable(GL_TEXTURE_2D);
			glGenTextures(1,&ID[RecsFilled]);
			glBindTexture(GL_TEXTURE_2D,ID[RecsFilled]);
			glCopyTexImage2DEXT(GL_TEXTURE_2D,0,GL_RGBA,0,0,1920,1080,0);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			RecsFilled++;
		glDisable(GL_TEXTURE_2D);
		//clear Framebuffer
		glClear(GL_COLOR_BUFFER_BIT);
	}
	ClearStencil();
	//Additively blends all shadow passes
	glClear(GL_COLOR_BUFFER_BIT);
	glBlendFunc(GL_ONE,GL_ONE);
	for(int K = 0; K < RecsFilled;K++){
		GLuint & CID = ID[K];
		TextureProcedures::RenderInvertedQuad(0,0,1920,1080,CID,false);
	}
	glDeleteTextures(RecsFilled,ID);
	RecsFilled = 0;

	RenderConvexHulls(ActiveBodies);

	glLoadIdentity();
	SDL_GL_SwapBuffers();
}
void RenderConvexHulls(std::vector<Convex_Hull*> & ActiveBodies){
	for(K = 0; K < ActiveBodies.size();K++){
		Convex_Hull * CH = ActiveBodies[K];
		CH->V_Render();
	}
}
void RenderPositionList(std::vector<Particle> & TempVertexList){
	glBegin(GL_LINE_LOOP);
		for(K = 0; K < TempVertexList.size();K++){
			Particle & CV = TempVertexList[K];
			glVertex2f(CV.Position.X,CV.Position.Y);
		}
	glEnd();
}
void RenderShadows(std::vector<Convex_Hull*> & ActiveBodies,Light & CL){
	for(unsigned int K = 0;K < ActiveBodies.size();K++){
		Convex_Hull * CH = ActiveBodies[K];
		CH->RenderShadows(CL);
	}
}
void OpenStencil(){
	glEnable(GL_STENCIL_TEST);
	glStencilFunc(GL_NEVER, 0x0, 0x0);
	glStencilOp(GL_INCR, GL_INCR, GL_INCR);
}
void CloseStencil(){
	glStencilFunc(GL_EQUAL, 0x00, 0xFF);
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
void CloseStencilUnlocked(){
	glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
void ClearStencil(){
	glClear(GL_STENCIL_BUFFER_BIT);
}
void ClearAlphaChannel(float TranslateX,float TranslateY){
	glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); //only write to alpha
		TextureProcedures::FillRect(TranslateX*-1,TranslateY*-1,100000,100000,0.0f,0.0f,0.0f,0.1f);
	glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //enable color writes
}

void RenderFins(std::vector<Convex_Hull*> & ActiveBodies, Light & CL){
	BindedClasses.TestShader->Begin();
	for(unsigned int K = 0; K < ActiveBodies.size();K++){
		ActiveBodies[K]->RenderShadowFin(CL);
	}
	BindedClasses.TestShader->End();
}

Basically in order for the shadow fins to render correctly i have to render each iteration separately and then use additive blending otherwise
the shadow fins will be rendered with dark edges rather than faded edges.


Am I using glCopyTexImage incorrectly or is it just slow?

Footage:

Ad:

#2 Brother Bob   Moderators   -  Reputation: 1767

Like
2Likes
Like

Posted 25 February 2012 - 05:47 PM

At the very least, you should use glCopyTexSubImage instead of allocating new textures and destroying them every time. Make an empty textrure (pass a null-pointer to glTexImage but with the desired dimensions and internal format), and then update it with the Sub-family of functions instead of allocating new textures and destroying them all the time.

There are also more modern render-to-texture alternatives if you want to go that route, but just Sub-imaging existing texture should at least be a good start.

#3 thecoast47   Members   -  Reputation: 102

Like
0Likes
Like

Posted 25 February 2012 - 06:58 PM

Thanks for the advice.
It now runs waaaay faster than before.






We are working on generating results for this topic
PARTNERS