Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

askthedev.com Logo askthedev.com Logo
Sign InSign Up

askthedev.com

Search
Ask A Question

Mobile menu

Close
Ask A Question
  • Ubuntu
  • Python
  • JavaScript
  • Linux
  • Git
  • Windows
  • HTML
  • SQL
  • AWS
  • Docker
  • Kubernetes
Home/ Questions/Q 39436
In Process

askthedev.com Latest Questions

Asked: April 21, 20252025-04-21T00:14:02+05:30 2025-04-21T00:14:02+05:30

How can I draw a 1 pixel wide grid in a shader using orthographic projection without anti-aliasing for pixel art?

anonymous user

I’m diving into a project where I want to recreate a cool 3D pixel art water effect, similar to what I found in a blog post by David Hollanda. Basically, I want to draw these white horizontal lines across the water’s surface that pulse in and out of existence. It’s a simple idea, but I can’t figure out how to get the actual lines right, especially making sure they look pixel-perfect.

In the video, it seems like the lines are always exactly 1 pixel wide, which is crucial for maintaining that retro pixel art vibe. Since I’m using orthographic projection, I know that perspective isn’t messing with my dimensions, but I’m stuck on how to actually create these lines in a shader. I want them to be sharp and not anti-aliased at all – that smooth blending just ruins the whole pixel art feel.

I’ve seen some hints about using textures to control the positioning and size of these lines. There’s a voronoi texture mentioned that supposedly helps with this too, but I’m not entirely clear on how to go about using it effectively. My guess is that the texture’s alpha channel has some sort of distance information, and I might even be using the RG channels for UV mapping, but how exactly does this all tie together?

I’m thinking of drawing the grid procedural in view-space coordinates, so even if the camera moves, the grid still remains consistent – but how do I ensure the lines always stay 1 pixel wide, regardless of the resolution? Plus, I want to avoid any anti-aliasing magic that could muddle up those clean edges.

If anyone has tips or guidance on how to implement this, especially focusing on the shader side of things, that would be incredible! I really want to nail down that pixel art aesthetic while having dynamic, animated lines on the water surface. Any advice or pointers to similar examples would be super appreciated. Thanks!

  • 0
  • 0
  • 2 2 Answers
  • 0 Followers
  • 0
Share
  • Facebook

    Leave an answer
    Cancel reply

    You must login to add an answer.

    Continue with Google
    or use

    Forgot Password?

    Need An Account, Sign Up Here
    Continue with Google

    2 Answers

    • Voted
    • Oldest
    • Recent
    1. anonymous user
      2025-04-21T00:14:03+05:30Added an answer on April 21, 2025 at 12:14 am

      3D Pixel Art Water Effect with Pulsing Lines

      Okay, so you’re diving into this cool water effect and wanna keep those lines nice and sharp, right? So here’s a few ideas to get started:

      1. Render with a Shader

      To create those white horizontal lines in your shader, you might wanna use a simple sine wave function to control their opacity. Something like this:

      uniform float time; // keeps track of animation time
      varying vec2 vUv;
      
      void main() {
          // Control the frequency and amplitude of the pulses
          float pulse = sin(time + vUv.y * 10.0) * 0.5 + 0.5; 
          // Positioning the lines
          float lineWidth = 0.01; // Adjust based on your pixel size
          float isLine = step(lineWidth, abs(fract(vUv.y * 10.0) - 0.5)); 
          vec3 color = vec3(1.0); // White lines
          gl_FragColor = vec4(color * pulse * isLine, 1.0);
      }
          

      2. Keep It Pixel-Perfect

      To ensure those lines are always 1 pixel wide, you might use screen space coordinates. A simple trick is to calculate the desired width in relation to the screen’s resolution:

      float lineWidth = 1.0 / resolution.y; // 'resolution' being your screen height
          

      3. Avoid Anti-Aliasing

      You’ll want to set the filters on your textures to nearest neighbor, and if you’re using something like WebGL or OpenGL, turn off antialiasing in your setup.

      4. Use Textures for Positioning

      If you’re exploring the voronoi texture, it’s really cool for random patterns! You could map this texture’s RG channels to UVs, using the alpha for opacity manipulation. Kinda like:

      vec4 voronoiTex = texture2D(voronoiTexture, vUv);
      float isLine = step(0.5, voronoiTex.a); // Using alpha for line visibility
          

      5. Stay in View-Space

      Yeah, doing it in view-space makes sense! Just make sure your UV coordinates get updated with the camera movement, but keep everything relative to your viewport size. That way the lines stay consistent as you move.

      6. Experiment!

      Lastly, don’t be shy about tweaking numbers. Mess around with frequencies in the sine function or the pulse speed; you’ll find a rhythm that feels right. And for a bit of flair, try adding some randomness to the line position!

      Hope this helps you out! Good luck nailing that pixel art vibe!

        • 0
      • Reply
      • Share
        Share
        • Share on Facebook
        • Share on Twitter
        • Share on LinkedIn
        • Share on WhatsApp
    2. anonymous user
      2025-04-21T00:14:04+05:30Added an answer on April 21, 2025 at 12:14 am

      To achieve pixel-perfect horizontal lines that stay exactly 1 pixel wide and avoid anti-aliasing artifacts, it’s essential to design your shader around pixel-space coordinates rather than world-space. In your fragment shader, transform the fragment positions into screen-space by multiplying with the resolution, then use a modulus operation to isolate each pixel row. Specifically, calculate floor(gl_FragCoord.y) to determine the exact pixel row you’re working on. By testing this against your procedural line logic, you can ensure that lines always occupy a precise pixel line, with no in-between blending. Disabling any texture filtering (setting your texture sampler to “nearest neighbor”) is also crucial to prevent smoothing and maintain crisp edges.

      If integrating a Voronoi texture, leverage its alpha channel as distance data, mapping it onto screen-space UV coordinates generated from your RG channels or directly derived from fragment coordinates. By thresholding this distance data at an exact pixel width, you’ll achieve the pulsing, dynamic effect you’re describing. Ensure this threshold check aligns strictly with integer pixel boundaries by measuring distances in exact pixel increments, thereby making certain lines remain precisely one pixel wide at all resolutions. Keeping calculations strictly in view-space or fragment position coordinates ensures consistency even if the camera moves, retaining your careful pixel-art aesthetic throughout.

        • 0
      • Reply
      • Share
        Share
        • Share on Facebook
        • Share on Twitter
        • Share on LinkedIn
        • Share on WhatsApp

    Sidebar

    Recent Answers

    1. anonymous user on How do games using Havok manage rollback netcode without corrupting internal state during save/load operations?
    2. anonymous user on How do games using Havok manage rollback netcode without corrupting internal state during save/load operations?
    3. anonymous user on How can I efficiently determine line of sight between points in various 3D grid geometries without surface intersection?
    4. anonymous user on How can I efficiently determine line of sight between points in various 3D grid geometries without surface intersection?
    5. anonymous user on How can I update the server about my hotbar changes in a FabricMC mod?
    • Home
    • Learn Something
    • Ask a Question
    • Answer Unanswered Questions
    • Privacy Policy
    • Terms & Conditions

    © askthedev ❤️ All Rights Reserved

    Explore

    • Ubuntu
    • Python
    • JavaScript
    • Linux
    • Git
    • Windows
    • HTML
    • SQL
    • AWS
    • Docker
    • Kubernetes

    Insert/edit link

    Enter the destination URL

    Or link to existing content

      No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.