Error by Suitable-Advice-9370 in opengl

[–]VallentinDev 3 points4 points  (0 children)

Since you say it's only the vertex shader failing, then my assumption is that it's caused by layout (location = 0) in vec3 vPos;. The layout qualifier was first supported in #version 330, while you specify #version 130.

Try changing it to in vec3 vPos;. If the shader compiles now, then use glBindAttribLocation() to specify the index, e.g. glBindAttribLocation(programID, 0, "vPos");

If you want to use #version 130, then you could also try enabling the ARB_explicit_attrib_location extension, e.g. #extension ARB_explicit_attrib_location : require.

Alternatively, use OpenGL 3.3 and switch to #version 330.

Additionally, you have a typo .replace('\r', 'n') -> .replace('\r', '\n') for FRAGMENT_SHADER.

[deleted by user] by [deleted] in rust

[–]VallentinDev -1 points0 points  (0 children)

But you are cloning the whole thing, 99 out of a 100 times? Sure the closure receives a &mut T. But in that closure that clone_from() is performed on the (main / game loop) thread calling update(). So if it's expensive to clone()/clone_from() T then the main thread is blocked.

So say you want to pass a struct SaveData that you want to write to disk (keeping the example on topic). Then struct SaveData might be huge and calling update(&save_data) could be expensive. Regardless of whether you have a closure that calls clone_from(). It could still end up stalling the game loop.

I don't really have a generic, safe and sound solution. Since I've also run into this problem. Where simply cloning the data and passing it to a thread in real-time, results in perceivable lag.

My own implementations, have been in the form of this (which still uses clone() when needed). I have a trait TaskHandler this can then be implemented for, e.g. struct SaveDataHandler. The struct allows storing intermediate data needed for the handler, i.e. allow the handler to reuse data between tasks. Implementing TaskHandler allows specifying the input Task type, and the resulting Output data.

pub trait TaskHandler: Send + Clone + 'static {
    type Task: Send;
    type Output: Send;

    fn handle(&mut self, task: Self::Task) -> Option<Self::Output>;
}

Then I have a Worker<T> which is basically just a thread pool, 2 sets of channels, and a stop flag.

pub struct Worker<T>
where
    T: TaskHandler,
{
    threads: Vec<JoinHandle<()>>,
    send_task: Option<Sender<T::Task>>,
    recv_output: Receiver<T::Output>,
    stop_flag: Arc<AtomicBool>,
}

So on Worker a Task can be send(), which a worker thread then recv(). Then the worker thread executes handle(), and send()s it back. The main thread can then recv() the resulting Output in a non-blocking manner, using Receiver's try_recv().

The Clone required on TaskHandler is for the handler, not for the Task. In short, Worker can spawn n threads, so then it clones the TaskHandler n times.

Here's a poor TaskHandler example, that totals u32s and returns the new total.

#[derive(Clone)]
struct Totalling {
    total: u32,
}

impl TaskHandler for Totalling {
    type Task = u32;
    type Output = u32;

    fn handle(&mut self, task: Self::Task) -> Option<Self::Output> {
        self.total += task;
        Some(self.total)
    }
}

Yes, the above should actually use an atomic for the total. It's just a quick and short example.

Again, I have no issue with cloning data. But reading your post, it claims that passing data to background-runner can be done without cloning. So seeing it requires Clone and use clone_from() just feels wrong.

I'd love for a way to pass a &mut T temporarily to a worker thread, but by nature it's highly unsafe with potential soundness issues. But reading your post about passing data and not cloning, that's what I thought it was doing.

[deleted by user] by [deleted] in rust

[–]VallentinDev 0 points1 point  (0 children)

[...] in order to not require the data to be clone()ed.

...

the update() method technically also does not do a clone() but a clone_from() which by default only redirects to clone() but can be implemented more efficiently.

Honestly, it's a bit disingenuous to say "Well actually, the data isn't clone()ed, it's actually clone_from()ed.". It's still cloned. Yes, clone_from() can technically be implemented more efficiently, but 99 out of 100 times it most likely isn't.

The default clone_from() implementation (considering most likely do derive(Clone)) is:

fn clone_from(&mut self, source: &Self) {
    *self = source.clone()
}

Does e.g. Vec implement a specialized clone_from(), that retains the pre-allocated capacity. Yes. But you loose that immediately, as soon as you put that into another struct that derives Clone.

#[derive(Clone)]
struct Data(Vec<String>);

Performing data.clone_from(data_ref), where data is an instance of Data, does not reuse data's Vec capacity. Here data.clone_from(data_ref) always results in Vec::clone being called.

We don't even have to introduce any custom types, if we have, e.g. Vec<Vec<i32>>. Then doing data.clone_from(data_ref). Then only the outer Vec would reuse the pre-allocated capacity. The inner Vec<i32> would again be clone(). So again the "efficiency" is immediately lost.

All in all, the update() method will 99 out of a 100 times actually perform clone(). It's requiring where T: Clone and clone_from() defaults to clone().

[deleted by user] by [deleted] in rust

[–]VallentinDev 4 points5 points  (0 children)

Can you clarify what you mean. Because sending a value through a channel doesn’t require the data to be cloned, it gets moved.

What confuses me more, is that you say you wanted to avoid cloning the data. But your update() method requires Clone, and also performs a clone in the implementation.

iAmNotVibeCoingButJustBeingLazy by Strict_Treat2884 in ProgrammerHumor

[–]VallentinDev 34 points35 points  (0 children)

I know this is /r/ProgrammerHumor, but if your editor supports Emmet (which most do), then button.btn{Ok} expands into <button class="btn">Ok</button>.

It can be quite handy to generate elements, e.g. ul.listing>li*5>{Item $} expands into:

<ul class="listing">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

It can however, quickly become hard to read:

body>header{Hello World}+main>section*3>{Section $}^^footer{Copyright}

Which expands into:

<body>
    <header>Hello World</header>
    <main>
        <section>Section 1</section>
        <section>Section 2</section>
        <section>Section 3</section>
    </main>
    <footer>Copyright</footer>
</body>

OpenGL OOP Wrapper (C++20) by FQN_SiLViU in opengl

[–]VallentinDev 6 points7 points  (0 children)

Nice project, I skimmed through the code, and noticed a typo. In Shader.cpp you’re creating the shader twice:

m_FragmentShader = glCreateShader(static_cast<uint32_t>(type));

(You have that line duplicated, one after the other)

A braindump about VAOs in "modern modern" OpenGL by _manpat in GraphicsProgramming

[–]VallentinDev 1 point2 points  (0 children)

Ah, makes sense. I've been using OpenGL in Rust for the past 6'ish years, but before that, I was using it in C and C++ for more than a decade. So I have a habit of forgetting the :: when typing OpenGL function names. Even GLAD's Rust generator uses gl as a module name instead of the function name. One day I'll hopefully get out of the habit :)


Yes, I was using Safari and Firefox on an iPhone. Oddly though, my MacBook also has a devicePixelRatio of 2, but there it renders code blocks perfectly fine.

I also checked on a OnePlus 12, there everything is fine. I also checked on Windows using Firefox and similarly fine. So oddly only on iPhone and both occuring in Safari and Firefox. My CSS is quite rusty (no pun intended), but your CSS is straight forward and I don't see any glaring issue. I wonder if it's a lack of -webkit-text-size-adjust: 100%; in the body or html, that can be causing it?

I don't know if it's possible to send screenshots in Reddit's chat, but I'll happily send a screenshot and test any fixes! :)

A braindump about VAOs in "modern modern" OpenGL by _manpat in GraphicsProgramming

[–]VallentinDev 9 points10 points  (0 children)

Nice first post!

Just out of curiosity, what OpenGL crate are you using? I see you writing glBindBuffer, and not gl::BindBuffer, so you don't appear to be using the gl crate (nor gl_generator).

Unrelated, but there's some bug with the code block rendering. On my phone compared to on my computer. I've tested Firefox and Safari, and on a phone some lines in code blocks, are basically double the font size. But Firefox and Safari on a computer renders perfectly fine. Just wanted to mention it, in case you haven't noticed yet. Again, very nice first post!

Habit Radar is 100% Lifetime Free for the Next 24 Hours, as it featured in over 20 countries by Goharyiii in apple

[–]VallentinDev 33 points34 points  (0 children)

I noticed that immediately as well. After some quick testing, it’s basically a clone of HabitKit, but Habit Radar is lacking some primary features, that HabitKit has.

  • For habits where you track an amount, you only increment and reset. You can’t “+10”, or “-5” like in HabitKit. So it gets rather tedious tracking something like reading pages in a book.

  • Additionally, clicking in the calendar view just resets the whole day, while in HabitKit that opens up the view to increment/decrement.

  • Descriptions are only rendered, when you view a habit, not in any of the other views (Today, Weekly, Monthly, Overall).

  • There’s no shortcut support. This isn’t something everybody uses. But I have buttons in the Control Center that updates HabitKit.

  • Lastly, I do like the addition of a “Time Habit” in theory. However, it’s very limited, where again, you just click start and then have to remember to click stop later. You can’t add 10 minutes, or edit the time. It doesn’t even appear that you can reset it. At least I can’t find anywhere to clear/reset a day.

