10.3 C
New York
Tuesday, October 21, 2025

lighting – Making use of greyscale shading to things in a Python 3D renderer


I need assistance with tips on how to apply greyscale shading to things in a 3D renderer I made in Python. The code is pasted beneath:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
import numpy as np

pygame.init()
screen_size = (800, 600)
HEIGHT = 600
colour = 0
WIDTH = 800
display screen = pygame.show.set_mode(screen_size)
angle = 0
clock = pygame.time.Clock()
# z = 600
f = 400
centre_x = 400
centre_y = 300
line_width = 600
v4 = 0
z = 100
FOV = math.tan(60)
x_left,x_right,y_left,y_rigth=0,0,0,0

# vertices1 = np.array([
#     [-200, -200, -200],
#     [-100, -200, -200],
#     [-100, -100, -200],
#     [-200, -100, -200],
#     [-200, -200, -100],
#     [-100, -200, -100],
#     [-100, -100, -100],
#     [-200, -100, -100]
# ])

dt = 0

vertices = []
triangles = []
texture = pygame.picture.load("D:/3d objects/pexels-pixabay-207142_texture.jpg").convert_alpha() #not used
# with open("C:/Customers/Sohan/Desktop/sport remaining/Low_Poly_AK_47.obj", "r") as g:
#     for line in g:
#         if line.startswith("v "):  # vertex
#             elements = line.strip().cut up()[1:]
#             vertices.append([float(p) for p in parts])
#         elif line.startswith("f "):  # face
#             elements = line.strip().cut up()[1:]
#             face = []
#             for p in elements:
#                 # OBJ is 1-indexed, we convert to 0-indexed
#                 idx = int(p.cut up("/")[0]) - 1
#                 face.append(idx)
#             # triangulate if face has greater than 3 vertices
#             if len(face) == 3:
#                 triangles.append(tuple(face))
#             elif len(face) == 4:
#                 # quad → 2 triangles
#                 triangles.append((face[0], face[1], face[2]))
#                 triangles.append((face[0], face[2], face[3]))
#             else:
#                 # For polygons >4, easy fan triangulation
#                 for i in vary(1, len(face)-1):
#                     triangles.append((face[0], face[i], face[i+1]))

# vertices = np.array(vertices)
vertices = np.array([
    [-1, -1, -1],
    [ 1, -1, -1],
    [ 1,  1, -1],
    [-1,  1, -1],
    [-1, -1,  1],
    [ 1, -1,  1],
    [ 1,  1,  1],
    [-1,  1,  1]
], dtype=float)

triangles = np.array([
    [0, 1, 2], [0, 2, 3],  # again
    [4, 5, 6], [4, 6, 7],  # entrance
    [0, 1, 5], [0, 5, 4],  # backside
    [2, 3, 7], [2, 7, 6],  # high
    [0, 3, 7], [0, 7, 4],  # left
    [1, 2, 6], [1, 6, 5]   # proper
])

uvs = np.array([
    [0, 0],
    [1, 0],
    [1, 1],
    [0, 1],
    [0, 0],
    [1, 0],
    [1, 1],
    [0, 1]
], dtype=float)
close to = 1


print("Vertices:", len(vertices))
print("Triangles:", len(triangles))
scale = 50
vertices = vertices * (scale)/10

# def get_normal(v1,v2,v3):
#     regular = np.cross((v2 - v1),(v3 - v1))
#     return regular*-1





# def get_shadow(v1,v2,v3):
    
#     #digital camera = 0,0,0
#     regular = get_normal(v1,v2,v3)
#     l1_cam = (v1 + v2 + v3)/3
#     unit_l1_cam = l1_cam/np.linalg.norm(l1_cam)

#     unit_normal = regular/np.linalg.norm(regular)
#     theta = np.dot(unit_normal,unit_l1_cam)
#       # digital camera/gentle at origin
#     light_unit = unit_l1_cam

#     depth = max(0, theta)
#     colour = int(255 * depth)


#     theta_rad = np.arccos(np.clip(theta, -1.0, 1.0))
#     theta_deg = np.levels(theta_rad)
#     print(theta_deg)
#     return (colour,colour,colour)



# def get_shadow(v1, v2, v3):
#     # Compute regular
#     regular = get_normal(v1, v2, v3)
#     regular = regular / np.linalg.norm(regular)

#     # Mild course from origin (digital camera)
#     tri_center = (v1 + v2 + v3) / 3
#     light_dir = -tri_center
#     light_dir = light_dir / np.linalg.norm(light_dir)

#     # Depth
#     depth = np.dot(regular, light_dir)
#     depth = np.clip(depth, 0, 1)  # clamp to 0..1
#     color_val = int(255 * depth)
#     return (color_val, color_val, color_val)


    





def total_in_points(v1,v2,v3):
    
    rely = 0
    in_points = []
    for v in [v1, v2, v3]:
        if v[2] > close to  :
            rely += 1
            in_points.append(v[2])

    return in_points



