私は、PythonのOpenGL APIに慣れようとしています。私は、テクスチャクォードができるポイントに達しました。今度は異なるテクスチャを別のクワッドに配置したいので、クワッド要素のサブセットをレンダリングし、テクスチャを変更し、残りのクワッドをレンダリングする必要があります。pythonのOpenGL APIを使用して、要素インデックス配列のサブセットでどのようにglDrawElementsを実行しますか?
# based on http://www.pygame.org/wiki/GLSLExample
import sys
import pygame
import OpenGL.GL as gl
import OpenGL.GLU as glu
import OpenGL.GLUT as glut
from OpenGL.arrays import vbo
import numpy
from math import *
from PIL import Image
def compile_shader(source, shader_type):
shader = gl.glCreateShader(shader_type)
#source = c_char_p(source)
length = -1 #c_int(-1)
gl.glShaderSource(shader, source)
gl.glCompileShader(shader)
status = gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS)
if not status:
print_log(shader)
gl.glDeleteShader(shader)
raise ValueError('Shader compilation failed')
return shader
def compile_program(vertex_source, fragment_source):
vertex_shader = None
fragment_shader = None
program = gl.glCreateProgram()
if vertex_source:
vertex_shader = compile_shader(vertex_source, gl.GL_VERTEX_SHADER)
gl.glAttachShader(program, vertex_shader)
if fragment_source:
fragment_shader = compile_shader(fragment_source, gl.GL_FRAGMENT_SHADER)
gl.glAttachShader(program, fragment_shader)
gl.glLinkProgram(program)
if vertex_shader:
gl.glDeleteShader(vertex_shader)
if fragment_shader:
gl.glDeleteShader(fragment_shader)
return program
def load_texture(file_name):
image = Image.open(file_name)
width = image.size[0]
height = image.size[1]
image_bytes = image.convert("RGBA").tobytes ("raw", "RGBA", 0, -1)
texture = gl.glGenTextures(1)
gl.glBindTexture (gl.GL_TEXTURE_2D, texture)
gl.glTexParameterf (gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT)
gl.glTexParameterf (gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT)
gl.glTexParameteri (gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,gl.GL_NEAREST)
gl.glTexParameteri (gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR_MIPMAP_LINEAR)
glu.gluBuild2DMipmaps (gl.GL_TEXTURE_2D, gl.GL_RGBA, width, height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, image_bytes)
return texture
def perspective_matrix(fov, aspect_, near, far):
# https://www.opengl.org/discussion_boards/showthread.php/166405-Perspective-Matrix-implementation
f = 1/tan(fov/2)
#print(f, fov)
wiggy = -2 * far * near/(far - near)
aspect = aspect_
return numpy.matrix([
[ f/aspect, 0, 0, 0],
[0, f, 0, 0],
[0, 0, (far+near)/(near-far), wiggy],
[0, 0, -1, 0]] , dtype=numpy.float32)
def print_log(shader):
length = gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH)
if length > 0:
log = gl.glGetShaderInfoLog(shader)
print(log, file=sys.stderr)
#
#
#
def translation_matrix(x, y, z):
return numpy.matrix([[1, 0, 0, x],
[0, 1, 0, y],
[0, 0, 1, z],
[0, 0, 0, 1]], numpy.float32)
def scale_matrix(scale):
return numpy.array([[scale, 0, 0, 0],
[0, scale, 0, 0],
[0, 0, scale, 0],
[0, 0, 0, 1]], numpy.float32)
def norm4(mat):
return [mat, mat/mat[0,3] ]
def rotation_matrix(radians, axis):
len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2])
x = axis[0]/len
y = axis[1]/len
z = axis[2]/len
c = cos(radians)
s = sin(radians)
t=1-c
# http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/
return numpy.matrix([[ t*x*x + c, t*x*y - z*s, t*x*z + y*s, 0],
[ t*x*y + z*s, t*y*y + c, t*y*z - x*s, 0],
[ t*x*z - y*s, t*y*z + x*s, t*z*z + c, 0],
[0,0,0,1]], dtype=numpy.float32)
def attributes(handle):
# http://nullege.com/codes/show/src%40p%40y%40PyGLy-HEAD%40pygly%40shader.py/210/OpenGL.GL.glGetActiveAttrib/python
"""Returns an iterator for the attributes of the specified program.
Each attribute returns a tuple.
:rtype: (name, size, type)
:return: A tuple consisting of 3 values:
name is the variable name
size is the variable size in bytes
type is the GL enumeration
"""
# get number of active uniforms
num_attributes = gl.glGetProgramiv(handle, gl.GL_ACTIVE_ATTRIBUTES)
for index in range(num_attributes):
yield attribute_for_index(handle, index)
def attribute_for_index(handle, index):
"""Returns the attribute for the specified attribute index.
:rtype: tuple(name, size, type)
"""
# Constants like GLsizei are only found in OpenGL.constants
# for older versions of pyopengl
name_length = 30
glNameSize = (gl.constants.GLsizei)()
glSize = (gl.constants.GLint)()
glType = (gl.constants.GLenum)()
glName = (gl.constants.GLchar * name_length)()
gl.glGetActiveAttrib(
handle,
index,
name_length,
glNameSize,
glSize,
glType,
glName
)
name, size, type = glName.value, glSize.value, glType.value
return name, size, type
def app():
glut.glutInit(sys.argv)
width, height = 640, 480
pygame.init()
pygame.display.set_mode((width, height), pygame.OPENGL | pygame.DOUBLEBUF)
program = compile_program('''
// Vertex program
attribute vec2 vertex_uv;
uniform mat4 mvp;
varying vec3 pos;
varying vec2 texCoord;
void main() {
pos = gl_Vertex.xyz;
gl_Position = mvp * gl_Vertex;
texCoord = vertex_uv;
}
''', '''
// Fragment program
varying vec3 pos;
varying vec2 texCoord;
uniform sampler2D tex;
void main() {
gl_FragColor.rgb = texture(tex, texCoord);
//gl_FragColor.r = 0.5;
}
''')
persp =perspective_matrix(pi/4, 1024/float(768), 0.01, 1000)
mat_loc = gl.glGetUniformLocation(program, bytes("mvp", "ascii"))
print(mat_loc)
uv_loc = gl.glGetAttribLocation(program, bytes("vertex_uv", "ascii"))
print(uv_loc)
tmp = gl.glGetAttribLocation(program, bytes("gl_Vertex", "ascii"))
print([ "gl_Vertex", tmp])
tex_loc = gl.glGetUniformLocation(program, bytes("tex", "ascii"))
print(["tex uniform location", tex_loc])
if False:
name_length = 30
glNameSize = (gl.constants.GLsizei)()
glSize = (gl.constants.GLint)()
glType = (gl.constants.GLenum)()
glName = (gl.constants.GLchar * name_length)()
gl.glGetActiveAttrib(program,1,
name_length,
glNameSize,
glSize,
glType,
glName)
print(glName.value)
for name,y,z in attributes(program):
print([name,y,z, gl.glGetAttribLocation(program, name)])
gl.glEnable(gl.GL_DEPTH_TEST)
vertices = [-1, -1, -1,
1, -1, -1,
1, 1, -1,
-1, 1, -1,
-1, -1, 1,
1, -1, 1,
1, 1, 1,
-1, 1, 1]
uvs = [0,0,
1,0,
1,1,
0,1,
0,0,
1,0,
1,1,
0,1,
]
indices = [0,1,2,3,
4,5,6,7,
# 8,9,10,11,
# 12,13,14,15,
# 16,17,18,19,
# 20,21,22,23
]
vert_buffer = vbo.VBO(numpy.array(vertices, dtype=numpy.float32))
uv_buffer = vbo.VBO(numpy.array(uvs, dtype=numpy.float32))
index_buffer = vbo.VBO(numpy.array(indices, dtype=numpy.uint16), target=gl.GL_ELEMENT_ARRAY_BUFFER)
#
texture1 = load_texture("bear64.png")
texture2 = load_texture("flamingo64.gif")
#
quit = False
angle = 0
gl.glUseProgram(program)
# bind all our buffers out here because this scene is so static
index_buffer.bind()
vert_buffer.bind()
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, False, 0, None)
if uv_loc>=0:
uv_buffer.bind()
gl.glEnableVertexAttribArray(uv_loc)
gl.glVertexAttribPointer(uv_loc, 2, gl.GL_FLOAT, False, 0, None)
import time
while not quit:
t0 = time.time()
for e in pygame.event.get():
if e.type == pygame.QUIT:
quit=True
elif e.type == pygame.KEYDOWN:
print(e.key)
if e.key == pygame.K_q:
quit = True
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
z = (t0/10)%1
mvp = persp*translation_matrix(0,0,-5)* scale_matrix(1) * rotation_matrix(pi*0.4, [-1,0,0]) *rotation_matrix(z*pi*2, [0,0,1])
#print(mvp.dot([0,0,0,1]))
mvp_ = numpy.asfortranarray(mvp, dtype=numpy.float32)
gl.glUniformMatrix4fv(mat_loc, 1, False, mvp_)
gl.glBindTexture(gl.GL_TEXTURE_2D, texture1)
gl.glUniform1i(tex_loc, 0)
gl.glDrawElements(gl.GL_QUADS, 4, gl.GL_UNSIGNED_SHORT, None)
gl.glBindTexture(gl.GL_TEXTURE_2D, texture2)
#gl.glDrawElements(gl.GL_QUADS, len(indices)-4, gl.GL_UNSIGNED_SHORT, 4*2)
pygame.display.flip()
if __name__ == '__main__':
app()
この例がどれほど巨大であるかをお詫び申し上げますが、OpenGLはコンパクトではありません。
私の質問は:から構築されたindex_buffer
の残りの四角形を描画するように、gl.glDrawElements
を呼び出すにはどうすればよいですか?私が見たすべての例は、ポインタフィールドにNoneを使用しています。これはwebGLと対照的に、0
は要素の先頭から、i*2
からはi
番目のインデックスから開始することができます。
この例を実行するには、bear64.pngとflamingo64.gifが必要です。すべての古いイメージが機能するはずですが、http://www.purplefrog.com/~thoth/wow/bear-64.gifを試すことができます。 OpenGLの4参照(glBindBuffer)から
https://www.opengl.org/sdk/docs/man:あなたのケースではINDEX_TYPEがSHORTで、SHORTサイズはトリックは値がそうのようなCのvoidポインタにキャストしなければならないことである2です/html/glDrawRangeElements.xhtml私は別の活動に走っていますが、これがあなたの答えかもしれません。明日はそれに近づきます。がんばろう。 – Andreas
その呼び出しを試した後、その開始と終了のパラメータは、インデックス配列によって参照される頂点インデックスを束縛すると思います( 'start <= indices [i] <= end'を意味し、' [0..count ) ')、頂点バッファ全体のロードを避けることができます。私は、私の使命を達成するために、何もなしではなく指標に渡すべきものを見つけ出す必要があると考えます。 –