Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

What the title says.Is it possible to update a texture via a glsl shader ? Something like :

//Read
vec4 Pixel = texture2D(TextureID,gl_TexCoord[TextureIndex].st);

//Write to texture memory ?
vec4 NewPixel = Pixel + vec4(0.0,0.0,0.0,AlphaPatch);

// ?? How to write back to texture memory ??
texture2D(TextureID,gl_TexCoord[TextureIndex].st) = NewPixel; 

??

share|improve this question

2 Answers 2

up vote 3 down vote accepted

What you want is to bind a texture to a shader and then render to that texture. I could spit through miles of documentation specification of OpenGL, but I'm going to give the feeling my gut gives me:

I don't think that's possible.

What I do know is possible, however, is that you create a Frame Buffer Object (FBO) and render to that. First, you must generate an FBO and attach a texture to it with the same size as the one you want to update.

GLuint fbo_handle, fbo_texture_handle;

GLuint texture_width = GetTextureWidth();
GLuint texture_height = GetTextureWidth();

// generate texture

glGenTextures(1, &fbo_texture_handle);
glBindTexture(GL_TEXTURE_2D, fbo_texture_handle);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

// generate framebuffer

glGenFrameBuffers(1, &fbo_handle);
glBindFrameBuffer(GL_FRAMEBUFFER, fbo_handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture_handle, 0);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
    LOG_ERROR("Could not validate framebuffer);
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);

When you want to update your texture, you must take the followings steps.

First, you attach the FBO:

glBindFramebuffer(GL_FRAMEBUFFER, fbo_handle);

glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, texture_width, texture_height);

Now you can render a fullscreen quad with a shader that outputs the updated color:

vec4 frag_texture = texture2D(TextureID, gl_TexCoord[TextureIndex].st);

vec4 frag_updated = frag_texture + vec4(0.0, 0.0, 0.0, AlphaPatch);

gl_FragData[0] = frag_updated;

And then you have to copy the resulting framebuffer to the original texture.

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle);
glBindTexture(GL_TEXTURE_2D, original_texture_handle);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texture_width, texture_height);

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

glPopAttrib();

However, you should consider the following:

  • How often do you update this texture?
  • If you don't have to update it every frame, is this method worth the speed penalty?
  • Can you generate multiple version of this texture and cycle between them?
  • Is there another way to achieve the same effect?
share|improve this answer
    
Wow thank you very much for the help! And to answer your questions : 1.I have a special texture for my hero that i have to update every time collision occurs (with dots of blood and other things). 2.Due to the nature of the game you get hit or touch things full of dirt(mud) all the time so i have to update that texture very frequently... 3.That's how i do it right now and im not happy with it(i need dynamic texture patching) 4.Don't know :o –  user1010005 Jun 26 '12 at 13:58
4  
Aha! Well that helps in fine-tuning my answer. What you're probably looking for is multi-texturing. You have a texture for your game character and you have a texture that shows dirt and blood and whatnot. In a shader, you can combine them to create the effect you want. This is much cheaper than continually rendering to a frame buffer object and copying the result to a texture. –  knight666 Jun 26 '12 at 14:07
    
Thank you once again.I'm not quite sure what you mean with multi texturing but i will try to search on stackexchange :)) –  user1010005 Jun 27 '12 at 6:39

If your hardware supports it, the GL_ARB_shader_image_load_store extension allows you to write to a texture.

share|improve this answer
1  
I can tell you right now that my NVIDIA GeForce GTS 250 supports OpenGL 3.3.0, but not GL_EXT_shader_image_load_store. That means your answer is probably correct, but not practical in the field yet. Sucks. :( –  knight666 Jun 26 '12 at 13:24
1  
Yep, looks like you need a GeForce 400 series or greater for support (it's a GL4/DX11 feature). –  elFarto Jun 26 '12 at 14:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.