#!python # -*- mode: python; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2022/09/22 20:28:08 +0900> """ Darw trees billboard. Windows10 x64 21H2 + Python 3.9.13 64bit + PyOpenGL 3.1.6 """ import sys import math import random from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from PIL import Image IMG_NAME = "tex.png" # SCRW, SCRH = 1600, 900 SCRW, SCRH = 512, 512 FPS = 60 FLOOR_W = 10.0 TREES_MAX = 256 # USE_DEPTHMASK = True USE_DEPTHMASK = False # GET_DISTANCE = True GET_DISTANCE = False scr_w, scr_h = SCRW, SCRH window = 0 # Rotation angle for the Quads rotx = 0.0 roty = 0.0 objs = [] texture = 0 # lighting light_ambient = [1.0, 1.0, 1.0, 1.0] light_diffuse = [1.0, 1.0, 1.0, 1.0] light_specular = [1.0, 1.0, 1.0, 1.0] light_position = [5.0, 5.0, 10.0, 1.0] # material no_mat = [0.0, 0.0, 0.0, 1.0] mat_ambient = [0.05, 0.1, 0.25, 1.0] mat_diffuse = [0.0, 1.0, 0.0, 1.0] mat_specular = [0.5, 0.5, 0.5, 1.0] mat_emission = [0.2, 0.2, 0.2, 0.0] no_shininess = [0.0] low_shininess = [5.0] high_shininess = [100.0] class Obj: def __init__(self, x, y, z, scale, kind): self.x = x self.y = y self.z = z self.scale = scale uv = [ (0.5, 0.0), (0.75, 0.0), (0.5, 0.25), (0.75, 0.25), (0.5, 0.5), (0.75, 0.5), (0.5, 0.75), (0.75, 0.75), ] self.u, self.v = uv[kind] def draw(self): glAlphaFunc(GL_GREATER, 0.5) glEnable(GL_ALPHA_TEST) glEnable(GL_BLEND) glEnable(GL_TEXTURE_2D) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDisable(GL_LIGHTING) glColor4f(1.0, 1.0, 1.0, 1.0) # color glPushMatrix() glTranslatef(self.x, self.y, self.z) # translate m = glGetDoublev(GL_MODELVIEW_MATRIX) m[0][0] = m[1][1] = m[2][2] = 1.0 m[0][1] = m[0][2] = 0.0 m[1][0] = m[1][2] = 0.0 m[2][0] = m[2][1] = 0.0 glLoadMatrixd(m) w = 1.0 * self.scale u, v = self.u, self.v uw = 0.25 glBegin(GL_QUADS) glTexCoord2f(u, v) glVertex3f(-w, w * 2, 0) # Top Left glTexCoord2f(u + uw, v) glVertex3f(w, w * 2, 0.0) # Top Right glTexCoord2f(u + uw, v + uw) glVertex3f(w, 0.0, 0.0) # Bottom Right glTexCoord2f(u, v + uw) glVertex3f(-w, 0.0, 0.0) # Bottom Left glEnd() glPopMatrix() glDisable(GL_ALPHA_TEST) glDisable(GL_TEXTURE_2D) def init_objs(): global objs w = FLOOR_W n = 4.0 kind = 0 i = 0 while i < TREES_MAX: x = random.uniform(-w, w) y = 0 z = random.uniform(-w, w) if (x * x + z * z <= n * n): continue scale = random.uniform(1.0, 1.5) objs.append(Obj(x, y, z, scale, kind)) kind = (kind + 1) % 4 i += 1 def draw_objs(): global objs for obj in objs: obj.draw() def load_texture(): global texture # load image by using PIL im = Image.open(IMG_NAME) w, h = im.size print("Image: %d x %d, %s" % (w, h, im.mode)) if im.mode == "RGB": # RGB convert to RGBA im.putalpha(alpha=255) elif im.mode == "L" or im.mode == "P": # Grayscale, Index Color convert to RGBA im = im.convert("RGBA") raw_image = im.tobytes() ttype = GL_RGBA if im.mode == "RGB": ttype = GL_RGB print("Set GL_RGB") elif im.mode == "RGBA": ttype = GL_RGBA print("Set GL_RGBA") glBindTexture(GL_TEXTURE_2D, glGenTextures(1)) # glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ALIGNMENT, 4) # set texture glTexImage2D( GL_TEXTURE_2D, # target 0, # MIPMAP level ttype, # texture type (RGB, RGBA) w, # texture image width h, # texture image height 0, # border width ttype, # texture type (RGB, RGBA) GL_UNSIGNED_BYTE, # data is unsigne char raw_image, # texture data pointer ) glClearColor(0, 0, 0, 0) glShadeModel(GL_SMOOTH) # set texture repeat glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # set texture filter glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) # glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND) def draw_floor(): """Draw floor quads.""" w = FLOOR_W u, v = 0.0, 0.0 uw = 0.5 glDisable(GL_LIGHTING) glEnable(GL_BLEND) glEnable(GL_TEXTURE_2D) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(1.0, 1.0, 1.0, 1.0) # color glPushMatrix() glBegin(GL_QUADS) glTexCoord2f(u, v) glVertex3f(-w, 0.0, -w) # Top Left glTexCoord2f(u + uw, v) glVertex3f(w, 0.0, -w) # Top Right glTexCoord2f(u + uw, v + uw) glVertex3f(w, 0.0, w) # Bottom Right glTexCoord2f(u, v + uw) glVertex3f(-w, 0.0, w) # Bottom Left glEnd() glPopMatrix() def draw_cube(): """ Draw cube.""" glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient) glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse) glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular) glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess) glMaterialfv(GL_FRONT, GL_EMISSION, no_mat) glPushMatrix() glDisable(GL_TEXTURE_2D) glColor3f(0.0, 1.0, 0.0) if False: glTranslatef(0.0, 2.0, 0.0) glutSolidCube(4.0) else: glTranslatef(0.0, 1.2, 0.0) glutSolidTeapot(2.0) glPopMatrix() def draw_gl(): global rotx, roty glClearColor(0.85, 0.85, 0.85, 0.0) # background color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # set light glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient) glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse) glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular) glLightfv(GL_LIGHT0, GL_POSITION, light_position) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glLoadIdentity() # Reset The View # move camera r = 16.0 ex = r * math.cos(math.radians(roty + 90.0)) ey = 6.0 + 4.0 * math.cos(math.radians(roty * 3)) ez = r * math.sin(math.radians(roty + 90.0)) tx, ty, tz = 0.0, 0.0, 0.0 gluLookAt(ex, ey, ez, tx, ty, tz, 0, 1, 0) cam_pos = (ex, ey, ez) draw_floor() draw_cube() draw_objs() glutSwapBuffers() def init_viewport_and_pers(width, height): # Prevent A Divide By Zero If The Window Is Too Small if height == 0: height = 1 scr_w, scr_h = width, height # Reset The Current Viewport And Perspective Transformation glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() # Reset The Projection Matrix # Calculate The Aspect Ratio Of The Window # gluPerspective(fovy, aspect, zNear, zFar ) gluPerspective(45.0, float(width) / float(height), 0.1, 100.0) glMatrixMode(GL_MODELVIEW) def InitGL(width, height): glClearColor(0.85, 0.85, 0.85, 0.0) # background color glClearDepth(1.0) # Enables Clearing Of The Depth Buffer glEnable(GL_DEPTH_TEST) # Enables Depth Testing glDepthFunc(GL_LESS) # The Type Of Depth Test To Do glShadeModel(GL_SMOOTH) # Enables Smooth Color Shading # setiing fog fog_color = [0.85, 0.85, 0.85] glEnable(GL_FOG) glFogi(GL_FOG_MODE, GL_LINEAR) glFogfv(GL_FOG_COLOR, fog_color) glFogf(GL_FOG_DENSITY, 0.1) glHint(GL_FOG_HINT, GL_DONT_CARE) glFogf(GL_FOG_START, 8.0) glFogf(GL_FOG_END, 25.0) init_viewport_and_pers(width, height) def resize_gl(width, height): init_viewport_and_pers(width, height) def on_timer(value): global rotx, roty rotx = 0.0 roty = roty + 0.25 glutPostRedisplay() glutTimerFunc(int(1000 / FPS), on_timer, 0) def key_pressed(key, x, y): # If escape is pressed, kill everything. ESCAPE = b"\x1b" if key == ESCAPE or key == b'q': if glutLeaveMainLoop: glutLeaveMainLoop() else: sys.exit() def main(): global window glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(SCRW, SCRH) # glutInitWindowPosition(0, 0) window = glutCreateWindow(b"Draw texture") glutDisplayFunc(draw_gl) glutReshapeFunc(resize_gl) glutKeyboardFunc(key_pressed) # glutFullScreen() # glutIdleFunc(draw_gl) glutTimerFunc(int(1000 / FPS), on_timer, 0) InitGL(SCRW, SCRH) load_texture() init_objs() glutMainLoop() if __name__ == "__main__": print("Hit ESC key to quit.") main()