Updating a texture partially with another texture

Hi, all.

when i was trying to update a small area of a texture with a second texture/image, i was embarassed that it is currently not possible. The modifyTexture method in the renderer-class only allows a texture to be updated completly by an image, where you are not able to select a region in that area. After reading a lot of documentation i decided to implement it.

Here is my contribution:

Renderer:

public void modifyTexture(Texture tex, Image pixels, int tileX, int tileY, int w, int h);

GLRenderer:

public void modifyTexture(Texture tex, Image pixels, int tileX, int tileY, int w, int h) {
    setTexture(0, tex);
    int target = convertTextureType(tex.getType(), pixels.getMultiSamples(), -1);
    texUtil.uploadSubTexture(pixels, target, 0, tileX, tileY, w, h, linearizeSrgbImages);
}

TextureUtil:

public void uploadSubTexture(Image image, int target, int index, int tileX, int tileY, int w, int h, boolean linearizeSrgb) {
    /*
        similiar to  public void uploadSubTexture(image, target, index, x, y, linearizeSrgb) 
        if (data == null) {
            throw new IndexOutOfBoundsException("The image index " + index + " is not valid for the given image");
        }
        ... here comes the new stuff
     */
    data.limit(data.capacity());

    int width = image.getWidth();
    int pixelSize = image.getFormat().getBitsPerPixel() / 8;
    for (int i = 0; i < h; i++) {
        int y = tileY * h + i;
        data.position((tileX + y * width) * pixelSize);
        gl.glTexSubImage2D(target, 0, tileX, y, w, 1, oglFormat.format, oglFormat.dataType, data);
    }
}

This was basically implemented in a different context and i just transformed it with no compiling. Feel free to give some feedback and maybe have that integrated into the engine.

Best regards.

4 Likes

Very neat. Got some pictures of it working?

1 Like

Sure

2 Likes

It should be done on shader level with custom material and additional parameters. I can’t imagine to make any serious effect this way. What if there are two geometries with the same texture?

Do you want to make something like this? (May 2017) Monthly WIP screenshot thread - #57 by FrozenShade

On shader level you can combine/replace/blend a lot of textures in any way you want, with any parameters or masks. And it is MUCH faster than doing it on CPU.

3 Likes

My usecase is updating a texture for stars. The texture has a size of 4096x4096 and i’m using a custom shader to render the texture. By updating it in one step or render it completely the render time will exceed. So i made a renderer, which only updates parts of a textures and updates this texture over 600 frames tile by tile (While the stars are not visible - during day). While i was reading the whole routines to do this i thought, that maybe someone who has the same problem can use this help.

1 Like

By rendering the sky do you mean rendering all the stars on one texture? And if there is a lot of them you have low fps and it slows down all other things, am I right?

If so you can still render it without any CPU copy operations, all you need is to render
few stars every frame and to not clear your framebuffer until you render all of them.

2 Likes

Got you. Maybe i have to poste some more details :).

here is a snippet of my routine:

                uiGeometry.setWidth(cam.getWidth());
                uiGeometry.setHeight(cam.getHeight());
                uiGeometry.setMaterial(material);
                renderer.setFrameBuffer(fb);
                renderManager.setCamera(cam, false);
                renderManager.renderGeometry(uiGeometry);
                renderer.readFrameBuffer(fb, newData.getData(0));
                renderer.modifyTexture(target, newData, positionX, positionY);

i wasn’t able to set the destination and to limit it to a region in the target texture so i decided to use the following:

                renderer.readFrameBuffer(fb, newData.getData(0));
                renderer.modifyTexture(target, newData, positionX, positionY);
2 Likes

Okay i rechecked my code and probably you are right, i could get rid of the bytebuffer, which eliminates the cpu work.

3 Likes