python 曲面_Python之OpenGL笔记(35):曲面物体的构建
一、目的
1、曲面物體的構建畫球體;
2、棋盤紋理著色器應用;
二、程序運行結果
棋盤紋理著色器應用
三、曲面物體的構建基本原理
吳亞峰《OpenGL ES 3.x游戲開發》(上卷)內容
OpenGL 中任何形狀的 3D 物體都是用三角形拼湊而成的,因此,構建?面物體最重要的就是找到將曲面恰當拆分成三角形的策略。最基本的策略是首先按照一定的規則將物體按行和列兩個方向進行拆分,這時就可以得到很多的小四邊形。然后再將每個小四邊形拆分成兩個三角形即可。
球面首先被按照緯度(行)和經度(列)的方向拆分成了很多的小四邊形,每個小四邊形又被拆分成兩個小三角形。
這種拆分方式下,三角形中每個頂點的坐標都可以用解析幾何的公式方便地計算出來,具體情況如下。
x = R×cosα×cosβ;
y = R×cosα×sinβ;
z = R×sinα
四、棋盤紋理著色器
棋盤紋理著色器是一種非常簡單的著色器,其原理如下圖所示:
具體的著色策略為,若片元位于黑色小方塊中,就將該片元的顏色設置為紅色;若片元位于白棋盤色小方塊中,則將片元的顏色設置為白色,具體計算方法如下所列。
首先計算出當前片元 x、 y、 z 坐標對應的行數(x 軸)、層數(y 軸)及列數(z 軸)。
如果行數、層數、列數之和為奇數,則片元為紅色;若和為偶數,則片元為白色。
五、源代碼
"""
程序名稱:GL_DrawBall02.py
編程: dalong10
功能: 球體構建、棋盤著色器應用的實現
參考資料: 《OpenGL ES 3.x游戲開發》(上卷)吳亞峰
"""
import myGL_Funcs #Common OpenGL utilities,see myGL_Funcs.py
import sys, random, math
import OpenGL
from OpenGL.GL import *
from OpenGL.GL.shaders import *
import numpy
import numpy as np
import glfw
from pyrr import Quaternion, matrix44, Vector3
strVS = """
#version 330 core
layout(location = 0) in vec3 position;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform float Rx;
uniform float Ry;
uniform float Rz;
uniform float theta1;
out vec3 vPosition ; //用于傳遞給片元著色器的頂點位置
void main(){
mat4 rot3=mat4( vec4(cos(theta1)+Rx*Rx*(1-cos(theta1)), Rx*Ry*(1-cos(theta1))-Rz*sin(theta1), Rx*Rz*(1-cos(theta1))+Ry*sin(theta1), 0),
vec4(Rx*Ry*(1-cos(theta1))+Rz*sin(theta1),cos(theta1)+Ry*Ry*(1-cos(theta1)),Ry*Rz*(1-cos(theta1))-Rx*sin(theta1),0),
vec4(Rx*Rz*(1-cos(theta1))-Ry*sin(theta1),Ry*Rz*(1-cos(theta1))+Rx*sin(theta1),cos(theta1)+Rz*Rz*(1-cos(theta1)), 0.0),
vec4(0.0, 0.0,0.0, 1.0));
gl_Position=uPMatrix * uMVMatrix* rot3 *vec4(position.x, position.y, position.z, 1.0);
//將頂點的位置傳給片元著色器
vPosition = position;//將原始頂點位置傳遞給片元著色器
}
"""
strFS = """
#version 330 core
in vec3 vPosition;//接收從頂點著色器過來的頂點位置
out vec4 fragColor;//輸出的片元顏色
void main(){
vec3 color;
float n = 8.0;//外接立方體每個坐標軸方向切分的份數
float uR=1.0 ;
float span = 2.0*uR/n;//每一份的尺寸(小方塊的邊長)
int i = int((vPosition.x + uR)/span);//當前片元位置小方塊的行數
int j = int((vPosition.y + uR)/span);//當前片元位置小方塊的層數
int k = int((vPosition.z + uR)/span);//當前片元位置小方塊的列數
//計算當前片元行數、層數、列數的和并對2取模
int whichColor = int(mod(float(i+j+k),2.0));
if(whichColor == 1) {//奇數時為紅色
color = vec3(0.678,0.231,0.129);//紅色
}
else {//偶數時為白色
color = vec3(1.0,1.0,1.0);//白色
}
//將計算出的顏色傳遞給管線
fragColor=vec4(color,0);
}
"""
VIEW=np.array([-0.8, 0.8, -0.8, 0.8, 1.0, 20.0]) # 視景體的left/right/bottom/top/near/far六個面
SCALE_K=np.array([1.0, 1.0, 1.0]) # 模型縮放比例
cameraPos=np.array([0.0, 0.0, 30]) # 眼睛的位置(默認z軸的正方向)
cameraFront=np.array([0.0, 0.0, 0.0]) # 瞄準方向的參考點(默認在坐標原點)
cameraUp=np.array([0.0, 1.0, 0.0]) # 定義對觀察者而言的上方(默認y軸的正方向)
WIN_W, WIN_H = 640, 480 # 保存窗口寬度和高度的變量
class FirstSphere:
def __init__(self, cube_verticeside ):
# load shaders
self.program = myGL_Funcs.loadShaders(strVS, strFS)
glUseProgram(self.program)
self.vertIndex = glGetAttribLocation(self.program, b"position")
self.cube_vertices = cube_verticeside
# set up vertex array object (VAO)
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)
# set up VBOs
vertexData = numpy.array(self.cube_vertices, 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)
# Position attribute
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)
glVertexAttribPointer(self.vertIndex, 3, GL_FLOAT, GL_FALSE, 0,None)
# unbind VAO
glBindVertexArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def render(self, Rx,Ry,Rz,r1,pMatrix,mvMatrix):
# use shader
glUseProgram(self.program)
# set proj matrix
glUniformMatrix4fv(glGetUniformLocation(self.program, 'uPMatrix'),
1, GL_FALSE, pMatrix)
# set modelview matrix
glUniformMatrix4fv(glGetUniformLocation(self.program, 'uMVMatrix'),
1, GL_FALSE, mvMatrix)
glUniform1f(glGetUniformLocation(self.program, "Rx"), Rx)
glUniform1f(glGetUniformLocation(self.program, "Ry"), Ry)
glUniform1f(glGetUniformLocation(self.program, "Rz"), Rz)
theta1 = r1*PI/180.0
glUniform1f(glGetUniformLocation(self.program, "theta1"), theta1)
# bind VAO
glBindVertexArray(self.vao)
# draw
glDrawArrays(GL_TRIANGLES,0,len(self.cube_vertices) )
# unbind VAO
glBindVertexArray(0)
def drawglobeVBO():
PI = 3.14159265358979323846264
statcky = 30 # 橫向向切成多少片
stlicex = 30 # 縱向切多少片
R = 1.0 # 半徑
angleHy = (2*PI)/statcky # 橫向每份的角度 算出弧度值
angleZx = (2*PI)/stlicex; # 縱向每份的角度 算出弧度值
NumAngleHy = 0.0 # 當前橫向角度
NumAngleZx = 0.0 # 當前縱向角度
x=0.0
y=0.0
z=0.0
c=numpy.array([], numpy.float32)
for j in range(statcky):
for i in range(stlicex):
NumAngleHy = angleHy*i #
NumAngleZx = angleZx*j # 起點都是軸指向的方向。根據右手定則決定轉向,只要轉向相同,那么兩個就合適
x0 = R*np.cos(NumAngleHy)*np.cos(NumAngleZx)
y0 = R*np.cos(NumAngleHy)*np.sin(NumAngleZx)
z0 = R*np.sin(NumAngleHy)
x1 = R*np.cos(NumAngleHy)*np.cos(NumAngleZx+angleZx)
y1 = R*np.cos(NumAngleHy)*np.sin(NumAngleZx+angleZx)
z1 = R*np.sin(NumAngleHy)
x2 = R*np.cos(NumAngleHy+angleHy)*np.cos(NumAngleZx+angleZx)
y2 = R*np.cos(NumAngleHy+angleHy)*np.sin(NumAngleZx+angleZx)
z2 = R*np.sin(NumAngleHy+angleHy)
x3 = R*np.cos(NumAngleHy+angleHy)*np.cos(NumAngleZx)
y3 = R*np.cos(NumAngleHy+angleHy)*np.sin(NumAngleZx)
z3 = R*np.sin(NumAngleHy+angleHy)
c=np.hstack((c,numpy.array([x1,y1,z1], numpy.float32) ))
c=np.hstack((c,numpy.array([x3,y3,z3], numpy.float32) ))
c=np.hstack((c,numpy.array([x0,y0,z0], numpy.float32) ))
c=np.hstack((c,numpy.array([x1,y1,z1], numpy.float32) ))
c=np.hstack((c,numpy.array([x2,y2,z2], numpy.float32) ))
c=np.hstack((c,numpy.array([x3,y3,z3], numpy.float32) ))
return c
#Is called whenever a key is pressed/released via GLFW
def on_key(window, key, scancode, action, mods):
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.set_window_should_close(window,1)
if __name__ == '__main__':
import sys
import glfw
import OpenGL.GL as gl
keys=numpy.zeros(1024)
deltaTime = 0.0
lastFrame = 0.0 # Time of last frame
# Initialize the library
if not glfw.init():
sys.exit()
# Create a windowed mode window and its OpenGL context
window = glfw.create_window(640, 480, "GL_DrawBall02 ", None, None)
if not window:
glfw.terminate()
sys.exit()
# Make the window's context current
glfw.make_context_current(window)
# Install a key handler
glfw.set_key_callback(window, on_key)
PI = 3.14159265358979323846264
# 畫球面
vert = drawglobeVBO()
# Loop until the user closes the window
a=0
firstSphere1 = FirstSphere(vert)
while not glfw.window_should_close(window):
currentFrame = glfw.get_time()
deltaTime = currentFrame - lastFrame
lastFrame = currentFrame
# Render here
width, height = glfw.get_framebuffer_size(window)
WIN_W, WIN_H =width, height
ratio = width / float(height)
glfw.poll_events()
gl.glViewport(0, 0, width, height)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
#glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); #用于控制多邊形的顯示方式
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.1,0.1,1.0)
# modelview matrix
mvMatrix = matrix44.create_look_at(cameraPos, cameraFront, cameraUp,None) # 設置視點
pMatrix = matrix44.create_perspective_projection_from_bounds(-ratio*1.0, ratio*1.0, -1, 1,20,100,None)
firstSphere1.render( 0, 1,1, a ,pMatrix, mvMatrix) #球
# Swap front and back buffers
glfw.swap_buffers(window)
# Poll for and process events
glfw.poll_events()
glfw.terminate()
六、參考資料
1、大龍10的簡書:https://www.jianshu.com/p/49dec482a291
2、吳亞峰《OpenGL ES 3.x游戲開發》(上卷)
總結
以上是生活随笔為你收集整理的python 曲面_Python之OpenGL笔记(35):曲面物体的构建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 央行票据互换(CBS)什么意思?发行央行
- 下一篇: 裕民银行金裕存是什么?收益怎么样?