【PyOpenGL学习笔记】第一篇:启动篇

一、介绍

        OpenGL已经非常古老了,本文是给想学习OpenGL的小白们一个教程,让大家可以写出一个简单的'Hello World'。而且使用的是Python(!!!)OpenGL只需要简简单单的一行 pip install pyOpenGL 就可以,这不就是小白所需要的吗!

        笔者也在学习中,如果大家看到本文内容有误,还望斧正,在这里先谢谢大家了

二、初始化项目

        现在我们正式进入代码的编写,这里我们使用pygame来帮助我们快速初始化,如果你没下载pygame库,那速速下载一个!时间不等人!

import pygame as pg
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

在这里我们从pygame.locals中导入是为了在代码中直接使用预定义的标识符,不然每个标识符都需要pg.locals.xxx可太麻烦了,接下来我们继续

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

定义一个main函数,在其中使用pygame.init()函数来初始化,然后设置分辨率和显示模式,在这里我们使用了双缓冲GL,有助于避免画面撕裂

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

重点概念:视锥体

先把函数的定义摆出来

gluPerspective(fovy, aspect, zNear, zFar)

fovy:垂直视角,也就是游戏里经常见到的FOV,一般为了贴合人眼,游戏取值区间会在60到90,建模等制作时会在45到60之间,防止摄像机造成畸变影响制作

aspect:宽高比,根据不同的比例,图像会有一定程度的拉伸,就像FPS游戏里不变的16/9跟4/3之争,很多人觉得4/3比例下人头会比较大(?)

zNear & zFar:近截面和远截面,这里有一幅图方便理解

视锥体是渲染透视视图的一个非常重要的概念,具体可以浏览这篇知乎文章【透视与正交 - 知乎】本文中就不再赘述啦

import pygame as pg
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                quit()

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        pg.display.flip()
        pg.time.wait(10)

if __name__ == "__main__":
    main()

一次性将代码补全,写一个死循环,在其中添加pygame的事件检测,然后刷新画面

BOOM!!第一个helloworld就做好了,让我们点击运行看一下

黑咕隆咚

别急着退出这篇文章,这是因为我们并没有用GL绘制任何图形,目前只是创建了一个pygame的窗口,使用了双缓冲GL

关闭窗口,我们来添加一个立方体

# Vertex
cubeVertices = ((1, 1, 1), (1, 1, -1), (1, -1, -1), (1, -1, 1),
                (-1, 1, 1), (-1, -1, -1), (-1, -1, 1), (-1, 1, -1))
cubeQuads = ((0, 4, 6, 3), (2, 3, 6, 5), (1, 2, 5, 7),
             (1, 7, 4, 0), (7, 5, 6, 4), (2, 1, 0, 3))
cubeColors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1))

我们先声明一下立方体的顶点坐标,然后将各个点按照逆时针顺序连接为四边形,最后上色。记得一定要逆时针连接,如果没注意好用了顺时针的顺序,面法线就会朝向立方体内部,剔除背面后丑的一

glBegin(GL_QUADS)
for i, quad in enumerate(cubeQuads):
    glColor3fv(cubeColors[i])
    for vertex in quad:
        glVertex3fv(cubeVertices[vertex])
glEnd()

接下来我们用GL绘制一个立方体,众所周知,GL是一个巨大的状态机,所以我们用glBegin来告诉GL我们接下来要绘制了。GL_QUADS声明我们要绘制单个四边面。然后就是我们刚刚定义的一大堆东西出场的时间了,用for循环遍历所有面,先为单个面声明颜色,然后为每个顶点声明坐标,不多废话上代码

import pygame as pg
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

# Vertex
cubeVertices = ((1, 1, 1), (1, 1, -1), (1, -1, -1), (1, -1, 1),
                (-1, 1, 1), (-1, -1, -1), (-1, -1, 1), (-1, 1, -1))
cubeQuads = ((0, 4, 6, 3), (2, 3, 6, 5), (1, 2, 5, 7),
             (1, 7, 4, 0), (7, 5, 6, 4), (2, 1, 0, 3))
cubeColors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1))

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                quit()

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glBegin(GL_QUADS)
        for i, quad in enumerate(cubeQuads):
            glColor3fv(cubeColors[i])
            for vertex in quad:
                glVertex3fv(cubeVertices[vertex])
        glEnd()
        pg.display.flip()
        pg.time.wait(10)

if __name__ == "__main__":
    main()

运行代码看看我们会得到什么

画面是有东西了但是这个立方体怎么这么奇怪呢,那是因为我们没有设置剔除背面,为什么刚才我们没有加上呢,嘿嘿我忘了

import pygame as pg
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

# Vertex
cubeVertices = ((1, 1, 1), (1, 1, -1), (1, -1, -1), (1, -1, 1),
                (-1, 1, 1), (-1, -1, -1), (-1, -1, 1), (-1, 1, -1))
cubeQuads = ((0, 4, 6, 3), (2, 3, 6, 5), (1, 2, 5, 7),
             (1, 7, 4, 0), (7, 5, 6, 4), (2, 1, 0, 3))
cubeColors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1))

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

    glEnable(GL_CULL_FACE)
    glEnable(GL_DEPTH_TEST)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                quit()

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glBegin(GL_QUADS)
        for i, quad in enumerate(cubeQuads):
            glColor3fv(cubeColors[i])
            for vertex in quad:
                glVertex3fv(cubeVertices[vertex])
        glEnd()
        pg.display.flip()
        pg.time.wait(10)

if __name__ == "__main__":
    main()

这下没问题了,但是只有一面似乎有点单调了,让我们给立方体加上一个旋转,不多废话直接上代码

import pygame as pg
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

# Vertex
cubeVertices = ((1, 1, 1), (1, 1, -1), (1, -1, -1), (1, -1, 1),
                (-1, 1, 1), (-1, -1, -1), (-1, -1, 1), (-1, 1, -1))
cubeQuads = ((0, 4, 6, 3), (2, 3, 6, 5), (1, 2, 5, 7),
             (1, 7, 4, 0), (7, 5, 6, 4), (2, 1, 0, 3))
cubeColors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1))

def main():
    pg.init()
    display = (960, 540)
    pg.display.set_mode(display, DOUBLEBUF | OPENGL | RESIZABLE)

    glEnable(GL_CULL_FACE)
    glEnable(GL_DEPTH_TEST)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                quit()
        
        glRotatef(1, 0, 1, 0)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glBegin(GL_QUADS)
        for i, quad in enumerate(cubeQuads):
            glColor3fv(cubeColors[i])
            for vertex in quad:
                glVertex3fv(cubeVertices[vertex])
        glEnd()
        pg.display.flip()
        pg.time.wait(10)

if __name__ == "__main__":
    main()

然后我们就得到了一个旋转的雪月花,不对,立方体

这一篇我们就先到这里吧,下一篇让我们添加上视角的移动,wasd和鼠标控制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值