Search Projects

Wednesday, June 17, 2026

OpenGL Python Program for Rendering Poké Ball

 


1. Render a Normal 3D Poké Ball

The Poké Ball itself is usually just a sphere mesh with:

  • A red upper hemisphere
  • A white lower hemisphere
  • A black center band
  • A circular button on the front

The geometry can be:

  • A UV sphere
  • An icosphere
  • A procedurally generated sphere

The fragment shader might assign colors based on position:

if (worldPos.y > 0.0)
    color = vec3(1.0, 0.0, 0.0); // red
else
    color = vec3(1.0);            // white

The black band can be created using latitude calculations or a separate mesh.


2. Use Low-Resolution Rendering

A common pixel-art trick is rendering to a small framebuffer first.

For example:

320 x 180

instead of:

1920 x 1080

The scene is rendered into an off-screen texture (FBO).

Then that texture is stretched to the screen using:

GL_NEAREST

filtering.

This creates large visible pixels.

glTexParameteri(
    GL_TEXTURE_2D,
    GL_TEXTURE_MIN_FILTER,
    GL_NEAREST
);


3. Quantized Lighting

Instead of smooth lighting:

float diffuse = max(dot(N, L), 0.0);

you reduce it to a few discrete levels.

Example:

float diffuse = max(dot(N, L), 0.0);

diffuse = floor(diffuse * 4.0) / 4.0;

This produces only 4 brightness levels.

Result:

  • Bright region
  • Mid-bright
  • Mid-dark
  • Dark

Very similar to retro sprite shading.


4. Palette Reduction

Pixel-art renderers often limit colors intentionally.

Example:

vec3 color = baseColor * diffuse;

color = floor(color * 8.0) / 8.0;

This converts continuous colors into a small palette.

Instead of thousands of shades, you might have:

  • 8 reds
  • 8 grays
  • 8 blacks

giving a classic pixel-art appearance.


5. Pixel Grid Snapping

Many projects quantize screen coordinates.

Example:

vec2 pixelSize = vec2(4.0);

vec2 snappedUV =
    floor(gl_FragCoord.xy / pixelSize)
    * pixelSize;

All fragments within a block sample the same value.

This creates chunky pixels even when rendering at higher resolutions.


6. Dithering

To fake additional colors, retro-style renderers often use dithering.

Common patterns:

Bayer Matrix

0  8  2 10
12 4 14 6
3 11 1  9
15 7 13 5

Shader:

if(diffuse < threshold)
    color *= 0.8;

This creates the checkerboard patterns often seen in pixel art.


7. Outline Rendering

Many stylized renders add outlines.

Two common methods:

Inverted Hull

Render the model twice:

  1. Normal render
  2. Render enlarged backfaces in black

position += normal * 0.02;

Produces a cartoon outline.

Edge Detection

Run a post-process pass using:

  • Depth buffer
  • Normal buffer

Detect sharp changes and draw black edges.


8. Shadow Quantization

If the image has sharp, stylized shadows, they may use toon shading:

if(diffuse > 0.7)
    shade = 1.0;
else if(diffuse > 0.4)
    shade = 0.7;
else
    shade = 0.3;

Instead of smooth gradients, you get discrete shadow bands.


9. Specular Highlights

The shiny white highlight on the Poké Ball can be stylized:

float spec =
    pow(max(dot(R, V), 0.0), 32.0);

spec = step(0.5, spec);

Using step() creates a hard-edged highlight instead of a realistic glossy reflection.


10. Typical Rendering Pipeline

A common pipeline would be:

Sphere Mesh
     
Vertex Shader
     
Toon Lighting
     
Palette Reduction
     
Render to Low-Res FBO
     
Nearest Neighbor Upscaling
     
Dithering Pass
     
Display

The characteristic "3D object that looks like pixel art" usually comes primarily from:

  1. Rendering to a very low-resolution framebuffer
  2. Nearest-neighbor upscaling
  3. Quantized (toon) lighting
  4. Palette reduction
  5. Optional dithering and outlines

Those five techniques together can make a smooth 3D OpenGL model look remarkably similar to hand-drawn pixel art while still being fully real-time and rotatable.

It can be generate via below mentioned stacks - 

  • PyOpenGL + GLFW (closest to modern OpenGL tutorials)
  • PyOpenGL + Pygame
  • moderngl (cleaner Python API, often easier)
  • Pyglet
  • Ursina (higher-level engine)

  • Python Project

    Google Doc File • 7 KB

    Download

    No comments:

    Post a Comment