[Solved]glCopyTexImage alternative?

Started by
1 comment, last by thecoast47 12 years, 1 month ago
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: [media]
[/media]
Advertisement
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.
Thanks for the advice.
It now runs waaaay faster than before.

This topic is closed to new replies.

Advertisement