Created
October 29, 2015 03:43
-
-
Save xvedejas/b37e0babbf6c0f9c9ffa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# This is a sample bit of code that shows how to draw arbitrary axis-aligned | |
# boxes in 3D space. | |
# based on: https://gist.github.com/binarycrusader/5823716a1da5f0273504 | |
import ctypes | |
import numpy as np | |
import time | |
from OpenGL import GL, GLU, GLUT | |
from OpenGL.GL import shaders | |
from OpenGL.arrays import vbo | |
import sdl2, sdl2.sdlimage, sdl2.ext | |
def sdl_load(resource): | |
image = sdl2.sdlimage.IMG_Load(resource) | |
try: | |
image.contents # Gives null pointer exception on failure | |
except ValueError: | |
print(sdl2.SDL_GetError(image)) | |
exit(1) | |
return image | |
def gl_load(path): | |
img = sdl_load(path).contents | |
array = sdl2.ext.pixels3d(img) | |
mode = GL.GL_RGBA | |
texture = GL.glGenTextures(1) | |
GL.glActiveTexture(GL.GL_TEXTURE0) | |
GL.glBindTexture(GL.GL_TEXTURE_2D, texture) | |
GL.glTexImage2D(GL.GL_TEXTURE_2D, 0,mode , img.w, img.h, 0, mode, GL.GL_UNSIGNED_BYTE, array) | |
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST) | |
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) | |
return texture | |
class Box(): | |
# This vertex data defines a cube (minus the bottom face) in terms of a | |
# strip of triangles | |
vertex_data = np.array([ | |
# X Y Z U V | |
0, 0, -1, 2/3, 2/3, | |
1, 0, 0, 1/3, 1, | |
0, 0, 0, 2/3, 1, | |
1, 0, 1, 1/3, 2/3, | |
1, 0, 0, 1/3, 1, | |
0, 0, 1, 2/3, 2/3, | |
1, 1, 1, 1/3, 1/3, | |
1, 0, 0, 0, 2/3, | |
1, 0, 1, 1/3, 2/3, | |
1, 1, 0, 0, 1/3, | |
1, 0, 0, 0, 2/3, | |
1, 1, 1, 1/3, 1/3, | |
0, 1, 1, 2/3, 1/3, | |
1, 0, 1, 1/3, 2/3, | |
0, 0, 1, 2/3, 2/3, | |
1, 1, 1, 1/3, 1/3, | |
1, 0, 1, 1/3, 2/3, | |
0, 1, 1, 2/3, 1/3, | |
0, 1, 0, 1, 1/3, | |
0, 0, 1, 2/3, 2/3, | |
0, 0, 0, 1, 2/3, | |
0, 1, 1, 2/3, 1/3, | |
0, 0, 1, 2/3, 2/3, | |
0, 1, 0, 1, 1/3, | |
0, 1, 0, 2/3, 0, | |
1, 1, 1, 1/3, 1/3, | |
0, 1, 1, 2/3, 1/3, | |
1, 1, 0, 1/3, 0, | |
1, 1, 1, 1/3, 1/3, | |
0, 1, 0, 2/3, 0, | |
], dtype=np.float32) | |
def __init__(self, position, size, texture, shader_program): | |
self.position = position | |
self.size = size | |
x, y, z = position | |
w, l, h = size | |
#self.matrix = np.matrix([[1, 0, 0, x], [0, 1, 0, y], [0, 0, 1, z], [0, 0, 0, 1]], dtype=np.float32) | |
self.matrix = np.matrix([[w, 0, 0, 0], [0, l, 0, 0], [0, 0, h, 0], [x, y, z, 1]], dtype=np.float32) | |
self.shader_program = shader_program | |
# Core OpenGL requires that at least one OpenGL vertex array be bound | |
self.VAO = GL.glGenVertexArrays(1) | |
GL.glBindVertexArray(self.VAO) | |
# Need VBO for triangle vertices and texture UV coordinates | |
self.VBO = GL.glGenBuffers(1) | |
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.VBO) | |
GL.glBufferData(GL.GL_ARRAY_BUFFER, self.vertex_data.nbytes, self.vertex_data, GL.GL_STATIC_DRAW) | |
# enable array and set up data | |
positionAttrib = GL.glGetAttribLocation(self.shader_program, 'position') | |
coordsAttrib = GL.glGetAttribLocation(self.shader_program, 'texCoords') | |
GL.glEnableVertexAttribArray(0) | |
GL.glEnableVertexAttribArray(1) | |
GL.glVertexAttribPointer(positionAttrib, 3, GL.GL_FLOAT, GL.GL_FALSE, 4*5, None) | |
GL.glVertexAttribPointer(coordsAttrib, 2, GL.GL_FLOAT, GL.GL_TRUE, 4*5, ctypes.c_void_p(4*3)) | |
self.texture = texture | |
self.texUnitUniform = GL.glGetUniformLocation(self.shader_program, 'texUnit') | |
# Finished | |
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) | |
GL.glBindVertexArray(0) | |
def render(self, matrix): | |
GL.glUseProgram(self.shader_program) | |
MVP = GL.glGetUniformLocation(self.shader_program, "MVPMatrix"); | |
GL.glUniformMatrix4fv(MVP, 1, GL.GL_FALSE, self.matrix * matrix); | |
try: | |
# Activate texture | |
GL.glActiveTexture(GL.GL_TEXTURE0) | |
GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture) | |
GL.glUniform1i(self.texUnitUniform, 0) | |
# Activate array | |
GL.glBindVertexArray(self.VAO) | |
# draw triangle | |
GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(self.vertex_data)//5) | |
finally: | |
GL.glBindVertexArray(0) | |
GL.glUseProgram(0) | |
class PipelineGL(): | |
def __init__(self): | |
return | |
def __enter__(self): | |
sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) | |
sdl2.sdlttf.TTF_Init() | |
self.window = sdl2.SDL_CreateWindow(b"demo", | |
sdl2.SDL_WINDOWPOS_UNDEFINED, | |
sdl2.SDL_WINDOWPOS_UNDEFINED, | |
800, 600, | |
sdl2.SDL_WINDOW_OPENGL) | |
self.surface = sdl2.SDL_GetWindowSurface(self.window) | |
# Change this if using hardware acceleration | |
self.renderer = sdl2.SDL_CreateSoftwareRenderer(self.surface, -1, 0) | |
# Force OpenGL 3.3 'core' context. Must set *before* creating GL context | |
sdl2.video.SDL_GL_SetAttribute(sdl2.video.SDL_GL_CONTEXT_MAJOR_VERSION, 3) | |
sdl2.video.SDL_GL_SetAttribute(sdl2.video.SDL_GL_CONTEXT_MINOR_VERSION, 3) | |
sdl2.video.SDL_GL_SetAttribute(sdl2.video.SDL_GL_CONTEXT_PROFILE_MASK, | |
sdl2.video.SDL_GL_CONTEXT_PROFILE_CORE) | |
self.context = sdl2.SDL_GL_CreateContext(self.window) | |
# Setup GL shaders, data, etc. | |
vertexShader = shaders.compileShader(""" | |
#version 330 | |
layout (location=0) in vec3 position; | |
layout (location=1) in vec2 texCoords; | |
uniform mat4 MVPMatrix; | |
out vec2 theCoords; | |
void main() | |
{ | |
gl_Position = MVPMatrix * vec4(position, 1); | |
//gl_Position = vec4(position, 1); | |
theCoords = texCoords; | |
} | |
""", GL.GL_VERTEX_SHADER) | |
fragmentShader = shaders.compileShader(""" | |
#version 330 | |
uniform sampler2D texUnit; | |
in vec2 theCoords; | |
out vec4 outputColour; | |
void main() | |
{ | |
outputColour = texture(texUnit, theCoords); | |
} | |
""", GL.GL_FRAGMENT_SHADER) | |
self.shader_program = shaders.compileProgram(vertexShader, fragmentShader) | |
texture = gl_load(b'test.png') | |
self.boxes = [Box((0.0, 1.0, 0.0), (1.0, 1.0, 1.0), texture, self.shader_program), | |
Box((0.0, 0.0, 1.0), (1.0, 1.0, 1.0), texture, self.shader_program), | |
Box((1.0, 0.0, 0.0), (1.0, 1.0, 1.0), texture, self.shader_program),] | |
event = sdl2.SDL_Event() | |
return self | |
def __exit__(self, t, value, traceback): | |
sdl2.SDL_GL_DeleteContext(self.context) | |
sdl2.SDL_DestroyWindow(self.window) | |
sdl2.SDL_Quit() | |
def render(self): | |
GL.glClearColor(0, 0, 0, 1) | |
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) | |
zoom = 0.2 | |
MVP = np.matrix([[zoom, 0, 0, 0], | |
[0, zoom, 0, 0], | |
[0, 0, zoom, 0], | |
[0, 0, 0, 1.0]], | |
dtype=np.float32) | |
#~ a = 135 / 180 * np.pi | |
a = (time.time() % 4) / 2 * np.pi | |
MVP *= np.matrix([[np.cos(a), np.sin(a), 0, 0], | |
[-np.sin(a), np.cos(a), 0, 0], | |
[0, 0, 1, 0], | |
[0, 0, 0, 1]], | |
dtype=np.float32) | |
b = (time.time() % 8) / 4 * np.pi | |
MVP *= np.matrix([[1, 0, 0, 0], | |
[0, np.cos(b), np.sin(b), 0], | |
[0, -np.sin(b), np.cos(b), 0], | |
[0, 0, 0, 1]], | |
dtype=np.float32) | |
for box in self.boxes: | |
box.render(MVP) | |
sdl2.SDL_GL_SwapWindow(self.window) | |
sdl2.SDL_Delay(10) | |
def run(): | |
with PipelineGL() as pgl: | |
running = True | |
while running: | |
## handle events here | |
pgl.render() | |
return 0 | |
if __name__ == "__main__": | |
exit(run()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment