まあ、色々スキルもあるけれど、これが動けば大抵のモノは作れちゃうんじゃないかな。
テスト用なので細かいところは、動けば良いよ的になってます。
テスト用なので細かいところは、動けば良いよ的になってます。
from OpenGL.GL import *
from OpenGL.GL.shaders import *
import pygame
import numpy
import math
import sys
vs = """
in vec3 position;
in vec3 normal;
in vec3 color;
in vec2 uv;
uniform mat4 pMatrix;
uniform mat4 vMatrix;
uniform mat4 mMatrix;
out vec3 vColor;
out vec2 vUv;
void main(){
vColor = color * max(dot(vec3(1.0), (vMatrix*mMatrix*vec4(normal, 0.0)).xyz), 0.2);
vUv = uv;
gl_Position = pMatrix * vMatrix * mMatrix * vec4(position, 1.0);
}
"""
fs = """
in vec3 vColor;
in vec2 vUv;
void main(void)
{
gl_FragColor = vec4(vColor * vec3(vUv, 0.5), 1.0);
}
"""
def perspective(fovy, aspect, near, far):
top = near * math.tan(fovy * math.pi / 360)
right = top * aspect
u = right * 2
v = top * 2
w = far - near
return numpy.array([
near * 2 / u, 0, 0, 0, 0,
near * 2 / v, 0, 0, 0, 0,
-(far + near) / w, -1, 0, 0,
-(far * near * 2) / w, 0], numpy.float32)
def normalize(p):
return p / numpy.linalg.norm(p)
def lookAt(eye, center, up):
z = normalize(numpy.array(eye) - numpy.array(center))
x = normalize(numpy.cross(up, z))
y = normalize(numpy.cross(z, x))
return numpy.array([
x[0], y[0], z[0], 0,
x[1], y[1], z[1], 0,
x[2], y[2], z[2], 0,
-numpy.dot(x, eye), -numpy.dot(y, eye), -numpy.dot(z, eye), 1], numpy.float32)
def rotX(a):
sin = math.sin(a)
cos = math.cos(a)
return numpy.array([
1, 0, 0, 0,
0, cos, sin, 0,
0, -sin, cos, 0,
0, 0, 0, 1], numpy.float32)
def rotY(a):
sin = math.sin(a)
cos = math.cos(a)
return numpy.array([
cos, 0, -sin, 0,
0, 1, 0, 0,
sin, 0, cos, 0,
0, 0, 0, 1], numpy.float32)
def rotZ(a):
sin = math.sin(a)
cos = math.cos(a)
return numpy.array([
cos, sin, 0, 0,
-sin, cos, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1], numpy.float32)
def transpose(a):
return numpy.array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
a[0], a[1], a[2], 1], numpy.float32)
def mIdentity():
return numpy.array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1], numpy.float32)
def mMultply(a, b):
return numpy.array(
numpy.matrix(a.reshape((4,4))) * numpy.matrix(b.reshape((4,4))), numpy.float32)
def main():
w, h = 350, 250
pygame.init()
pygame.display.set_mode((w, h), pygame.OPENGL|pygame.DOUBLEBUF)
pygame.display.set_caption('pygame de GLSL')
program = compileProgram(
compileShader(vs, GL_VERTEX_SHADER),
compileShader(fs, GL_FRAGMENT_SHADER))
glUseProgram(program)
position = [
-1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1,
-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
-1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1,
-1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1,
1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1 ]
normal = [
0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 ]
uv = [
0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1 ]
color = numpy.ones(72)
indeces = [
0, 2, 1, 0, 3, 2,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 15, 14, 12, 14, 13,
16, 17, 18, 16, 18, 19,
20, 23, 22, 20, 22, 21 ]
data = [
{'name': 'position', 'stride': 3, 'vertices': position},
{'name': 'normal', 'stride': 3, 'vertices': normal},
{'name': 'color', 'stride': 3, 'vertices': color},
{'name': 'uv', 'stride': 2, 'vertices': uv}]
for d in data:
vertices = numpy.array(d['vertices'], numpy.float32)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, 4 * len(vertices), vertices, GL_STATIC_DRAW)
attr = glGetAttribLocation(program, d['name'])
glVertexAttribPointer(attr, d['stride'], GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(attr)
indeces = numpy.array(indeces, numpy.ushort)
ibo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * len(indeces), indeces, GL_STATIC_DRAW)
size = len(indeces)
uniform = {
'pMatrix': glGetUniformLocation(program, 'pMatrix'),
'vMatrix': glGetUniformLocation(program, 'vMatrix'),
'mMatrix': glGetUniformLocation(program, 'mMatrix'),
}
glUniformMatrix4fv(uniform['pMatrix'], 1, GL_FALSE, perspective(45, w / h, 0.1, 100))
glUniformMatrix4fv(uniform['vMatrix'], 1, GL_FALSE, lookAt([0, 0, 6], [0, 0, 0], [0, 1, 0]))
glClearDepth(1)
glClearColor(0, 0, 0, 1)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
clock = pygame.time.Clock()
while True:
clock.tick(60)
t = pygame.time.get_ticks() / 1000
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUniformMatrix4fv(uniform['mMatrix'], 1, GL_FALSE, mMultply(rotX(t*0.2), rotY(t*0.5)))
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT, None)
glUniformMatrix4fv(uniform['mMatrix'], 1, GL_FALSE, mMultply(transpose((1.0, 0.0, 0.0)), rotX(0.5)))
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT, None)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: sys.exit()
if __name__ == '__main__':
main()