Sign in to follow this  
thecoast47

[Solved]glCopyTexImage alternative?

Recommended Posts

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:
[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();
}[/code]

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: [media]http://www.youtube.com/watch?v=6Nc1boqxyZA&feature=youtu.be[/media]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this