我在opengl的停留时间里花了最后几个星期。尽管在一些较旧的NEHE示例之后,我没有问题,但从我阅读的所有内容中,OpenGL4都是完全不同的过程。而且我可以访问《红皮书》和《超级圣经》,但前者仍在提供旧版OpenGL呼叫,而后者使用自己的图书馆。两者都不有助于理解如何在项目中整理代码。例如,我目前的理解是Glu和Glut是遗产,不应用于OpenGL 4。
我可以很容易地为假设的模型空间生成顶点。我很难理解模型最终如何显示在我的屏幕上。我的尝试中约有95%的尝试最终出现黑色屏幕。
预先感谢。
这是一些代码:
# primatives.py
from collections import Iterable
from functools import reduce
import operator
import numpy as np
from exc import UnimplementedMethod
class Primative(object):
SIZE = 1 # number of pixels on a default grid
def __init__(self, point=None, *args, **kwargs):
self.point = point if isinstance(point, Iterable) else [0, 0, 0]
self.point = np.array(self.point, dtype=np.float32)
scaler = [self.SIZE/2]*len(self.point)
self.point = (self.point * scaler).tolist()
@property
def active(self):
attr = "__active__"
if not hasattr(self, attr):
setattr(self, attr, False)
return getattr(self, attr)
@active.setter
def active(self, value):
attr = "__active__"
if value in [True, False]:
setattr(self, attr, value)
return getattr(self, attr)
@property
def vertices(self):
"""Returns a simple list of calculated vertices"""
clsname = self.__class__.__name__
raise UnimplementedMethod(clsname)
@property
def dimension(self):
return len(self.point)
@property
def scaler(self):
attr = "__scaler__"
if not hasattr(self, attr):
size = self.SIZE / 2
setattr(self, attr, [size]*self.dimension)
return getattr(self, attr)
@scaler.setter
def scaler(self, *values):
attr = "__scaler__"
values = values[0] if len(values) == 1 else values
if len(values) == 1 and len(values) != self.point:
if isinstance(values, [int, float]):
setattr(self, attr, [values]*self.dimension)
elif isinstance(values, Iterable):
data = [(v, i)
for v, i in zip(values, xrange(self.dimension))]
value = [v for v, i in data]
if len(value) != self.dimension:
raise ValueError
setattr(self, attr, value)
@property
def translation(self):
attr = "__transalation__"
if not hasattr(self, attr):
size = self.SIZE / 2
setattr(self, attr, [size]*self.dimension)
return getattr(self, attr)
@translation.setter
def transalation(self, *values):
attr = "__transalation__"
values = values[0] if len(values) == 1 else values
if isinstance(values, (int, float)):
setattr(self, attr, [values]*self.dimension)
elif isinstance(values, Iterable):
data = [(v, i)
for v, i in zip(values, xrange(self.dimension))]
value = [v for v, i in data]
if len(value) != self.dimension:
raise ValueError
setattr(self, attr, value)
@property
def rotation(self):
"""
Rotation in radians
"""
attr = "__rotation__"
if not hasattr(self, attr):
setattr(self, attr, [0]*self.dimension)
return getattr(self, attr)
@rotation.setter
def rotation(self, *values):
"""
Rotation in radians
"""
attr = "__rotation__"
values = values[0] if len(values) == 1 else values
if isinstance(values, (int, float)):
setattr(self, attr, [values]*self.dimension)
elif isinstance(values, Iterable):
data = [(v, i)
for v, i in zip(values, xrange(self.dimension))]
value = [v for v, i in data]
if len(value) != self.dimension:
raise ValueError
setattr(self, attr, value)
@property
def volume(self):
clsname = self.__class__.__name__
raise UnimplementedMethod(clsname)
class Cube(Primative):
# G H
# * --------- *
# /| /|
# C / | D / |
# * --------- * |
# | * -------|- *
# | / E | / F
# |/ |/
# * --------- *
# A B
@property
def center_of_mass(self):
"""
Uses density to calculate center of mass
"""
return self.point
@property
def material(self):
clsname = self.__class__.__name__
raise UnimplementedMethod(clsname)
@material.setter
def material(self, value):
clsname = self.__class__.__name__
raise UnimplementedMethod(clsname)
@property
def mass(self):
return self.material.density * self.volume
@property
def volume(self):
func = operator.mul
return reduce(func, self.scaler, 1)
@property
def normals(self):
"""
computes the vertex normals
"""
norm = []
if len(self.point) == 1:
norm = [
# counter clockwise
# x (left hand rule)
(-1), # A
(1) # B
]
elif len(self.point) == 2:
norm = [
# counter clockwise
# x, y (left hand rule)
(-1, -1), # A
(1, -1), # B
(1, 1), # C
(-1, 1) # D
]
elif len(self.point) == 3:
norm = [
# counter clockwise
# x, y, z (left hand rule)
(-1, -1, 1), # A 0
(1, -1, 1), # B 1
(1, 1, 1), # D 2
(-1, 1, 1), # C 3
(-1, -1, -1), # E 4
(1, -1, -1), # F 5
(1, 1, -1), # H 6
(-1, 1, -1), # G 7
]
return norm
@property
def indices(self):
indices = []
if len(self.point) == 2:
indices = [
[[1, 0, 3], [2, 3, 1]], # BAC CDB front
]
elif len(self.point) == 3:
indices = [
[[1, 0, 3], [2, 3, 1]], # BAC CDB front
[[5, 1, 2], [2, 6, 5]], # FBD DHF right
[[4, 5, 6], [6, 7, 4]], # EFH HGE back
[[5, 4, 0], [0, 1, 5]], # FEA ABF bottom
[[0, 4, 7], [7, 3, 0]], # AEG GCA left
[[2, 3, 7], [7, 6, 2]], # DCG GHD top
]
return indices
@property
def nodes(self):
normals = np.array(self.normals, dtype=np.float32)
scaler = np.array(self.scaler, dtype=np.float32)
nodes = normals * scaler
return nodes.tolist()
@property
def vertices(self):
verts = (n for node in self.nodes for n in node)
return verts
和另一个:
# Voxel.py
from collections import Iterable
from time import time
import numpy as np
import pyglet
from pyglet.gl import *
from primatives import Cube
import materials
class Voxel(Cube):
"""
Standard Voxel
"""
def __init__(self, point=None, material=None):
super(Voxel, self).__init__(point=point)
if isinstance(material, materials.Material):
self.material = material
else:
self.material = materials.stone
def __str__(self):
point = ", ".join(str(p) for p in self.point)
material = self.material.name
desc = "<Voxel [%s] (%s)>" % (material, point)
return desc
def __repr__(self):
point = ", ".join(str(p) for p in self.point)
material = self.material.name
desc = "<Voxel %s(%s)>" % (material, point)
return desc
@property
def material(self):
attr = "__material__"
if not hasattr(self, attr):
setattr(self, attr, materials.ether)
return getattr(self, attr)
@material.setter
def material(self, value):
attr = "__material__"
if value in materials.valid_materials:
setattr(self, attr, value)
return getattr(self, attr)
class Chunk(Cube):
"""
A Chunk contains a specified number of Voxels. Chunks are an
optimization to manage voxels which do not change often.
"""
NUMBER = 16
NUMBER_OF_VOXELS_X = NUMBER
NUMBER_OF_VOXELS_Y = NUMBER
NUMBER_OF_VOXELS_Z = NUMBER
def __init__(self, point=None):
point = (0, 0, 0) if point is None else point
super(Chunk, self).__init__(point=point)
self.batch = pyglet.graphics.Batch()
points = []
x_scale = self.NUMBER_OF_VOXELS_X / 2
y_scale = self.NUMBER_OF_VOXELS_Y / 2
z_scale = self.NUMBER_OF_VOXELS_Z / 2
self.rebuild_mesh = True
if len(point) == 1:
points = ((x,) for x in xrange(-x_scale, x_scale))
elif len(point) == 2:
points = ((x, y)
for x in xrange(-x_scale, x_scale)
for y in xrange(-y_scale, y_scale))
elif len(point) == 3:
points = ((x, y, z)
for x in xrange(-x_scale, x_scale)
for y in xrange(-y_scale, y_scale)
for z in xrange(-z_scale, z_scale))
t = time()
self.voxels = dict((point, Voxel(point)) for point in points)
self.active_voxels = dict((p, v)
for p, v in self.voxels.iteritems()
if v.active)
self.inactive_voxels = dict((p, v)
for p, v in self.voxels.iteritems()
if not v.active)
print 'Setup Time: %s' % (time() - t)
@property
def material(self):
return ether
@material.setter
def material(self, value):
if value in materials.valid_materials:
for voxel in self.voxels:
if voxel.material != value:
voxel.material = value
self.rebuild_mesh = True
@property
def mesh(self):
"""
Returns the verticies as defined by the Chunk's Voxels
"""
attr = "__mesh__"
if self.rebuild_mesh == True:
self.mesh_vert_count = 0
vertices = []
t = time()
for point, voxel in self.active_voxels.iteritems():
if voxel.active is True:
vertices.extend(voxel.vertices)
num_verts_in_voxel = len(voxel.normals)
self.mesh_vert_count += num_verts_in_voxel
print "Mesh Generation Time: %s" % time() - t
vertices = tuple(vertices)
setattr(self, attr, vertices)
voxel_count = len(self.active_voxels)
voxel_mesh = self.mesh
count = self.mesh_vert_count
group = None
data = ('v3f/static', vertices)
self.batch.add(count, self.mode, group, data)
return getattr(self, attr)
@property
def center_of_mass(self):
"""
Uses density to calculate center of mass. This is probably only
useful if the chunk represents an object.
"""
center = self.point
points = []
for point, voxel in self.active_voxels.iteritems():
mass = voxel.mass
if mass > 0:
point = [p*mass for p in point]
points.append(point)
points = np.array(points)
means = []
if points.any():
for idx, val in enumerate(self.point):
means.append(np.mean(points[:, idx]))
if means:
center = means
return center
def add(self, voxel):
added = False
point = None
if isinstance(voxel, Voxel):
point = voxel.point
elif isinstance(voxel, Iterable):
point = voxel
if point in self.inactive_voxels.iterkeys():
last = self.voxels[point]
self.voxels[point] = voxel if isinstance(voxel, Voxel) else last
self.voxels[point].active = True
self.active_voxels[point] = self.voxels[point]
self.inactive_voxels.pop(point)
added = True
self.rebuild_mesh = True
return added
def remove(self, voxel):
removed = False
point = None
if isinstance(voxel, Voxel):
point = voxel.point
elif isinstance(voxel, Iterable):
point = voxel
if point in self.active_voxels.iterkeys():
last = self.voxels[point]
self.voxels[point] = voxel if isinstance(voxel, Voxel) else last
self.voxels[point].active = False
self.inactive_voxels[point] = self.voxels[point]
self.active_voxels.pop(point)
removed = True
self.rebuild_mesh = True
return removed
def render(self):
voxels = len(self.active_voxels)
self.batch.draw()
return voxels
if __name__ == "__main__":
import pyglet
from pyglet.gl import *
class Window(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
vox_cnt = self.setup_scene()
print 'Added: %s voxels' % (vox_cnt)
def run(self):
"""wrapper to start the gui loop"""
pyglet.app.run()
def setup_scene(self):
self.chunk = Chunk()
cnt = 0
t = time()
for x in xrange(self.chunk.NUMBER_OF_VOXELS_X):
for y in xrange(self.chunk.NUMBER_OF_VOXELS_Y):
self.chunk.add((x, y))
cnt += 1
print "Setup Scene Time: %s" % (time() - t)
return cnt
def render_scene(self):
y = h = self.height
x = w = self.width
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# glEnable(GL_DEPTH_TEST)
# glDepthFunc(GL_LESS)
t = time()
voxels_drawn = self.chunk.render()
print 'Render Time: %s' % (time() - t)
print 'Points Rendered %s' % voxels_drawn
# array_len = len(self.vertex_data)
# glDrawArrays(GL_TRIANGLES, 0, array_len)
def on_draw(self, *args, **kwargs):
self.render_scene()
w = Window()
w.run()
源分布中有示例,如果下载它们(链接到页面)。
您想看到的一个是在<top-dir>/examples/opengl.py
中 - 对于圆环。如果您进行以下修改,您将有一个立方体。
# line 91:
cube.draw() # previously torus.draw()
# line 178: replace the line with the below (GL_TRIANGLES for GL_QUADS)
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, indices)
# line 187:
cube = Cube(0.8) # previously torus = Torus(1, 0.3, 50, 30)
# replace lines 125 through 166 with:
class Cube(object):
Vertices =(0.,0.,0., 1.,0.,0., 0.,0.,1., 1.,0.,1.,
0.,1.,0., 1.,1.,0., 0.,1.,1., 1.,1.,1.)
def __init__(self, scale):
# Create the vertex and normal arrays.
indices = [0,1,3,2, 1,5,7,3, 5,4,6,7,
0,2,6,4, 0,4,5,1, 2,3,7,6]
normals = [ 0.0, -1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
0.0, 0.0, 1.0]
vertices = [scale * v for v in Cube.Vertices]
vertices = (GLfloat * len(vertices))(*vertices)
normals = (GLfloat * len(normals))(*normals)
我对Python的类包装器不了解,而且我已经有一段时间没有进行任何图形编程。但是我知道,您应该在硬件伙计们社区中搜索有关实际工作和内部词的合格答案谁可以创建VHDL GPU代码或编写低级驱动程序。他们知道确保其工作原理以及某些常见问题解释应该在其社区中可用。
基于该假设,这是一些谷歌搜索我的首先:
-
OpenGL 4.4 API参考卡 - Page 7 - (在http://www.opengl.org上的顶级资源之间可用)显示一些简单的图片>图片(5岁?)渲染管道分为
- 蓝色块指示各种缓冲区,这些缓冲液由OpenGL管道喂食或喂食
- 绿色块指示固定功能阶段
- 黄色块指示可编程阶段
-
震惊的沃尔顿 - DirectX与OpenGL辩论的回归指向130页的幻灯片,OpenGL如何解锁15X性能增长|NVIDIA博客。这两篇文章都属于
AMD,Intel,NVIDIA,Game Developer Converence
我很久以前使用C,C ,Delphi的一些简单的OpenGL,我的建议是首先摆脱Python映射。寻找合适的班级图书馆,并提供良好的社区,只有之后您就知道您要寻找的东西。
以上是恕我直言的水,要在