I am trying to use a texture with the SDL_PIXELFORMAT_ARGB2101010 color format but I only get a black texture. The same program works when using the SDL_PIXELFORMAT_ARG88888 format.
None of SDL's variables are null. This is my code:
#include <SDL2/SDL.h>
int main(int argc, const char * argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, 0);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE);
SDL_Texture *tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB2101010, SDL_TEXTUREACCESS_STREAMING, bufferWidth, bufferHeight);
uint32_t* buffer = new uint32_t[bufferWidth * bufferHeight];
for(int bufferIdx = 0; bufferIdx < bufferWidth * bufferHeight; bufferIdx++) {
buffer[bufferIdx] = 0xc0ffffff;
}
SDL_Event event;
while(running) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
running = false;
}
SDL_UpdateTexture(tex, nullptr, buffer, bufferWidth * 4);
SDL_RenderCopy(ren, tex, nullptr, nullptr);
SDL_RenderPresent(ren);
}
}
This is some of my hardware and software:
AMD Radeon Pro 5500M GPU
SDL Version 2.0.14
MacOS 11.1
C++14
Compiled with default Xcode 12.3 settings
Related
I'm having some trouble understanding texture streaming and loading a 2D texture from an array of raw pixel data.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#define WINDOW_W 640
#define WINDOW_H 320
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_EVERYTHING))
exit(1);
/* Set up main window. */
SDL_Window *window = SDL_CreateWindow(
"Texture Streaming",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WINDOW_W,
WINDOW_H,
SDL_WINDOW_SHOWN
);
if (window == NULL)
exit(2);
/* Set up renderer. */
SDL_Renderer *renderer = SDL_CreateRenderer(
window,
-1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
if (renderer == NULL)
exit(3);
SDL_Event ev;
int window_running = 1;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, 64, 32);
Uint32 pixels[64 * 32];
for (int i = 0; i < (64 * 32); i++)
pixels[i] = 0xFF00FFFF;
for (int i = 0; i < 64; i++)
pixels[i] = 0xFF0000FF;
SDL_UpdateTexture(texture, NULL, pixels, 4);
while (window_running)
{
while (SDL_PollEvent(&ev) != 0)
{
if (ev.type == SDL_QUIT)
window_running = 0;
}
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Instead of my program drawing the first 64 pixels red and the rest magenta, it just spits out a random chunk of red and yellow pixels.
I'm having trouble understanding SDL_CreateTexture and SDL_UpdateTexture.
Your pitch in UpdateTexture is wrong. Pitch is byte length of a row, not single pixel. In your case pitch is 64*4.
Pixel format SDL_PIXELFORMAT_RGBA32 is alias to either SDL_PIXELFORMAT_RGBA8888 or SDL_PIXELFORMAT_ABGR8888 (latter in your case). Look at https://wiki.libsdl.org/SDL_PixelFormatEnum . So your 0xFF00FFFF is yellow (R=0xff, G=0xff, B=0, A=0xff).
Finally, if we're talking about texture streaming (i.e. updating every frame or otherwise very often), you should create streaming texture and use LockTexture/UnlockTexture. UpdateTexture is for static textures.
I need to build an interface where on the left side of the screen shows part of one streaming video and the right side the other part. Something like this https://www.youtube.com/watch?v=fSPXpdVzamo
The video streaming is saved on a memory buffer that is being loaded on a texture. My question is how to render just the half of the texture, I've bee trying using SDL_Rect but nothing happens.
This is the relevant part of my code:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
If I try something like this, it doesn't work:
SDL_UpdateTexture(texture, NULL, buffer_start, fmt.fmt.pix.width * 2);
SDL_Rect someRect;
someRect.x = 0;
someRect.y = 0;
someRect.w = 1500;
someRect.h = 3000;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &someRect);
SDL_RenderPresent(renderer);
Any advice would be great!
Without you posting a MCVE is hard to know where you went wrong. My guess is your x position is wrong. Here is an example where I show how to draw 2 images in the fashion of your video.
Green image: https://i.imgur.com/yaOG8Ng.png
Red image: https://i.imgur.com/faKKShU.png
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#define HEIGHT 600
#define WIDTH 800
using namespace std;
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Red Green", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool quit = false;
SDL_Event event;
SDL_Texture *green_part = IMG_LoadTexture(renderer, "Green400x600.png");
SDL_Texture *red_part = IMG_LoadTexture(renderer, "Red400x600.png");
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
SDL_RenderClear(renderer);
SDL_Rect copy_rect{0, 0, 400, 600};
SDL_RenderCopy(renderer, green_part, nullptr, ©_rect);
// We now draw from half the screen onward x position = WIDTH / 2.
copy_rect.x = 400;
SDL_RenderCopy(renderer, red_part, nullptr, ©_rect);
SDL_RenderPresent(renderer);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
Here is some code in SMFL
RenderWindow window(VideoMode(320, 480), "The Game!");
Texture t1,t2,t3;
t1.loadFromFile("images/tiles.png");
t2.loadFromFile("images/background.png");
t3.loadFromFile("images/frame.png");
Sprite s(t1), background(t2), frame(t3);
Does SDL 2.0 has functions like this and how to convert them to SDL 2.0
yes, all is there:
https://programmersranch.blogspot.kr/2014/03/sdl2-animations-with-sprite-sheets.html
#include <SDL.h>
#include <SDL_image.h>
int main(int argc, char ** argv)
{
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
SDL_Window * window = SDL_CreateWindow("SDL2 Sprite Sheets",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
480, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface * image = IMG_Load("spritesheet.png");
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
image);
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return 0;
}
I am using SDL2 in windowed mode on Windows 7 64bit to create a small game.
I get tearing at the same height of the window despite having VSYNC active. The weird thing is that the movement in itself is fluid, but there is this line, about 50px from the bottom, where tearing is noticeable. It always stays there, without moving or anything.
The weird thing is that if I crate a smaller window, I get tearing at exactly the same height from the bottom.
I tried taking screens of it but it doesn't show the tearing.
I have no idea if this is a problem of SDL2, a problem with Windows, a problem with my pc or a problem in my source file. I have tried looking online for a solution but I could not find anything like this problem.
It is a first for me since I have been playing with a lot of SDL games in the past in windowed mode and none had this problem.
Here is a snippet of the source I have been using:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
const int SCREEN_WIDTH = 400;
const int SCREEN_HEIGHT = 300;
bool init( SDL_Window** window, SDL_Renderer** renderer ) {
SDL_Init(SDL_INIT_VIDEO);
*window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
*renderer = SDL_CreateRenderer(*window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
int flags = IMG_INIT_PNG;
IMG_Init(flags);
return true;
}
void close( SDL_Texture** image, SDL_Window** window ) {
SDL_DestroyTexture( *image );
*image = NULL;
SDL_DestroyWindow( *window );
*window = NULL;
SDL_Quit();
}
int main(int argc, char* argv[]) {
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* image = NULL;
const SDL_Rect rect = { 0, 0, SCREEN_WIDTH, 200 };
SDL_Rect rectImage, rectImageOriginal;
int w, h;
SDL_QueryTexture(image, NULL, NULL, &w, &h);
rectImage = { 0, 0, w, h };
rectImageOriginal = rectImage;
init( window, renderer );
image = IMG_LoadTexture( renderer, path );
while (running) {
[... here I move rectImage ...]
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255);
SDL_RenderFillRect(renderer, NULL);
SDL_RenderCopy(renderer, image, &rectImageOriginal, &rectImage);
SDL_RenderPresent(renderer);
}
close(&image, &window);
}
Ive been trying to fix this particular SDL error for a while and strangely haven't found the same error mentioned once through searches.
Here is the Visual Studio error output:
Error 1 error LNK2019: unresolved external symbol _IMG_LoadTexture referenced in function "struct SDL_Texture * __cdecl LoadImage(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?LoadImage##YAPAUSDL_Texture##V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) C:\Users\DemonicSmokingJacket\Documents\Visual Studio 2012\Projects\ShitHappens\ShitHappens\main.obj ShitHappens
And here is the code:
#include <SDL.h>
#include <SDL_image.h>
#include <string>
const int screen_x = 640;
const int screen_y = 480;
SDL_Window *window = nullptr;
SDL_Renderer *renderer = nullptr;
using namespace std;
SDL_Texture *LoadImage(string file)
{
//Initialized variables for texture.
SDL_Texture *texture = nullptr;
//Load image.
texture = IMG_LoadTexture(renderer, file.c_str());
return texture;
}
void ApplySurface(int x, int y, SDL_Texture *texture, SDL_Renderer *second_renderer)
{
//Initialize variables and set x and y axis.
SDL_Rect pos;
pos.x = x;
pos.y = y;
SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h);
SDL_RenderCopy(second_renderer, texture, NULL, &pos);
}
int main(int argc, char* argv[])
{
//Initialize variables limited to function 'main'.
int bW, bH, iW, iH, x, y;
SDL_Texture *background = nullptr, *image = nullptr;
//Initialize all of SDL's features; an SDL window and make the window rendable.
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("Shit Happens", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_x, screen_y, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//Load background images from 'LoadImage' function.
background = LoadImage("background.png");
image = LoadImage("image.png");
//Clear Render 'renderer'.
SDL_RenderClear(renderer);
//Display and tile background image. "background.bmp"
SDL_QueryTexture(background, NULL, NULL, &bW, &bH);
ApplySurface(bW, bH, background, renderer);
ApplySurface(bW, 0, background, renderer);
ApplySurface(0, bH, background, renderer);
ApplySurface(0, 0, background, renderer);
//Display front image. "image.bmp"
SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
x = screen_x / 2 - iW / 2;
y = screen_y / 2 - iH / 2;
//Apply changes to renderer.
ApplySurface (x, y, image, renderer);
//Apply renderer to screen.
SDL_RenderPresent(renderer);
SDL_Delay(2000);
//Destroy the SDL Textures (images); the SDL Renderer and the SDL window.
SDL_DestroyTexture(background);
SDL_DestroyTexture(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
//Quit SDL.
SDL_Quit();
return 0;
}
Thank you very much for your time, hopefully this will help other users.
Sincerely,
(DamnitIForgotMyName)
Thanks to self., I have come to a conclusion. The problem was I hadnt downloaded the newest version of SDL_Image ,which does contain the function IMG_LoadTexture, from http://www.libsdl.org/projects/SDL_image/.
Thanks once again to self.