Conversion from SDL_TEXTUREACCESS_TARGET to SDL_TEXTUREACCES

Before I will show you how I wanted to acheive this I would like to explain expected capabilities:

  1. Render to texture anything like Images
  2. Draw to texture anything like RectFill ect.
  3. Apply effects like Blur (requiring Pixel access to texture)

Above steps can “occure” in random count and order.

For 1 and 2 point I need to use SDL_TEXTUREACCESS_TARGET (simply redirecting output from NULL ( screen) to texture using SDL_SetRenderTarget

For 3 I need to use SDL_TEXTUREACCESS_STREAMING

Switching from STREAMING to TARGET is quite easy - simply rendering STREAMING texture to TARGET with SDL_SetRenderTarget, but I have no idea how to “reverse” this porcess.

Here is my idea however it does not work and I don’t know why?

  1. Function receives “Master” Texture (TARGET one)
  2. Inside function I’m creating 2 textures - tex1 (TARGET) and tex2 (STREAMING)
  3. Switching output from screen to tex1
  4. Rendering Master texture to tex1
  5. Read Pixels from tex1 using SDL_RenderReadPixels to pixels
  6. Performing operations on pixels
  7. Updating tex2 with pixels
  8. Switching output from tex1 to Master texture
  9. Rendering tex2 to Master texture

However It looks like function SDL_RenderReadPixels is not reading pixels from texture (when output is redirected to texture - thats why to be double sure that texture is not empty im creating separate tex1 and put context inside)

Code is below - question is same - how to switch texture from TARGET to STREAMING??[Question]

Code:
using namespace std;

#include
#include
#include <time.h>
#include <SDL.h>

void fillTexture(SDL_Renderer *renderer, SDL_Texture *texture, int r, int g, int b, int a)
{
SDL_SetRenderTarget(renderer, texture);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer, r, g, b, a);
SDL_RenderFillRect(renderer, NULL);
}

void fillTexture2(SDL_Renderer *renderer, SDL_Texture *texture, int r, int g, int b, int a)
{
SDL_Texture * newt=SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 50, 50);
SDL_Texture * newt2=SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 50, 50);
cout << “SDLERROR1” << SDL_GetError() << endl;

//render to newt2
SDL_SetRenderTarget(renderer, newt2);
cout << "SDLERROR2" << SDL_GetError() << endl;

//render input texture to newt2
SDL_RenderCopyEx(renderer, texture, NULL, NULL,0,NULL,SDL_FLIP_NONE);
cout << "SDLERROR3" << SDL_GetError() << endl;


SDL_Rect q={0,0,50,50};
int pitch   = 4;
int w=50;
int h=50;
int pixelCount = w*h;
void * pixels = new Uint8[w * h * pitch];

//current renderer is set newt2
if(SDL_RenderReadPixels (renderer,&q,SDL_PIXELFORMAT_RGBA8888,pixels,w*pitch)<0)
{
    int i;
    i=1;
}

//memset(pixels, 0, w * h * pitch);
Uint32* pixels32=(Uint32*) pixels;
cout << "SDLERROR4" << SDL_GetError() << endl;
//memset(pixels,0,w * h * pitch);
for(int i = 0; i < pixelCount/16; i++)
{
   cout <<(int)pixels32[i];// << "\n";
}

int m,x;
for (int i = 0; i < pixelCount; i++)
{
    x=i%2;
    if(x==0)
        {
            pixels32[i]=m;
        }
    //cout <<pixels32[i] << "\n";

}

if(SDL_UpdateTexture(newt,&q,pixels,w*pitch)<0)
{
    int i;
    i=1;

}
    cout << "SDLERROR5" << SDL_GetError() << endl;

        SDL_SetRenderTarget(renderer, texture);
    cout << "SDLERROR5" << SDL_GetError() << endl;

        //SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
        SDL_SetRenderDrawColor(renderer, r, g, b, a);
        SDL_SetTextureBlendMode(texture,SDL_BLENDMODE_BLEND);
        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
        SDL_RenderCopyEx(renderer, newt, NULL, NULL,0,NULL,SDL_FLIP_NONE);
        cout << "SDLERROR6" << SDL_GetError() << endl;
        SDL_SetRenderTarget(renderer, NULL);
        //SDL_RenderCopyEx(renderer, texture, NULL, NULL,0,NULL,SDL_FLIP_NONE);
        SDL_DestroyTexture(newt);
        SDL_DestroyTexture(newt2);
        newt=NULL;
        newt2=NULL;

            cout << "SDLERROR7" << SDL_GetError() << endl;

}