def clipping_triangles(v1,v2,v3):
    points_arr = total_in_points(v1,v2,v3)

    #points_arr[0] = level,z,1
    #points_arr[1] = level,z,2
    if len(points_arr) == 3  :
        tri = np.array([v1,v2,v3])
        return tri
    elif len(points_arr) == 2:
    # Separate inside vs exterior vertices
        vertices_list = [v1, v2, v3]
        inside = [v for v in vertices_list if v[2] > close to]
        exterior = [v for v in vertices_list if v[2] <= close to][0]

        
        i1 = exterior + (inside[0] - exterior) * (close to - exterior[2]) / (inside[0][2] - exterior[2])
        i2 = exterior + (inside[1] - exterior) * (close to - exterior[2]) / (inside[1][2] - exterior[2])

       # 2 new triangles
        tri_new_1 = np.array([inside[0], inside[1], i1])
        tri_new_2 = np.array([i1, inside[1], i2])
        return tri_new_1, tri_new_2

    elif len(points_arr) == 1:
        vertices_list = [v1 , v2 , v3]
        inside = [v for v in vertices_list if v[2] > close to][0]
        exterior = [v for v in vertices_list if v[2] <= close to]

        i1 = inside + (exterior[0] - inside) * (close to - inside[2])/(exterior[0][2] - inside[2])
        i2 = inside + (exterior[1] - inside) * (close to - inside[2])/(exterior[1][2] - inside[2])

        tri_new = np.array([inside,i2,i1])

        return tri_new 
    if len(points_arr) == 0 : return None

def projected_tris(list_proj):
    list_proj = [] 
    return list_proj

def get_points(tri, projected_triangles):
    
    
    projected_new = []
    for v in tri:
        x1, y1 = topygamecoords(v[0] * f / v[2], -v[1] * f / v[2])
        projected_new.append((x1, y1))

        # Append the projected triangle
    projected_triangles.append(projected_new)

    

def draw_tri(tri, vertexes):
    projected_triangles = []
    for tri1 in tri:
        v1, v2, v3 = [vertexes[i] for i in tri1]

        clipped_points = clipping_triangles(v1, v2, v3)

        if clipped_points is None:
            proceed

        tris_to_draw = clipped_points if isinstance(clipped_points, tuple) else [clipped_points]

        for tri_tri in tris_to_draw:
            tri_proj = []
            for v in tri_tri:
                x1, y1 = topygamecoords(v[0] * f / v[2], -v[1] * f / v[2])
                tri_proj.append((x1, y1))
            projected_triangles.append((tri_proj)) 

    return projected_triangles
    








def draw_triangels(tri_angle):
    for tri_proj in tri_angle:
        pygame.draw.polygon(display screen,(255,255,255),tri_proj,1)
    


tx,ty,tz = 0,0,800
def translated_matrix(tx,ty,tz):
    return np.array([[1,0,0,tx],
                        [0,1,0,ty],
                        [0,0,1,tz],
                        [0,0,1,0]])

def rotation_matrix(ang):
    c = math.cos(ang)
    s = math.sin(ang)
    return np.array([
        [c, 0, s, 0],
        [0, 1, 0, 0],
        [-s,0, c, 0],
        [0, 0, 0, 1]
    ])
def sort_tri_z(v1,v2,v3):cross


def topygamecoords(x,y):
    x = x + 400
    y = y + 300
    return x,y

whereas True:
    for occasion in pygame.occasion.get():
        if occasion.sort == QUIT:
            #working = False
            pygame.stop()
            exit()
    display screen.fill((0,0,0))
    dt = clock.tick(60) / 1000.0 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        tz -= 5
    if keys[pygame.K_s]:
        tz += 5
    if keys[pygame.K_a]:
        tx += 5
    if keys[pygame.K_d]:
        tx -= 5
    if keys[pygame.K_q]:
        ty += 5
    if keys[pygame.K_e]:
        ty -= 5
    # angle = math.cos(a)
    
    line_width = (WIDTH*600)/z
    rotated = rotation_matrix(angle)
    translate = translated_matrix(tx,ty,tz)
    #rotated_finish = np.dot(vertices, rotation_matrix(angle).T)

    

    vertices_transformed = []
    projected_triangles = []
    for v in vertices:
        v4 = np.append(v,1)
        v_trans = translate@rotated@v4


        vertices_transformed.append(v_trans[:3])
    projected = draw_tri(tri=triangles,vertexes=vertices_transformed)
    #texture_scan(vertices_transformed[0],vertices_transformed[1],vertices_transformed[2],display screen)
    
    
    if not keys[pygame.K_k]:
        for tri_proj in projected:
            #tri_color = get_shadow(tri_proj[0],tri_proj[1],tri_proj[2])
            pygame.draw.polygon(display screen, (255,255,255), tri_proj) 
            # if len(tri_proj) == 3:
            #     texture_scan(tri_proj[0], tri_proj[1], tri_proj[2], display screen)

    
    
    pygame.show.set_caption(str(clock.get_fps()))
    pygame.show.flip()
    angle+=0.01
    # clock.tick(60)

Now, I’ve tried a primary methodology of taking the traditional to a triangle within the commented out sections. Now the form is type of shading however it’s not appropriate.

The place am I going improper with my calculations? I did strive enjoying round a bit with the indicators however that did not assist. Additionally I ended the rotation to see if issues received higher(they did not).

One concern may be that I am probably not taking the right slope from my digital camera to the triangle, however I am unsure if that is the only real cause. I did strive rendering it as a static object positioned very near my digital camera, so it did not transfer / change its coordinates, however that too gave me flawed outcomes.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles