Applying per pixel transparency via PNG with SDL 2.0 |
razerwolf
|
I think your code is setting the amask to 0 on little endian systems. But anyway, I think you have to do something like this:
But anyway, this seems like a lot of work, why aren't you just loading the image into a texture with IMG_LoadTexture() and then using the src rect parameter to specify a portion of the image to draw? Also doesn't this belong in Game Development, and not SDL Development? |
|||||||||||||
|
ronkrepps
|
I had went back and forth between
"amask = 0xff000000" and "amask = 0x00000000" Because when having it set to 0xff000000 the screen was completely black. And at least with it set to 0xff000000 it was drawing everything, but the sprite was not blending. But I think I have realized that was because blend was on when I was making the background image so it was blending everything? I don't understand why this happens. Does the blending destination always have to be set to SDL_BLENDMODE_NONE? Also, this code is loading in animation textures to a vector. To animate the sprites I am moving though the vector according to the current frame. I suppose I could do it by loading one large texture but then I have to do the calculations when rendering. I think it is easier to do them when creating the textures. It would be the same amount of work, right? And I posted this here because I posed it as a general SDL blending question. I didn't think the purpose behind the code mattered. Thank you and I don't see too much difference in your code was your suggestion just to change the blend mode of the surfaces? |
|||||||||||
|
ronkrepps
|
"And at least with it set to 0xff000000 it was drawing everything, but the sprite was not blending."
Was supposed to be: "And at least with it set to 0x00000000 it was drawing everything, but the sprite was not blending." Can't edit post... |
|||||||||||
|
razerwolf
|
I tried using several of the different blend modes for the destination and source surface, but setting SDL_BLENDMODE_NONE on the source surface, and SDL_BLENDMODE_BLEND on the destination surface was the only thing that worked
Also you wouldn't have to do the frame calculations in the render loop, you could just store the SDL_Rect you generate into the vector instead of a SDL_Texture, couldn't you? |
|||||||||||
|
ronkrepps
|
I'm also doing the same; making the destination NONE and the source BLEND was the best I have come up with. I think I remember reading somewhere if they are both blend it causes the black image. I'm still trying to figure this all out as I have not seen too many resources for texture blending. Yeah I guess the difference is storing 1 large texture and several rect objects for each frame, or just several smaller individual textures and copying the whole texture rather than a piece of one; you think that would be better? |
|||||||||||||
|
razerwolf
|
Most GPUs can store textures with dimensions around 512x512, 1024x1024, or 2048x2048 pixels (but 2048 is probably getting up in the higher end video cards), so you can store pretty large textures, and I think that is better on the memory anyway.
Also it sounds like you are storing all your game animations in the same file? I could be wrong about that, but if that is the case it would probably make better sense to split them up into their own file, and upload them as their own textures |
|||||||||||
|
ronkrepps
|
After many, many hours trying to get this to work and digging through a lot of resources I finally found an answer.
It turns out the problem (or maybe it isn't a problem, but rather SDL_BlitSurface is not designed to do transparency) is that BlitSurface just doesn't preserve transparency correctly. This is why the SDL2_gfx library implements some special Blit functions to get it to work. The library is not fully updated to work with 2.0 but luckily it was easy to get it to work after some slight modifications. Check here for the library and source: http://www.ferzkopp.net/joomla/software-mainmenu-14/4-ferzkopps-linux-software/19-sdlgfx I'm just curious why this problem (or non-design) isn't documented or explained in detail nearly anywhere (including the actual SDL_BlitSurface function.) I'd suggest adding in a note somewhere about the GFX library you could save people hours of time in the future. I just hope anyone having this issue finds this answer in a shorter amount of time than I did in the future. |
|||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
Sik
|
If SDL_Rect is badly defined then int is badly defined as well. It's
the functions that should decide how to use them :/ 2013/8/26, john skaller:
SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
Mason Wheeler
Guest
|
I don't agree that a SDL_Rect with negative height and width should be equivalent to an empty rect. An empty rect should have a size of 0, not a negative size. Seems to me that negative dimensions should perform exactly the same blit as positive dimensions, but with the result flipped around the axis/axes of the negative value(s). That makes a lot more sense mathematically...
From: john skaller To: SDL Development List Sent: Monday, August 26, 2013 11:12 AM Subject: Re: [SDL] Applying per pixel transparency via PNG with SDL 2.0 On 27/08/2013, at 3:07 AM, Sam Lantinga wrote:
I beg to differ. As I have pointed out before, the semantics of SDL_Rect are not properly defined. Until this is done the semantics of SDL_BlitSurface and related functions .. are .. well .. "non-normative gibberish". And there is a bug, also pointed out before, when intersecting two SDL_Rects namely the target surface and clipping rectangle, when using the software renderer. In this case, the resulting rectangle is NOT checked for emptiness, and the intersection WILL set negative width and height values if the clipping rectangle and target do not intersect. This causes the renderer to write pixels into undefined memory (instead of the for loop skipping its body). Please decide what the semantics for SDL_Rect are. Either negative widths and heights are allowed, and specify an empty rectangle with a definite location, an empty rectangle with no location, a non-empty rectangle, or whatever. Note the SDL_BlitSurface is badly defined with the wrong API (the second rectangle should be an SDL_Point). Really this should be fixed. The repair will NOT break C ABI because both SDL_Point and SDL_Rect start with x and y coordinates specified as ints. (It WILL break source code and it technically breaks ISO C99 and above strict aliasing rules). This wart MATTERS because an empty SDL_Rect still has x and y coordinates. This is of course nonsense if you perform an intersection, unless you want to extend the semantics of the usual intersection. -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
john skaller
Guest
|
On 27/08/2013, at 4:28 AM, Sik the hedgehog wrote:
Please read before making silly comments like that. I wrote:
Please read that carefully. The *semantics* of SDL_Rect are not properly defined. What this means is that there is no way to make the functions that use an SDL_Rect act consistently. Really you shouldn't be commenting here is you do not understand basic notions of abstraction and representation invariants. Of course C does not help, since it provides little support for these notions, but they must exist in the programmers mind even if the language fails to provide that support. Due to the inconsistent use of SDL_Rect in SDL I cannot figure out what the intended semantics actually are. Therefore I do not know how to fix the bug that exists in the software renderer. -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
Sam Lantinga
|
This is likely a bug. The expected behavior of the blit is documented here:http://wiki.libsdl.org/SDL_BlitSurface
If you find something that isn't behaving the way you expect, please submit a bug with a small test case to bugzilla: http://bugzilla.libsdl.org/ Thanks! On Mon, Aug 26, 2013 at 4:39 AM, ronkrepps wrote:
|
|||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
Sik
|
No, *you* don't get what I mean. SDL_Rect is just a rectangle,
*without any semantics on its own*. It's up to the functions to define its semantics. That's why the issue is with the functions, not with SDL_Rect. 2013/8/26, john skaller:
SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
john skaller
Guest
|
On 27/08/2013, at 3:07 AM, Sam Lantinga wrote:
I beg to differ. As I have pointed out before, the semantics of SDL_Rect are not properly defined. Until this is done the semantics of SDL_BlitSurface and related functions .. are .. well .. "non-normative gibberish". And there is a bug, also pointed out before, when intersecting two SDL_Rects namely the target surface and clipping rectangle, when using the software renderer. In this case, the resulting rectangle is NOT checked for emptiness, and the intersection WILL set negative width and height values if the clipping rectangle and target do not intersect. This causes the renderer to write pixels into undefined memory (instead of the for loop skipping its body). Please decide what the semantics for SDL_Rect are. Either negative widths and heights are allowed, and specify an empty rectangle with a definite location, an empty rectangle with no location, a non-empty rectangle, or whatever. Note the SDL_BlitSurface is badly defined with the wrong API (the second rectangle should be an SDL_Point). Really this should be fixed. The repair will NOT break C ABI because both SDL_Point and SDL_Rect start with x and y coordinates specified as ints. (It WILL break source code and it technically breaks ISO C99 and above strict aliasing rules). This wart MATTERS because an empty SDL_Rect still has x and y coordinates. This is of course nonsense if you perform an intersection, unless you want to extend the semantics of the usual intersection. -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||
|
Re: Applying per pixel transparency via PNG with SDL 2.0 |
ronkrepps
|
Hmm, so you think this is a bug? I would have expected a function so widely used, would have a bug like this reported already. After all I thought that is why the gfx library was made. I don't mind submitting a bug report if you think that's what it is. I just don't understand the library and blitting well enough yet to know if it was. |
|||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
john skaller
Guest
|
On 27/08/2013, at 4:55 AM, Mason Wheeler wrote:
I personally agree with that, however SDL has specific tests for empty rects that consider a rect empty if the height or width is negative. One can make the view that the semantics should be: { (x',y') | x <= x' < x + w && y <= y' < y + h } in which case negative or zero w and h implies an empty rectangle. Unfortunately in the software renderer this check is not done. It's probably just an oversight. A for loop like for (x' = x; x' < x + h; ++x) handles this kind of interpretation properly, but there's some kind of messing about with clipping in the code and the calculation seems wrong (its a bit hard to follow because the error spans two functions). However I find it disturbing that the intersection function puts junk at the output pointer if there is no intersection. It basically means you cannot use an SDL_Rect without always doing an SDL_IsEmpty call first. -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
john skaller
Guest
|
On 27/08/2013, at 5:32 AM, Sik the hedgehog wrote:
You mis-stated that. You meant to say "it is just a data structure" without any interpretation. And, I want to apologise, I was annoyed by your comment and was rude in my response. Sorry!
Of course the issue is with the functions. But the abstract semantics of a rectangle need to be stated SO that the concrete functions implementing them do the right thing, and one can tell what's wrong. And the fact is SDL_Rect is a struct, as a value that means it has 4 implicitly defined projection functions, and that is probably wrong: a rectangle is not isomorphhic to a 4-tuple. That's a basic problem but there's not much you can do about enforcing correct use in C. I suppose I should explain in full ;( 1. Let A be an abstraction, and R be any set, then a function repr: R -> A is called a *representation* of A. 2. Consider the collection of sets A of form: r = { (x',y') | x <= x' < x + w && y <= y' < y + h } for any integers x,y,w,h. We call such a collection of points a rectangle. Note I included an empty rectangle! 3. Consider the collection R: r = { (x,y,w,h) } where x,y,w,h are any integers. This is called a 4-tuple. 4. Now, the semantics of a representation R -> A are just a mapping but we have to specify it. 5. Now we need a new concept: a *structure preserving map*. Suppose we have some functions on A, for example: intersect: A * A -> A = A \intersect A is an easy one, because the function is just the setwise intersection. Then given a function: INTERSECT: R * R -> R the representation function repr is said to preserve structure if, and only if intersect (repr a, repr b) = repr ( INTERSECT (a,b) ) A set A together with some such collection of functions like intersect is called a structure in maths. The set R together with functions like INTERSECT is also a structure. So now the notion or representation is extended: a representation is a structure preserving map from the model structure to the abstract structure. Mathematicians also call this a functor, and the collections of sets and functions are called categories. Programmers sometimes call the representation an encoding. Now, I HOPE you will agree that the intersection of two rectangles in the abstract is what I specified above. What we WANT then is two things: (a) a model of a set of values R (b) a representation function from R to A and of course that representation must preserve structure. This means the repr is NOT just mapping points from R to A, it is also mapping functions as well: repr: INTERSECT -> intersect Now, the point is you are NOT free to just do anything you want. "repr" has rules to obey! It has to be a function, and it has to be structure preserving. IF we choose repr: SDL_Rect -> Rectangles given by x,y,w,h | --> { (x',y') | x <= x' < x + w && y <= y' < y + h } we have a model of rectangles. Some values map to the same rectangle, in fact the set: (x,y,w,h | w <= 0 or h <=0 } is the kernel of the representation (all the values map to the empty set), and all other values of the representation map to a unique rectangle. All non-empty rectangles also have a unique representation. It is my guess these are the intended semantics. Clearly the SDL_Blit function taking an SDL_Rect instead of a point is an error. This is not something you can argue about! Its a FACT provable from the representation. There is no unique left corner for an empty rectangle (in the abstract) and there are many left corners for empty rectangles modelled by an arbitrary SDL_Rect. So the results are indeterminate. And as I mentioned I believe there's a bug in the software renderer here, where the code forgets to check for the null case, and uses the h and w values as counters in a loop in such a way that the loop counts off to the maximimum integer then wraps around and only terminates -h and -w short of the start value. There are other possible semantics. One is to allow negative h and w. Another is to BAN non-positive h and w except in one case (0,0,0,0). This is not so good in C because the invariant cannot be enforced by the type system (an invariant is nothing more than a subset!) It really doesn't matter WHAT the representation is. But it HAS to be specified because it is NOT obvious. If a function "repr" is chosen mapping: repr:SDL_Rect* -> Rectangles [Where SDL_Rect* is some subset of SDL_Rect called the representation invariant] THEN we can check if it is structure preserving, in other words, we can check if the C functions are correctly implemented, given an abstract definition of the functions. So this is what I meant by "the semantics of SDL_Rect". Yes, its specified by functions, in particular the repr function. But that's a mathematical function NOT a C function. The C functions like SDL_Intersect are NOT models or specifications, rather, given SDL_Intersect is intended to represent the abstract intersection, there is a checkable requirement on the implementation that it act to preserve structure. The semantics I have used above is called Denotational Semantics which is gobbledgook for "modelling types as sets of values". The model here is concrete: I'm assuming a C struct is a tuple of values and thus represents a set in an obvious way. We can get more technical and model WITHOUT any sets at all, but that's category theory and is a bit beyond this mini-lecture -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
Jared Maddox
Guest
|
Sik, I believe that this is the wrong wording for what you're trying to convey. I think the correct wording is as follows: SDL_Rect is just and only a rectangle, with it's sides all parallel with either the X or Y axis, and represented by a vector. Functions that seem to use SDL_Rect are actually trying to use a derived type that only supports a subset of the semantics of SDL_Rect, but which have not been specified in the form of C types due to a lack of perceived need.
I don't even know why you're arguing about this. You should know by now that there are to be no removals from the API or ABI for the foreseeable future. At most you can branch the library, in which case your version isn't likely to get much use, nor development. As it is, it's likely this originated from SDL_BlitScaled, either by SDL_BlitSurface being separated out at one point as a faster blit, or by both of them being intentionally given identical function signatures. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||||
|
Applying per pixel transparency via PNG with SDL 2.0 |
john skaller
Guest
|
On 27/08/2013, at 11:03 AM, Jared Maddox wrote:
I wish to illustrate how given specifications one can PROVE things about code. That things are not merely matters of opinion. Theoreticians speak of "reasoning" about code.
I expect the fault will not be corrected. In this case it probably isn't serious.
Yes, that's what I expect. The problem is that there IS no upper left corner of an arbitrary SDL_Rect. However the docs are clear that only the x and y values are used, so it is up to the programmer to ensure they're correctly set. The real problem is the bug I think exists in the software renderer where if the target and clipping rect do not intersect one gets an (almost) infinite loop and overwrite of all memory. I may be wrong, its really hard to tell reading the code since so much is left unspecified and the code is so tediously low level. In other words I'm finding it really hard to reason about the code. -- john skaller http://felix-lang.org _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
|||||||||||||||||||||
|