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.