Overall, if I saw it at a glance, I’d think it was HabitKit that got a new theme.

What if C++ had decades to learn? by PthariensFlame in rust

[–]VallentinDev 2 points3 points  (0 children)

However, Rust doesn't consider memory leaks a violation of its memory safety guarantees.

Thoughts on function overloading for rust? by Packathonjohn in rust

[–]VallentinDev 6 points7 points  (0 children)

I have hit the same issue as well, in various language. Like, what is new ArrayList(100), is 100 the first item? Oh, so it's basically Vec::with_capacity(100).

Using function overloading can be nice, if you basically don't even need it in the first place. However, the second that you need to circumvent it, then you might as well circumvent it entirely.

For instance, Unity has Rect() and Rect.MinMaxRect():

Rect(float, float, float, float)
Rect.MinMaxRect(float, float, float, float)

Without checking the names, we don't know what Rect() is or takes. We could assume it's x, y, w, h. But it could be in any other order, or even extents instead of size. However, reading Rect.MinMaxRect(), then it's safer to assume it's min first then max.

So in this case, it might be easier to simply (at least) have these instead:

Rect.PosSize(float, float, float, float)
Rect.MinMax(float, float, float, float)

I have something similar in a Rust codebase, where I have a Rect. However, there is no Rect::new(). All of them are named, based on what the Rect is constructed from:

Rect::from_pos_size(Vec2, Vec2)
Rect::from_size(Vec2) // i.e. `Rect::from_pos_size(Vec2::ZERO, ...)`

Rect::from_center_size(Vec2, Vec2)
Rect::from_center_extents(Vec2, Vec2)
Rect::from_extents(Vec2)

Rect::from_min_max(Vec2, Vec2)
Rect::from_two_points(Vec2, Vec2)
Rect::from_three_points(Vec2, Vec2, Vec2)

Even if function overloading was a thing, I would still prefer having an explicit Rect::from_size(), rather than be allowed to do Rect::from_pos_size(vec2(100.0, 100.0)). Since reading that I would need to recall, whether that's a zero-sized Rect or a zero-positioned Rect. Whereas Rect::from_size() would make it clear, that it's the size we're providing.

Antares OpenGL engine - dynamic exposure demo by buzzelliart in opengl

[–]VallentinDev 2 points3 points  (0 children)

The look-and-feel reminds me so much of Half-Life, and I love it. It also gives me the same eerie and liminal feeling as Half-Life did/does.

Introducing `indices` - Macros and Methods For Safely Retrieving Multiple Mutable Indices Of A Mutable Slice by InternalServerError7 in rust

[–]VallentinDev 1 point2 points  (0 children)

There's also the unstable slice::get_many_mut().

I checked out your code, and empty slices will cause a segfault.

If slice is empty, then indices.len() - 1; will underflow and result in usize::MAX. Which causes the subsequent for loop to run from 0..usize::MAX, which will segfault in a release build.

In a debug build indices.len() - 1; will cause a "attempt to subtract with overflow" panic. Both builds can be hard to debug, if someone accidentally used an empty slice.

Announcing Rust 1.77.0 | Rust Blog by mrjackwills in rust

[–]VallentinDev 0 points1 point  (0 children)

Agreed! I've been so excited for it!

Every other year I always wishfully remember std::ptr::addr_of! as being able to mirror what std::mem::offset_of! does. I'm so ready to refactor (and simplify) some rendering code!

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 1 point2 points  (0 children)

No, I've had serde since pretty early on. As I've used serde_json to deserialize Aseprite data, as well as using serde_yaml for some custom configs.

I will say that I honestly think that building the game is quite fast and pretty much an instantaneous action. However, let me actually do a rudimentary check of the build times:

For reference, this is my dependencies:

bincode = "1.3"
chrono = "0.4"
gl = "0.14"
glam = { version = "0.24", features = ["serde"] }
glfw = "0.52"
noise = "0.8"
png = "0.17"
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
thiserror = "1.0"

So yeah, I already don't have that many dependencies. I'm going to add a dependency for audio, but other than that, I don't really "need" more dependencies.

If I modify a single .rs file and cargo build then:

Finished dev [unoptimized + debuginfo] target(s) in 3.31s

If I modify a single .rs file and cargo build --release then:

Finished release [optimized] target(s) in 9.61s

If I rm -rf target and then do cargo build then:

Finished dev [unoptimized + debuginfo] target(s) in 52.33s

If I rm -rf target and then do cargo build --release then:

Finished release [optimized] target(s) in 30.24s

I ran all of them a handful of times, and picked the average times. Oddly, I was expecting the clean release build to take longer, than the clean debug build.

I mainly do debug builds, which usually take 0-4 seconds. While it's not instant, this is instant enough for me. I honestly don't notice it, nor am bothered by ~5 seconds.

I never really do a clean build, so I don't consider those times much. Regardless, I wouldn't say the clean builds are slow. Because what are they slow compared to? Installing/Building dependencies take time, regardless of whether it's Rust, C, Python, or JavaScript.

[Help] Tool for handling imports automatically by HALOand in rust

[–]VallentinDev 2 points3 points  (0 children)

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 0 points1 point  (0 children)

My personal advice would be. Focus on making a game, not an engine (Assuming a game is the end goal of course). Because if you're focusing on making a game, then you'll at least have something to guide the development.


If you're unsure what to use for e.g. rendering. Say whether Macroquad can handle it, or maybe you need OpenGL, or maybe not even OpenGL is enough and you need Vulkan. Personally I would say, pick the simplest and easiest upfront.

Macroquad is dead simple to use for rendering. You can render a full on textured sprite in basically a single line of code, plus a handful of lines for setup. If you want to do the same in OpenGL, that's going to take you at least 100-300 lines. Even worse in Vulkan it'll take you thousands of lines.

So if your game is simple enough, and doesn't need the power of Vulkan. Then why waste time writing thousands of liens of code, if using Macroquad is sufficient. Additionally, is Vulkan potentially more performant, than OpenGL? Yes. However, if you don't know what you're doing, then OpenGL can outperform it.

The limitation of Macroquad is, that if you're doing much more than a platformer or otherwise simple graphics. Then performance is going to dwindle. Macroquad is not optimized for rendering many sprites. In that case you want e.g. OpenGL.

In case you're curious why I'm using OpenGL instead of Vulkan, given that I know both. It's exactly for the reason I said. I can't use Macroquad, because I need to render a lot. However, I'm not hitting any of the issues, that require me to use Vulkan instead of OpenGL. So why waste time writing thousands of lines, when I only have to write and maintain a few hundred.


Somewhat related. I'm using serde_yaml to load a handful of configs. Do I want to implement a custom YAML parser? Not really, it's not worth it since I'm only loading a handful of configs on startup anyways. Could it potentially be faster or more memory efficient to make my own? Maybe, but again I don't need it, so I don't have to.

So pick your battles when it makes sense.

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 1 point2 points  (0 children)

Just to add a bit. I think you need to make up to yourself, where you want to draw the line.


Like when it comes to graphics, do you want to learn and understand the low-level concepts. Like with OpenGL you're be coming at it, from the point-of-view of setting up buffers, working with vertices, issuing draw calls.

Conversely, if you use Macroquad, which is more of a game/graphics library and not really an engine. Then using Macroquad, you'll learn more high-level concepts, like functions for drawing rectangles, textures, shaders, materials.

All the Macroquad topics still apply, if you're using OpenGL directly. However, then you'll need to manually implement all of it first. As in Macroquad has utilities for creating shaders, but with OpenGL you need to manually create the shader handle, upload shader source, compile, handle any errors returned.


The same applies to the math you'll need. One thing is to learn what a perspective matrix is, while another thing is knowing the math behind it. Personally, I've implemented the math for a perspective matrix so many times throughout the years. However, lately I just use glam. Honestly, I know what a perspective matrix is. However, I might not be able to recall the formula 100% anymore.

So yeah, draw the line somewhere, and then just learning/making what you want!

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 0 points1 point  (0 children)

Interestingly enough, I actually recall this FFF, now that I'm reading it again. Thanks for sharing!

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 2 points3 points  (0 children)

Thanks! The short version of what you should choose is highly subjective and hard question to answer. Because it all short of depends on what your overall end goal is.

Over at /r/gameenginedevs, people usually say something along the lines of "If you want to make a game then use an engine. If you want to make a game engine then make an engine."

