Re: Indexed graphics for retro engine?
On Friday, 20 September 2019 at 00:41:58 UTC, Adam D. Ruppe wrote: On Thursday, 19 September 2019 at 03:47:05 UTC, Shadowblitz16 wrote: [...] My color.d actually can do it. [...] cool does this store image data as raw byte[]'s? I might have to use this :D
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 03:47:05 UTC, Shadowblitz16 wrote: Is there a way to make a indexed graphics library that can handle importing and exporting true color images? I would guess something like this could be simulated with pointers and references right? My color.d actually can do it. http://dpldocs.info/experimental-docs/arsd.color.html it has a true color to indexed quantize function: http://dpldocs.info/experimental-docs/arsd.color.quantize.html my png.d is capable of loading and saving them: http://dpldocs.info/experimental-docs/arsd.png.readPng.html you will want to cast it to IndexedImage or cast it to TrueColorImage and quantize to get an indexed one. and my simpledisplay.d knows how to display them, but it does so via conversions so palette swaps won't just work live like on a real DOS system or whatever. http://dpldocs.info/experimental-docs/arsd.simpledisplay.Image.fromMemoryImage.html all the module's source code are in here: https://github.com/adamdruppe/arsd but otherwise the support is not great because it is just whenever I decide to answer emails and i'm gonna be busy this next week. but it might be useful to you
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 23:32:13 UTC, norm wrote: On Thursday, 19 September 2019 at 20:47:45 UTC, Shadowblitz16 wrote: [...] I'd create a fragment shader to convert each pixel to 8 bit. There are many examples on the web about creating fragment shaders and 2d opengl scenes, i.e. a 2d scene where OpenGL coordinates are integer pixel coordinates. Once you get that you then just implement the conversion routine. Using the shader you can render the image as a textured quad and send the colour look up table down as an additional 1d texture. This way you can have several D arrays for each colour table and simply swap the texture buffer pointer to instantly switch colours. You can also get cool effects this way when you move to 3d using 8 bit colour tables. the issue with using openGL is its complex and hard to get working with a widget library
Re: String of templated struct at compile time
On Thursday, 19 September 2019 at 21:55:57 UTC, divi wrote: You know what, just because I want to watch the world burn gross but hey if it works it works
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 20:47:45 UTC, Shadowblitz16 wrote: On Thursday, 19 September 2019 at 19:16:03 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 18:25:05 UTC, Shadowblitz16 wrote: I wanted to do 4bpp 16 color graphics. and I didn't want to load anything unnecessary in the image like the palette but instead supply it myself as a Color[16]; I see. In that case, I suggest you find some tutorials on software rendering in C or C++ and adapt them to D. Most of the modern stuff out there is going to be targeting 24-bit or 32-bit graphics. You might find some older tutorials on indexed 8-bit rendering that you can adapt to 4-bit. Nothing to it but storing the palette indices in a byte array. can I do this in D and draw them to a 32bpp bitmap pixel by pixel? I would prefer do do this on the gpu but I don't know how. I'd create a fragment shader to convert each pixel to 8 bit. There are many examples on the web about creating fragment shaders and 2d opengl scenes, i.e. a 2d scene where OpenGL coordinates are integer pixel coordinates. Once you get that you then just implement the conversion routine. Using the shader you can render the image as a textured quad and send the colour look up table down as an additional 1d texture. This way you can have several D arrays for each colour table and simply swap the texture buffer pointer to instantly switch colours. You can also get cool effects this way when you move to 3d using 8 bit colour tables.
Re: Indexed graphics for retro engine?
On 20/09/2019 8:47 AM, Shadowblitz16 wrote: On Thursday, 19 September 2019 at 19:16:03 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 18:25:05 UTC, Shadowblitz16 wrote: I wanted to do 4bpp 16 color graphics. and I didn't want to load anything unnecessary in the image like the palette but instead supply it myself as a Color[16]; I see. In that case, I suggest you find some tutorials on software rendering in C or C++ and adapt them to D. Most of the modern stuff out there is going to be targeting 24-bit or 32-bit graphics. You might find some older tutorials on indexed 8-bit rendering that you can adapt to 4-bit. Nothing to it but storing the palette indices in a byte array. can I do this in D and draw them to a 32bpp bitmap pixel by pixel? I would prefer do do this on the gpu but I don't know how. I've done a quick lookup in my red book (seventh edition so 3.1). For OpenGL the choice between RGBA mode vs indexed happens by the system windowing library (context creation) not OpenGL itself. This means without writing a windowing library yourself, you won't get indexed mode and even then you would be stuck with it for whatever window you draw to. Also for x86 cpu's anything less than 32bpp is going to be inefficient. You may as well map your indexed image straight into RGBA8 on load. As for book recommendations here is one for DOS: https://www.amazon.com/Black-Art-Game-Programming-High-Speed/dp/1571690042 You will only want the first five chapters or so, but it should cover the material you need and have some more for when you are interested in 3d.
Re: Why must a bidirectional range also be a forward range?
On Thursday, September 19, 2019 3:31:32 AM MDT Joseph Rushton Wakeling via Digitalmars-d-learn wrote: > Hello folks, > > A question that occurred to me while implementing a new data > structure recently, which I'm not sure I've ever seen a reason > for. > > Why must bidirectional ranges also be forward ranges (as opposed > to just input ranges)? > > It doesn't seem to me that the `save` property is inherently > required to iterate backwards over a range -- just the `back` and > `popBack` methods. > > It makes sense that, for bidirectionality, the range needs to be > deterministic, so that iterating backward gives the exact same > elements as iterating forward, just in reverse order. But it > seems strange to require the `save` property in order to > automatically assume deterministic behaviour. > > For context, the use-case I have is a data structure which stores > an internal buffer as an array. A robust `save` method would > therefore have to duplicate the array (or at least the active > subset of its contents). This means a fresh heap allocation per > `save`, which has some nasty implications for phobos algorithms > that eagerly `.save` when they can. > > So, I'd rather not implement `save` in this case. But there is > nothing that blocks implementing `back` and `popBack`; yet I > can't use these with any of the functionality that requires > bidirectionality, because the current `isBidirectionalRange` > check requires `save`. > > So what gives? Are there some reasons for the `save` requirement > on bidirectional ranges that I'm missing? And regardless, any > advice on how to handle my particular use-case? > > Thanks & best wishes, > >-- Joe For better or worse, ranges were more or less set up as a linear hierarchy, and it's unlikely that use cases for bidirectional ranges which aren't forward ranges are common. I expect that it's a bit like infinite, bidirectional ranges. In theory, they could be a thing, but the use cases for them are uncommon enough that we don't really support them. Also, I expect that most range-based algorithms which operate on bidirectional ranges would require save anyway. A lot of algorithms do to the point that basic input ranges can be incredibly frustrating to deal with. Assuming we were redesigning the range API (which may happen if we do indeed end up doing a Phobos v2), then maybe we could make it so that bidirectional ranges don't have to be forward ranges, but honestly _any_ ranges which aren't forward ranges are a bit of a problem. We do need to support them on some level for exactly the kind of reasons that you're looking to avoid save with a bidirectional range, but the semantic differences between what makes sense for a basic input range and a forward range really aren't the same (in particular, it works far better for basic input ranges to be reference types, whereas it works better for forward ranges to be value types). As it stands, I don't think that we can change isBidirectionalRange, because it's likely that most code using it relies on its check for isForwardRange. So, I think that we're stuck for the moment, but it is food for thought in a possible range API redesign. I'll add it to my notes on the topic. Some aspects of a range API redesign should look like are pretty clear at this point, whereas others are very much an open question. Ideally, I'd like to force basic input ranges to be reference types, and forward ranges to be value types, but I'm not sure that that's reasonable in practice. It would really clean up some of the semantics of ranges, but it would also likely require allocating a lot more stuff on the heap than would be desirable. Either way, having bidirectional ranges not need to have the equivalent of save would mean treating them as more of an add-on capability (like length) rather than having the kind of hierarchy that we have now. I don't know if that's ultimately a good or a bad thing. - Jonathan M Davis
Re: String of templated struct at compile time
You know what, just because I want to watch the world burn I did the horrible hacky way. mixin template Magic() { import std.array : split; static if (is(typeof(this) == T!(A), alias T, A...)) { mixin(`alias Other = ` ~ T.stringof.split('(')[0] ~ `!(K.B);`); } else { static assert (0); } }
Re: String of templated struct at compile time
On Thursday, 19 September 2019 at 20:16:49 UTC, Adam D. Ruppe wrote: The reason for this is kinda crazy: the token `S` inside that struct (and thus inside its template mixin) refers to the *current instantiation*. Which includes the conflicting constraint. I didn't know that, and it explains a lot. I can be flexible on this and hadn't thought about moving the constraint inside the struct. It doesn't seem as aesthetically pleasing but would probably result in a better API I suppose. Thanks Adam!
Re: The biggest issue in Dlang
On Thursday, 19 September 2019 at 20:50:30 UTC, Daniel Kozak wrote: auto main() { return int(0); } for some reasons does not work WOW :-D this works ok: void main() { return other(); } auto other() { return; } so I believe even this should work: auto main() { return; } I am aware of https://dlang.org/spec/function.html#main, just seems wierd auto does not work too
The biggest issue in Dlang
auto main() { return int(0); } for some reasons does not work WOW :-D this works ok: void main() { return other(); } auto other() { return; } so I believe even this should work: auto main() { return; }
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 19:16:03 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 18:25:05 UTC, Shadowblitz16 wrote: I wanted to do 4bpp 16 color graphics. and I didn't want to load anything unnecessary in the image like the palette but instead supply it myself as a Color[16]; I see. In that case, I suggest you find some tutorials on software rendering in C or C++ and adapt them to D. Most of the modern stuff out there is going to be targeting 24-bit or 32-bit graphics. You might find some older tutorials on indexed 8-bit rendering that you can adapt to 4-bit. Nothing to it but storing the palette indices in a byte array. can I do this in D and draw them to a 32bpp bitmap pixel by pixel? I would prefer do do this on the gpu but I don't know how.
Re: combining libraries into 1 or 1 for each system?
On Thursday, 19 September 2019 at 19:10:26 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 18:28:25 UTC, Shadowblitz16 wrote: I mean I don't want to have multiple dependency dll's but instead just my own dll with the dependencies packed inside. of course dll is only for windows so I would like this done for mac and linux too Then statically link all your dependencies. ok cool I will look into this.
Re: String of templated struct at compile time
On Thursday, 19 September 2019 at 19:49:02 UTC, divi wrote: Due to prior design choices, I have the following setup: enum K { A, B } mixin template Magic() { mixin(`alias Other = ` ~ magic() ~ `!(K.B);`); } Just how constrained are you? I'd be inclined to completely remove the magic() function and make it something like this: mixin template Magic() { static if(is(typeof(this) == T!(A), alias T, A...)) alias Other = T!(K.B); else static assert(0); } But then you also need to change the constraint to something more along these lines: struct S(K k) { static if (k == K.A) mixin Magic; // now makes S!(K.B) } That is, moving the if from a constraint outside to a static if inside. The reason for this is kinda crazy: the token `S` inside that struct (and thus inside its template mixin) refers to the *current instantiation*. Which includes the conflicting constraint. I don't know if there's a way around that. I think it is a minor design flaw in the language personally and would love to see it changed... but I don't know if you can work around it directly, even with mixin strings and external helpers, since the constraint is even copied in the .stringof! Well, I guess you could slice the string on the first " " and cut that stuff off and maybe convince the compiler to look up the template at top level again. That'd probably work but is liable to maybe getting lost in aliases. If changing that constraint is possible though you can get a reasonably robust solution.
String of templated struct at compile time
Due to prior design choices, I have the following setup: enum K { A, B } mixin template Magic() { mixin(`alias Other = ` ~ magic() ~ `!(K.B);`); } struct S(K k) if (k == K.B) {} struct S(K k) if (k == K.A) { mixin Magic; // magic() returns "S" } struct T(K k) if (k == K.B) {} struct T(K k) if (k == K.A) { mixin Magic; // magic() returns "T" } alias A(alias T) = T!(K.A); void main() { A!S a; } Is there any possible way I can write magic() so that the above code works as intended? n.b. it must be able to go through the alias A. For what it's worth, I'm trying to define "Other" for the generic struct parameterised with k == K.A such that I can instantiate it's sister struct parameterised by K.B, e.g. A!S a; // type is S!(K.A) alias U = a.Other; U b; // type is S!(K.B)
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 18:25:05 UTC, Shadowblitz16 wrote: I wanted to do 4bpp 16 color graphics. and I didn't want to load anything unnecessary in the image like the palette but instead supply it myself as a Color[16]; I see. In that case, I suggest you find some tutorials on software rendering in C or C++ and adapt them to D. Most of the modern stuff out there is going to be targeting 24-bit or 32-bit graphics. You might find some older tutorials on indexed 8-bit rendering that you can adapt to 4-bit. Nothing to it but storing the palette indices in a byte array.
Re: combining libraries into 1 or 1 for each system?
On Thursday, 19 September 2019 at 18:28:25 UTC, Shadowblitz16 wrote: I mean I don't want to have multiple dependency dll's but instead just my own dll with the dependencies packed inside. of course dll is only for windows so I would like this done for mac and linux too Then statically link all your dependencies.
Re: combining libraries into 1 or 1 for each system?
On Thursday, 19 September 2019 at 05:16:33 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 03:44:28 UTC, Shadowblitz16 wrote: let's say I have a project the relies on multiple packages.. is it possible to combine these libraries into a single one (or 1 per os) for final shipment of a program? I assume you're referring to dub packages, in which case any dependencies you have will usually be configured to compile as static libraries. That means they'll be compiled into the executable without any extra effort on your part. If they're configured as dynamic libraries, you'll need to ship the dynamic library with your executable or manually edit the configurations to compile as static libraries. If they're bindings to C libraries, you'll need to ship the C dynamic libraries unless you statically link them. If none of this answers your question, please clarify what you mean by "multiple packages". I mean I don't want to have multiple dependency dll's but instead just my own dll with the dependencies packed inside. of course dll is only for windows so I would like this done for mac and linux too
Re: Indexed graphics for retro engine?
On Thursday, 19 September 2019 at 05:22:37 UTC, Mike Parker wrote: On Thursday, 19 September 2019 at 03:47:05 UTC, Shadowblitz16 wrote: Is there a way to make a indexed graphics library that can handle importing and exporting true color images? I don't see why not. I would guess something like this could be simulated with pointers and references right? If you want to, say, take a 24-bit or 32-bit and treat it as an 8-bit image, you'll probably want to actually do a conversion rather than a simulation. In which case you'd probably be better off just using an existing C library like FreeImage. You can find a binding here: https://github.com/BindBC/bindbc-freeimage Otherwise, you'll want to hit up a graphics programming forum for resources on image conversion. Two possibilities: https://www.reddit.com/r/GraphicsProgramming/ https://www.gamedev.net/forums/forum/5-graphics-and-gpu-programming/ I wanted to do 4bpp 16 color graphics. and I didn't want to load anything unnecessary in the image like the palette but instead supply it myself as a Color[16];
Re: Why must a bidirectional range also be a forward range?
On Thursday, 19 September 2019 at 09:31:32 UTC, Joseph Rushton Wakeling wrote: For context, the use-case I have is a data structure which stores an internal buffer as an array. A robust `save` method would therefore have to duplicate the array (or at least the active subset of its contents). This means a fresh heap allocation per `save`, which has some nasty implications for phobos algorithms that eagerly `.save` when they can. In this case, it is probably better to separate the range from the data structure it refers to. For example: struct Container { int[] data; private static struct Range { int[] contents; bool empty(){ return contents.length == 0; } int front() { return contents[0]; } void popFront() { contents = contents[1 .. $]; } int back() { return contents[$ - 1]; } void popBack() { contents = contents[0 .. $ - 1]; } Range save(){ return this; } } Range getRange() { return Range(data[]); } }
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Thursday, 19 September 2019 at 11:16:12 UTC, Simen Kjærås wrote: Might I ask what specifically you're working on? Of course. It's about issue 15881 (and 15763), namely approxEqual not always doing, what people think it should do. (As a side note: I stumbled over this, when I wanted to file a bug report, because I thought it's not doing, what it should do. In my case I was comparing the distance of geographic items in a town. approxEqual decided, that two items which where at opposite ends of the town, are at the same place. Seen from a global perspective, this might indeed be true, but here it was not, what I was looking for.) Well, some people (including me) think, that approxEqual should be a replacement for == for floatingpoint numbers, to accept small errors, that inevitantly creep in. But approxEqual accepts rather large errors with it's default values. (Probably because it's first use was to write some unittests for other functions in phobos, where this is sufficent to make the unittests pass, but not optimal, as errors might stay undetected). As it's not easy to define "small", I searched in the internet, if others have investigated on this and came up with [1], which, in my eyes, is a very good summary. Now I'm working on a replacement for approxEqual with the constraints given in [1]. My first try (PR #7173) was a little bit too fast and would have caused quite some trouble, so I closed it and replaced it with two new PRs (#7180 and #7187) as suggested by n8sh. [1] https://www.python.org/dev/peps/pep-0485/
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Thursday, 19 September 2019 at 10:25:01 UTC, berni wrote: On Thursday, 19 September 2019 at 07:26:17 UTC, Simen Kjærås wrote: That does indeed fail to compile, and there's no easy way to introduce the module-level abs() function to the scope. Again though, MergeOverloads to the rescue: I'm not sure, if MergeOverloads will be accepted into std/math.d. Meanwhile I've created a pull request (#7187), that does not handle complex numbers although the algorithm would be identical. Maybe handling complex numbers in math.d can be added later (or maybe it's better to put this in std/complex.d anyway, but then code duplication would be necessary). You could perfectly well place MergeOverloads inside whatever function you make, thus not polluting std.math: float abs(float f) { return f < 0 ? -f : f; } unittest { import std.complex : complex, cabs = abs; template MergeOverloads(T...) { static foreach (E; T) alias MergeOverloads = E; } alias abs = MergeOverloads!(cabs, .abs); abs(1); abs(complex(1,1)); } (you can also use this to create ridiculous overload sets, since MergeOverloads doesn't care if one function is called abs and the other dropBackExactly. Please don't do this) If you want to introduce MergeOverloads to Phobos officially, std.math is definitely *not* the place though. :) I'd probably say std.functional, but I'm not really sure where it'd belong. Let's put it in std.exception, since it's an exception from D's usual overload rules in functions. :p I don't think anything in std.math explicitly deals with std.complex at this point (some things may handle it generically), so it seems std.complex would be the logical place for anything that does. Might I ask what specifically you're working on? -- Simen
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Thursday, 19 September 2019 at 07:26:17 UTC, Simen Kjærås wrote: That does indeed fail to compile, and there's no easy way to introduce the module-level abs() function to the scope. Again though, MergeOverloads to the rescue: I'm not sure, if MergeOverloads will be accepted into std/math.d. Meanwhile I've created a pull request (#7187), that does not handle complex numbers although the algorithm would be identical. Maybe handling complex numbers in math.d can be added later (or maybe it's better to put this in std/complex.d anyway, but then code duplication would be necessary).
Why must a bidirectional range also be a forward range?
Hello folks, A question that occurred to me while implementing a new data structure recently, which I'm not sure I've ever seen a reason for. Why must bidirectional ranges also be forward ranges (as opposed to just input ranges)? It doesn't seem to me that the `save` property is inherently required to iterate backwards over a range -- just the `back` and `popBack` methods. It makes sense that, for bidirectionality, the range needs to be deterministic, so that iterating backward gives the exact same elements as iterating forward, just in reverse order. But it seems strange to require the `save` property in order to automatically assume deterministic behaviour. For context, the use-case I have is a data structure which stores an internal buffer as an array. A robust `save` method would therefore have to duplicate the array (or at least the active subset of its contents). This means a fresh heap allocation per `save`, which has some nasty implications for phobos algorithms that eagerly `.save` when they can. So, I'd rather not implement `save` in this case. But there is nothing that blocks implementing `back` and `popBack`; yet I can't use these with any of the functionality that requires bidirectionality, because the current `isBidirectionalRange` check requires `save`. So what gives? Are there some reasons for the `save` requirement on bidirectional ranges that I'm missing? And regardless, any advice on how to handle my particular use-case? Thanks & best wishes, -- Joe
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Wednesday, 18 September 2019 at 13:24:05 UTC, berni wrote: On Wednesday, 18 September 2019 at 12:37:28 UTC, Simen Kjærås wrote: How to resolve this, though? The simplest solution is to not use selective imports: import std.math; import std.complex; writeln(abs(complex(1.0,1.0))); writeln(abs(1.0)); That works. But: I'm trying to write some code for math.d and when I put this code inside math.d it doesn't work anymore. Also removing "import std.math" or moving it after the other import, did not help. So what you have is basically this? import std.stdio; float abs(float f) { return f >= 0 ? f : -f; } unittest { import std.complex : complex, abs; auto a = complex(1.0,1.0); auto b = 1.0f; writeln(abs(a)); writeln(abs(b)); } That does indeed fail to compile, and there's no easy way to introduce the module-level abs() function to the scope. Again though, MergeOverloads to the rescue: float abs(float f) { return f < 0 ? -f : f; } unittest { import std.complex : complex, cabs = abs; alias abs = MergeOverloads!(cabs, .abs); abs(1); abs(complex(1,1)); } template MergeOverloads(T...) { static foreach (E; T) alias MergeOverloads = E; } -- Simen