void prepareForRendering(SDL_Renderer *renderer)
{
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
}

void checkSdlError()
{
const char *sdlError = SDL_GetError();
if(sdlError && *sdlError)
{
::std::cout << "SDL ERROR3: " << sdlError << ::std::endl;
}
}

int main(int argc, char *argv[])
{
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_HAPTIC);

SDL_Window *window = SDL_CreateWindow("SDL test",
    SDL_WINDOWPOS_CENTERED,
    SDL_WINDOWPOS_CENTERED,
    320, 240,
    SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(
    window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

const int width = 50;
const int height = 50;

::std::vector<SDL_Texture*> textures;

SDL_Texture *redTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(redTexture);

SDL_Texture *greenTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(greenTexture);

SDL_Texture *purpleTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(purpleTexture);

// Here is setting the blend mode for each and every used texture:
for(int i = 0; i < textures.size(); ++i)
{
    SDL_SetTextureBlendMode(textures[i], SDL_BLENDMODE_BLEND);
}

int purpleAlpha = 0;

fillTexture(renderer, redTexture, 255, 0, 0, 255);
fillTexture(renderer, greenTexture, 0, 255, 0, 128);
fillTexture(renderer, purpleTexture, 255, 255, 255, 255);

prepareForRendering(renderer);

bool running = true;
while(running)
{
    SDL_Rect rect;
    rect.w = width;
    rect.h = height;

    SDL_RenderClear(renderer);

    rect.x = 50;
    rect.y = 50;
    SDL_RenderCopy(renderer, redTexture, NULL, &rect);

    rect.x = 75;
    rect.y = 70;
    SDL_RenderCopy(renderer, greenTexture, NULL, &rect);

    rect.x = 75;
    rect.y = 30;
    SDL_RenderCopy(renderer, purpleTexture, NULL, &rect);

    SDL_RenderPresent(renderer);

    // Process events
    {
        SDL_Event event;
        while(SDL_PollEvent(&event) == 1)
        {
            if(event.type == SDL_QUIT)
            {
                running = false;
            }
            else if(event.type == SDL_KEYDOWN)
            {
                switch(event.key.keysym.sym)
                {
                case SDLK_ESCAPE:
                    running = false;
                    break;
                case SDLK_a:
                    purpleAlpha = ::std::max(purpleAlpha - 32, 0);
                    fillTexture(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_s:
                    purpleAlpha = ::std::min(purpleAlpha + 32, 255);
                    fillTexture(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_q:
                    purpleAlpha = ::std::max(purpleAlpha - 32, 0);
                    fillTexture2(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_w:
                    purpleAlpha = ::std::min(purpleAlpha + 32, 255);
                    fillTexture2(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                }
            }
        }

        //checkSdlError();
    }
}

for(int i = 0; i < textures.size(); ++i)
{
    SDL_DestroyTexture(textures[i]);
}
textures.clear();

SDL_DestroyRenderer(renderer);
renderer = NULL;
SDL_DestroyWindow(window);
window = NULL;

SDL_Quit();

checkSdlError();

return 0;

}

[Question] [Question] [Question] [Question] [Question] [Question] [Question] [/code] [Question] [Question]

The function returns the pixels properly, its just that you are handling the data wrongly.

You cannot cast a Uint8 to Uint32 and expect it to be working. By doing that pixels32[0] will be pixels[0] + pixels[1] in binary. You have to handle it as a Uint8 throughout.

Also if you want to display it the proper way is to

char buffer[3];
sprintf ( buffer, “%d”, pixels[i] );
cout << buffer;

This is to force it to be a text and not print out the ASCII character of that value.

Lemonek wrote:> Before I will show you how I wanted to acheive this I would like to explain expected capabilities:

  1. Render to texture anything like Images
  2. Draw to texture anything like RectFill ect.
  3. Apply effects like Blur (requiring Pixel access to texture)

Above steps can “occure” in random count and order.

For 1 and 2 point I need to use SDL_TEXTUREACCESS_TARGET (simply redirecting output from NULL ( screen) to texture using SDL_SetRenderTarget

For 3 I need to use SDL_TEXTUREACCESS_STREAMING

Switching from STREAMING to TARGET is quite easy - simply rendering STREAMING texture to TARGET with SDL_SetRenderTarget, but I have no idea how to “reverse” this porcess.

Here is my idea however it does not work and I don’t know why?

  1. Function receives “Master” Texture (TARGET one)
  2. Inside function I’m creating 2 textures - tex1 (TARGET) and tex2 (STREAMING)
  3. Switching output from screen to tex1
  4. Rendering Master texture to tex1
  5. Read Pixels from tex1 using SDL_RenderReadPixels to pixels
  6. Performing operations on pixels
  7. Updating tex2 with pixels
  8. Switching output from tex1 to Master texture
  9. Rendering tex2 to Master texture

However It looks like function SDL_RenderReadPixels is not reading pixels from texture (when output is redirected to texture - thats why to be double sure that texture is not empty im creating separate tex1 and put context inside)

Code is below - question is same - how to switch texture from TARGET to STREAMING??[Question]

Code:
using namespace std;

#include
#include
#include <time.h>
#include <SDL.h>

void fillTexture(SDL_Renderer *renderer, SDL_Texture *texture, int r, int g, int b, int a)
{
SDL_SetRenderTarget(renderer, texture);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer, r, g, b, a);
SDL_RenderFillRect(renderer, NULL);
}

void fillTexture2(SDL_Renderer *renderer, SDL_Texture *texture, int r, int g, int b, int a)
{
SDL_Texture * newt=SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 50, 50);
SDL_Texture * newt2=SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 50, 50);
cout << “SDLERROR1” << SDL_GetError() << endl;

//render to newt2
SDL_SetRenderTarget(renderer, newt2);
cout << "SDLERROR2" << SDL_GetError() << endl;

//render input texture to newt2
SDL_RenderCopyEx(renderer, texture, NULL, NULL,0,NULL,SDL_FLIP_NONE);
cout << "SDLERROR3" << SDL_GetError() << endl;


SDL_Rect q={0,0,50,50};
int pitch   = 4;
int w=50;
int h=50;
int pixelCount = w*h;
void * pixels = new Uint8[w * h * pitch];

//current renderer is set newt2
if(SDL_RenderReadPixels (renderer,&q,SDL_PIXELFORMAT_RGBA8888,pixels,w*pitch)<0)
{
    int i;
    i=1;
}

//memset(pixels, 0, w * h * pitch);
Uint32* pixels32=(Uint32*) pixels;
cout << "SDLERROR4" << SDL_GetError() << endl;
//memset(pixels,0,w * h * pitch);
for(int i = 0; i < pixelCount/16; i++)
{
   cout <<(int)pixels32[i];// << "\n";
}

int m,x;
for (int i = 0; i < pixelCount; i++)
{
    x=i%2;
    if(x==0)
        {
            pixels32[i]=m;
        }
    //cout <<pixels32[i] << "\n";

}

if(SDL_UpdateTexture(newt,&q,pixels,w*pitch)<0)
{
    int i;
    i=1;

}
    cout << "SDLERROR5" << SDL_GetError() << endl;

        SDL_SetRenderTarget(renderer, texture);
    cout << "SDLERROR5" << SDL_GetError() << endl;

        //SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
        SDL_SetRenderDrawColor(renderer, r, g, b, a);
        SDL_SetTextureBlendMode(texture,SDL_BLENDMODE_BLEND);
        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
        SDL_RenderCopyEx(renderer, newt, NULL, NULL,0,NULL,SDL_FLIP_NONE);
        cout << "SDLERROR6" << SDL_GetError() << endl;
        SDL_SetRenderTarget(renderer, NULL);
        //SDL_RenderCopyEx(renderer, texture, NULL, NULL,0,NULL,SDL_FLIP_NONE);
        SDL_DestroyTexture(newt);
        SDL_DestroyTexture(newt2);
        newt=NULL;
        newt2=NULL;

            cout << "SDLERROR7" << SDL_GetError() << endl;

}

void prepareForRendering(SDL_Renderer *renderer)
{
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
}

void checkSdlError()
{
const char *sdlError = SDL_GetError();
if(sdlError && *sdlError)
{
::std::cout << "SDL ERROR3: " << sdlError << ::std::endl;
}
}

int main(int argc, char *argv[])
{
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_HAPTIC);

SDL_Window *window = SDL_CreateWindow("SDL test",
    SDL_WINDOWPOS_CENTERED,
    SDL_WINDOWPOS_CENTERED,
    320, 240,
    SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(
    window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

const int width = 50;
const int height = 50;

::std::vector<SDL_Texture*> textures;

SDL_Texture *redTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(redTexture);

SDL_Texture *greenTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(greenTexture);

SDL_Texture *purpleTexture = SDL_CreateTexture(renderer,
    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textures.push_back(purpleTexture);

// Here is setting the blend mode for each and every used texture:
for(int i = 0; i < textures.size(); ++i)
{
    SDL_SetTextureBlendMode(textures[i], SDL_BLENDMODE_BLEND);
}

int purpleAlpha = 0;

fillTexture(renderer, redTexture, 255, 0, 0, 255);
fillTexture(renderer, greenTexture, 0, 255, 0, 128);
fillTexture(renderer, purpleTexture, 255, 255, 255, 255);

prepareForRendering(renderer);

bool running = true;
while(running)
{
    SDL_Rect rect;
    rect.w = width;
    rect.h = height;

    SDL_RenderClear(renderer);

    rect.x = 50;
    rect.y = 50;
    SDL_RenderCopy(renderer, redTexture, NULL, &rect);

    rect.x = 75;
    rect.y = 70;
    SDL_RenderCopy(renderer, greenTexture, NULL, &rect);

    rect.x = 75;
    rect.y = 30;
    SDL_RenderCopy(renderer, purpleTexture, NULL, &rect);

    SDL_RenderPresent(renderer);

    // Process events
    {
        SDL_Event event;
        while(SDL_PollEvent(&event) == 1)
        {
            if(event.type == SDL_QUIT)
            {
                running = false;
            }
            else if(event.type == SDL_KEYDOWN)
            {
                switch(event.key.keysym.sym)
                {
                case SDLK_ESCAPE:
                    running = false;
                    break;
                case SDLK_a:
                    purpleAlpha = ::std::max(purpleAlpha - 32, 0);
                    fillTexture(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_s:
                    purpleAlpha = ::std::min(purpleAlpha + 32, 255);
                    fillTexture(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_q:
                    purpleAlpha = ::std::max(purpleAlpha - 32, 0);
                    fillTexture2(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                case SDLK_w:
                    purpleAlpha = ::std::min(purpleAlpha + 32, 255);
                    fillTexture2(renderer, purpleTexture, 255, 255, 255, purpleAlpha);
                    prepareForRendering(renderer);
                    ::std::cout << "Alpha: " << purpleAlpha << ::std::endl;
                    break;
                }
            }
        }

        //checkSdlError();
    }
}

for(int i = 0; i < textures.size(); ++i)
{
    SDL_DestroyTexture(textures[i]);
}
textures.clear();

SDL_DestroyRenderer(renderer);
renderer = NULL;
SDL_DestroyWindow(window);
window = NULL;

SDL_Quit();

checkSdlError();

return 0;

}

[Question] [Question] [Question] [Question] [Question] [Question] [Question] [/code] [Question] [Question]