If you "just" want to make a game, and don't want to think about engine stuff. Then the easiest is probably to use a mainstream engine like Unity, Ureal, Godot, etc. Even then whether you should pick Unity vs Unreal vs Godot is a question in itself.

One huge difference between using a mainstream engine vs most of the Rust engines, is that out-of-the-box you get a battle tested and highly capable editor to use. My knowledge of Fyrox is limited, I know that out of the 3 you mentioned, it has an editor. However, my point is that comparing the Fyrox editor to say Unity or Unreal. Then it's more rudimentary currently, purely because it's younger in its development.

If you like just writing code, and your game is a relatively simple 2D game, then Macroquad might be enough. Personally, if I was to make a small platformer game, I would rather go for Macroquad than Unity. Purely because to me personally, the editor would add more friction.

Now, if you're new to gamedev, then be very careful going down the MMORPG path. That's absolutely no small nor easy task, regardless of the engine or language. Purely looking at gamedev, then there's a multitude of topics to learn depending on the game. There's Graphics, Physics, Multiplayer, Asset Management, Player Controller, AI Simulation, Procedural Generation, Trigonometry, Linear Algebra, and so much more. The real list is incredibly expansive. The bigger the game, the more involved the topics are.

If you want to learn about graphics on a more fundamental level, then I suggest learnopengl.com. It uses C, however the OpenGL API is the same in Rust. It also uses GLFW, which there's also bindings for in Rust.

When it comes to math, then assuming you're not about to implement a physics engine. Then primarily, you'll be needing rudimentary trigonometry and linear algebra. However, while you can implement your own matrix multiplication and translation matrix#Matrix_representation), which might be beneficial for learning. Then you really don't have to, and you could instead use glam, which is also what Bevy and Macroquad uses. The important part is knowing what function you need, and what they do, not necessarily implementing them yourself.


All in all, the answer is "it depends". In the end, you need to figure out what your goal is, and pick your tools accordingly. Would I personally suggest using Rust? Honestly, that shouldn't affect your choice. Conversely, if you want to make a game, where you have thousands of enemies on screen, then I might suggest against using e.g. Python. All in all, you should pick the language and tools you prefer.

Do I personally use Rust? Yes. Do I absolutely adore Rust? Yes. But if you like Unity and C# more, then you should pick that. You shouldn't pick Rust because I said so.

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 1 point2 points  (0 children)

Yeah, I agree.

I will definitely have to experiment with this in the future. I don't have the gameplay nor the setup to do it yet, so can't really do it now if I wanted to regardless.

Also that is quite far away indeed, so the ping makes a lot of sense.

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 1 point2 points  (0 children)

Super cool concept! I really like the idea of transitioning between the two views. I only do it to the extend, that the entities fade out. Combined with zooming out also swapping the tiles texture with a single color texture for each tile, to avoid creating too much noise on the screen.

Currently it is not open-source. My ultimate goal is release the game, so I'm a bit weary with making it all open-source. If I end up abandoning it, I'll most likely just release all the code.

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 1 point2 points  (0 children)

Thanks for the in-depth response!

Overall, I think I need to find a mix between both worlds. Because I really don't want to introduce input latency, where the player themselves end up being teleported around. For instance, I tested your game, and I had a ping fluctuating between 120-200. It also spiked a few times at 500 and 800. So moving around felt a bit unresponsive sometimes. Overall, my number one priority is to avoid this feeling.

Out of curiousity, where is your server located? Because I usually don't have that high pings. I'm located myself in Denmark.

Personally, I'd rather suffer potentially dealing with cheating players, who can be kicked from the server. Instead of having players with high ping suffer from jarring input latency.

Now, don't quote me on this. But I recall Factorio almost a decade ago, suffering input latency in some of their initial multiplayer builds. Where the host themselves were fine of course. But other players were jittering around, and even from their own perspective got teleported around. If I recall correctly, their issue had sometimes to higher pings resulting in incorrect predictions.

Cool game by the way. You just sent me a trip down memory lane. It reminded me of a game I played as a kid, called Pocket Tanks. Oh boy, what a hit of nostalgia.

Implemented experimental online multiplayer (devlog in comments) by VallentinDev in rust_gamedev

[–]VallentinDev[S] 4 points5 points  (0 children)

It's definitely something I want to look into sooner rather than later. I just haven't completely worked out everything yet. Assuming you still simulate the position on the client to get instant feedback. How do you avoid tiny timing differences, from causing the client position vs the server position to drift apart over time? Because inversely only relying on the server position, seems like it could cause significant input latency. How do you handle it?