前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python绘制六角星外廓_Python之OpenGL笔记(32):正交投影画六角星

python绘制六角星外廓_Python之OpenGL笔记(32):正交投影画六角星

作者头像
用户7886150
修改2021-01-19 10:20:26
7750
修改2021-01-19 10:20:26
举报
文章被收录于专栏:bit哲学院bit哲学院

参考链接: 通过Python了解OpenGL

一、目的

 1、摄像机应用,正交投影画六角星;

 二、程序运行结果

 三、摄像机的设置

 吴亚峰《OpenGL ES 3.x游戏开发》(上卷)内容

 从日常生活的经验中可以很容易地了解到,随着摄像机位置、姿态的不同,就算是对同一个场景进行拍摄,得到的画面也是迥然不同的。

 摄像机的设置需要给出 3 方面的信息,包括摄像机的位置、观察的方向以及 up 方向,具体情况如图5-1 所示。

 摄像机的位置很容易理解,用其在 3D 空间中的坐标来表示。

 摄像机观察的方向可以理解为摄像机镜头的指向,用一个观察目标点来表示(通过摄像机位置与观察目标点可以确定一个向量,此向量即代表了摄像机观察的方向)。

 摄像机的 up 方向可以理解为摄像机顶端的指向,用一个向量来表示。

 可以看出,摄像机的位置、朝向、 up 方向可以有很多不同的组合。

 程序通过调用pyrr.matrix44.create_look_at()方法来完成对摄像机的设置

 mvMatrix = pyrr.matrix44.create_look_at(cameraPos, cameraFront, cameraUp,None)

 四、两种投影方式

 在图元装配之后的光栅化阶段前,首先需要把虚拟 3D 世界中的物体投影到二维平面上。 OpenGL中常用的投影模式有两种,分别为正交投影与透视投影

 ##1、 正交投影

 OpenGL中,根据应用程序中ᨀ供的投影矩阵,管线会确定一个可视空间区域,称为

 视景体。视景体是由 6 个平面确定的,这 6 个平面分别为:上平面(up)、下平面(down)、左平面(left)、右平面(right)、远平面(far)、近平面(near)。

 场景中处于视景体内的物体会被投影到近平面上(视景体外面的物体将被裁剪掉),然后再将近平面上投影出的内容映射到屏幕上的视口中。对于正交投影而言,视景体及近平面的情况如图 5-3所示。

 从图 5-3 中可以看出,由于正交投影是平行投影的一种,其投影线(物体的顶点与近平面上投影点的连线)是平行的。故其视景体为长方体,投影到近平面上的图形不会产生真实世界中“近大远小”的效果,图 5-4 更清楚地说明了这个问题

 五、源代码

 """

 程序名称:GL_orthoM.py

 编程: dalong10

 功能: 正交投影的实现

 参考资料: 《OpenGL ES 3.x游戏开发》(上卷)吴亚峰

 """

 import myGL_Funcs #Common OpenGL utilities,see myGL_Funcs.py

 import glfw

 from OpenGL.GL import *

 import numpy

 import numpy as np

 import pyrr

 from PIL import Image

 StarVS = """

 # version 330

 layout(location = 0) in vec3 a_position; //顶点位置

 layout(location = 1) in vec3 a_color; //顶点颜色

 uniform mat4 rotation; //总变换矩阵

 out vec3 v_color; //用于传递给片元着色器的变量

 void main()

 {

 gl_Position = rotation * vec4(a_position, 1.0); //根据总变换矩阵计算此次绘制此顶点位置

 v_color = a_color; //将接收的颜色传递给片元着色器

 }

 """

 StarFS = """

 # version 330

 in vec3 v_color; //接收从顶点着色器过来的参数

 out vec4 out_color; //输出到的片元颜色

 void main()

 {

 out_color = vec4(v_color, 1.0f); //给此片元颜色值

 }

 """

 class SixPointedStar:

 def initVertexData(self,R,r,z): # 初始化顶点数据的initVertexData方法

 self.vertexs = np.array([], np.float32) # 位置FloatArray(numPoint * 3)

 self.colorArray = np.array([], np.float32) # 颜色FloatArray(numPoint * 4)

 # 把矩形平铺在一个平面上

 PI = np.pi

 tempAngle=int(360/6)

 count=0

 for angle in range(0,360,tempAngle): # 循环生成构成六角形各三角形的顶点坐标

 x1=0.0 #第一个三角形,三个点

 y1=0.0

 z1=z

 x2=R*np.cos(PI*angle/180)

 y2=R*np.sin(PI*angle/180)

 z2=z

 x3=r*np.cos(PI*(angle+tempAngle/2)/180)

 y3=r*np.sin(PI*(angle+tempAngle/2)/180)

 z3=z

 x4=0

 y4=0

 z4=z

 x5=r*np.cos(PI*(angle+tempAngle/2)/180)

 y5=r*np.sin(PI*(angle+tempAngle/2)/180)

 z5=z

 x6=R*np.cos(PI*(angle+tempAngle)/180)

 y6=R*np.sin(PI*(angle+tempAngle)/180)

 z6=z

 self.vertexs=np.hstack((self.vertexs, np.array([x1,y1,z1], np.float32) )) #每个顶点xyz三个坐标,6个顶点

 self.vertexs=np.hstack((self.vertexs, np.array([1,1,1], np.float32) )) #中心点为白色

 self.vertexs=np.hstack((self.vertexs, np.array([x2,y2,z2], np.float32) ))

 self.vertexs=np.hstack((self.vertexs, np.array([0.45,0.75,0.75], np.float32) )) #边上的点为淡蓝色

 self.vertexs=np.hstack((self.vertexs, np.array([x3,y3,z3], np.float32) ))

 self.vertexs=np.hstack((self.vertexs, np.array([0.45,0.75,0.75], np.float32) )) #边上的点为淡蓝色

 self.vertexs=np.hstack((self.vertexs, np.array([x4,y4,z4], np.float32) ))

 self.vertexs=np.hstack((self.vertexs, np.array([1,1,1], np.float32) )) #中心点为白色

 self.vertexs=np.hstack((self.vertexs, np.array([x5,y5,z5], np.float32) ))

 self.vertexs=np.hstack((self.vertexs, np.array([0.45,0.75,0.75], np.float32) )) #边上的点为淡蓝色

 self.vertexs=np.hstack((self.vertexs, np.array([x6,y6,z6], np.float32) ))

 self.vertexs=np.hstack((self.vertexs, np.array([0.45,0.75,0.75], np.float32) )) #边上的点为淡蓝色

 def __init__(self,R,r,z):

 self.R= R

 self.r= r

 self.z = z

 self.initVertexData(R,r,z)

 # load shaders

 self.program = myGL_Funcs.loadShaders(StarVS, StarFS)

 #print('ok1')

 glUseProgram(self.program)

 self.vertIndex = glGetAttribLocation(self.program, b"a_position")

 self.colorIndex = glGetAttribLocation(self.program, b"a_color")

 # set up vertex array object (VAO)

 self.vao = glGenVertexArrays(1)

 glBindVertexArray(self.vao)

 # Step2: 创建并绑定VBO 对象 传送数据

 #self.vertexs= vertices

 vertexData = numpy.array(self.vertexs, numpy.float32)

 self.vertexBuffer = glGenBuffers(1)

 glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)

 glBufferData(GL_ARRAY_BUFFER, 4*len(vertexData), vertexData, GL_STATIC_DRAW)

 # enable arrays

 # 顶点位置属性

 glEnableVertexAttribArray(self.vertIndex)

 glVertexAttribPointer(self.vertIndex, 3, GL_FLOAT, GL_FALSE, vertexData.itemsize * 6, ctypes.c_void_p(0))

 # 顶点颜色属性

 glEnableVertexAttribArray(self.colorIndex)

 glVertexAttribPointer(self.colorIndex, 3, GL_FLOAT, GL_FALSE, vertexData.itemsize * 6, ctypes.c_void_p(12))

 # unbind VAO

 glBindVertexArray(0)

 glBindBuffer(GL_ARRAY_BUFFER, 0)

 def render(self, model):

 # use shader

 glUseProgram(self.program)

 # set modelview matrix

 glUniformMatrix4fv(glGetUniformLocation(self.program, 'rotation'),

 1, GL_FALSE, model)

 # bind VAO

 glBindVertexArray(self.vao)

 # draw

 #print(len(self.vertexs))

 glDrawArrays(GL_TRIANGLES,0,len(self.vertexs) )

 # unbind VAO

 glBindVertexArray(0)

 # glfw callback functions

 def window_resize(window, width, height):

 glViewport(0, 0, width, height)

 if __name__ == '__main__':

 import sys

 import glfw

 import OpenGL.GL as gl

 cameraPos=np.array([2.0, 0.0, 3]) # 眼睛的位置(默认z轴的正方向)

 cameraFront=np.array([0.0, 0.0, 0.0]) # 瞄准方向的参考点(默认在坐标原点)

 cameraUp=np.array([0.0, 1.0, 0.0]) # 定义对观察者而言的上方(默认y轴的正方向)

 # Initialize the library

 if not glfw.init():

 sys.exit()

 # Create a windowed mode window and its OpenGL context

 window = glfw.create_window(400, 300, "My OpenGL window", None, None)

 if not window:

 glfw.terminate()

 sys.exit()

 # set window's position

 glfw.set_window_pos(window, 100, 100)

 # set the callback function for window resize

 glfw.set_window_size_callback(window, window_resize)

 # make the context current

 glfw.make_context_current(window)

 glClearColor(0, 0.1, 0.1, 1)

 glEnable(GL_DEPTH_TEST)

 glEnable(GL_BLEND)

 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

 scale1 = pyrr.matrix44.create_from_scale(pyrr.Vector3([1, 1, 1]))

 cube1 = pyrr.matrix44.create_from_translation(pyrr.Vector3([-0.2, 0, 0]))

 board= [None]*6 #创建对象数组

 for i in range(6):

 board[i]=SixPointedStar(0.2,0.5,-0.3*i)

 # the main application loop

 while not glfw.window_should_close(window):

 width, height = glfw.get_framebuffer_size(window)

 ratio = width / float(height)

 currentFrame = 1.0*glfw.get_time()

 glfw.poll_events()

 gl.glViewport(0, 0, width, height)

 gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

 gl.glMatrixMode(gl.GL_PROJECTION)

 gl.glLoadIdentity()

 gl.glOrtho(-ratio, ratio, -1, 1, 1, -1)

 gl.glMatrixMode(gl.GL_MODELVIEW)

 gl.glLoadIdentity()

 gl.glClearColor(0.0,0.0,4.0,0.0)

 pMatrix = pyrr.matrix44.create_orthogonal_projection_matrix(-1, 1,-1,1, 1, 10.0,None)

 # modelview matrix

 mvMatrix = pyrr.matrix44.create_look_at(cameraPos, cameraFront, cameraUp,None)

 for i in range(6):

 model1 = pyrr.matrix44.multiply(scale1, cube1)

 model2 = pyrr.matrix44.multiply(pMatrix,model1)

 model3 = pyrr.matrix44.multiply(mvMatrix,model2)

 board[i].render( model3)

 glfw.swap_buffers(window)

 # terminate glfw, free up allocated resources

 glfw.terminate()

 六、参考资料

 1、大龙10的简书:https://www.jianshu.com/p/49dec482a291

 2、吴亚峰《OpenGL ES 3.x游戏开发》(上卷)

 本文地址:https://blog.csdn.net/dalong10/article/details/107614923

 如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档