Loading space_view3d_virtual_reality/__init__.py 0 → 100644 +193 −0 Changes for space_view3d_virtual_reality/__init__.py: 193 added lines, 0 removed lines. Original line number Diff line number Diff line #====================== BEGIN GPL LICENSE BLOCK ====================== # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #======================= END GPL LICENSE BLOCK ======================== # <pep8 compliant> bl_info = { "name": "Virtual Reality Viewport", "author": "Dalai Felinto", "version": (0, 9), "blender": (2, 7, 5), "location": "Window Menu", "description": "", "warning": "", "wiki_url": "", "tracker_url": "", "category": "3D View"} import bpy from bgl import ( Buffer, GL_INT, GL_RGBA, ) from .opengl_helper import ( calculate_image_size, create_image, create_shader, delete_image, draw_callback_px, resize, ) def get_context_3dview (context): """returns area and space""" screen = context.screen for area in screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'WINDOW': return area, region return None, None def get_space_3dview(context): area = context.area for space in area.spaces: if space.type == 'VIEW_3D': return space return None def get_glsl_shader(): import os folderpath = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(folderpath, 'oculus_dk2.glsl') f = open(filepath, 'r') data = f.read() f.close() return data class VirtualRealityViewportOperator(bpy.types.Operator): """""" bl_idname = "view3d.virtual_reality_toggle" bl_label = "Toggle Virtual Reality Mode" bl_description = "" _enabled = True _timer = None def modal(self, context, event): if event.type == 'ESC': return self.cancel(context) if event.type == 'TIMER': # bug, waiting for fix: "[#31026] context.region broken after QuadView on + off" # http://projects.blender.org/tracker/index.php?func=detail&aid=31026&group_id=9&atid=498 if not context.region or \ not context.space_data or \ context.space_data.type != 'VIEW_3D': return {'PASS_THROUGH'} viewport_shade = context.space_data.viewport_shade self._enabled = (viewport_shade != 'RENDERED') if (self.width != context.region.width) or (self.height != context.region.height): resize(self, context) return {'PASS_THROUGH'} def invoke(self, context, event): """ * Create a fullscreen window with the editor in fullscreen with clean UI. * Views should be on, and this window should have stereo 3d mode set to side-by-side * Also you should lock a camera to the viewport to make sure you always look nicely * Sync the Oculus rotation + translation to the Blender camera * Now the opengl fun ... create a GLSL screen shader to run the warping distortions. """ if context.area.type == 'VIEW_3D': #if bpy.ops.wm.window_fullscreen_toggle.poll(): # bpy.ops.wm.window_fullscreen_toggle() context.scene.render.use_multiview = True context.window.stereo_3d_display.display_mode = 'SIDEBYSIDE' #if bpy.ops.screen.screen_full_area.poll(): # bpy.ops.screen.screen_full_area(use_hide_panels=True) if bpy.ops.view3d.view_all.poll(): bpy.ops.view3d.view_all() space = get_space_3dview(context) space.show_only_render = True space.stereo_3d_camera = 'S3D' #bpy.v3d = get_context_3dview(context) #bpy.space = space bpy.ops.view3d.viewnumpad(type='CAMERA') self._timer = context.window_manager.event_timer_add(0.1, context.window) self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) self.viewport = Buffer(GL_INT, 4) self.width = context.region.width self.height = context.region.height # power of two dimensions self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # images to dump the screen buffers self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) # glsl shaders fragment_shader = get_glsl_shader() self.program_shader = create_shader(fragment_shader) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") return {'CANCELLED'} def cancel(self, context): if self._handle: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') del self._handle if self._timer: context.window_manager.event_timer_remove(self._timer) del self._timer self.quit() return {'CANCELLED'} def quit(self): """garbage colect""" if self.color_id: delete_image(self.color_id) def register(): bpy.utils.register_module(__name__) def unregister(): bpy.utils.unregister_module(__name__) if __name__ == '__main__': register() space_view3d_virtual_reality/oculus_dk2.glsl 0 → 100644 +78 −0 Changes for space_view3d_virtual_reality/oculus_dk2.glsl: 78 added lines, 0 removed lines. Original line number Diff line number Diff line uniform sampler2D bgl_RenderedTexture; uniform float bgl_RenderedTextureWidth; uniform float bgl_RenderedTextureHeight; const vec4 kappa = vec4(1.0,0.7,1.0,1.0); float screen_width = bgl_RenderedTextureWidth; float screen_height = bgl_RenderedTextureHeight; const float scaleFactor = 0.85; const vec2 leftCenter = vec2(0.25, 0.5); const vec2 rightCenter = vec2(0.75, 0.5); const float separation = -0.00; // Scales input texture coordinates for distortion. vec2 hmdWarp(vec2 LensCenter, vec2 texCoord, vec2 Scale, vec2 ScaleIn, float eta) { vec2 theta = (texCoord - LensCenter) * ScaleIn; float rSq = theta.x * theta.x + theta.y * theta.y; vec2 rvector = theta * (kappa.x + kappa.y * rSq + kappa.z * rSq * rSq + kappa.w * rSq * rSq * rSq); vec2 tc = LensCenter + Scale * eta * rvector; return tc; } bool validate(vec2 tc, int left_eye) { //keep within bounds of texture if ((left_eye == 1 && (tc.x < 0.0 || tc.x > 0.5)) || (left_eye == 0 && (tc.x < 0.5 || tc.x > 1.0)) || tc.y < 0.0 || tc.y > 1.0) { return false; } return true; } void main() { vec2 screen = vec2(screen_width, screen_height); vec3 eta = vec3(1.00,1.018,1.042); //refraction indices float as = float(screen.x / 2.0) / float(screen.y); vec2 Scale = vec2(0.47, as); vec2 ScaleIn = vec2(2.0 * scaleFactor, 1.0 / as * scaleFactor); vec2 texCoord = (gl_TexCoord[0].st); vec2 texCoordSeparated = texCoord; vec2 tcR = vec2(0.0); vec2 tcG = vec2(0.0); vec2 tcB = vec2(0.0); vec4 color = vec4(0.0); if (texCoord.x < 0.5) { texCoordSeparated.x += separation; tcR = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.r ); tcG = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.g ); tcB = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.b ); color.r = texture2D(bgl_RenderedTexture, tcR).r; color.g = texture2D(bgl_RenderedTexture, tcG).g; color.b = texture2D(bgl_RenderedTexture, tcB).b; if (!validate(tcR, 1)) color = vec4(0.0); } else { texCoordSeparated.x -= separation; tcR = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.r ); tcG = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.g ); tcB = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.b ); color.r = texture2D(bgl_RenderedTexture, tcR).r; color.g = texture2D(bgl_RenderedTexture, tcG).g; color.b = texture2D(bgl_RenderedTexture, tcB).b; if (!validate(tcR, 0)) color = vec4(0.0); } gl_FragColor = color; } space_view3d_virtual_reality/opengl_helper.py 0 → 100644 +286 −0 Changes for space_view3d_virtual_reality/opengl_helper.py: 286 added lines, 0 removed lines. Original line number Diff line number Diff line import bpy from bgl import * from mathutils import Matrix, Euler SpaceView3D = bpy.types.SpaceView3D callback_handle = [] fragment_shader =""" #version 120 uniform sampler2D color_buffer; void main(void) { vec2 coords = gl_TexCoord[0].st; vec4 foreground = texture2D(color_buffer, coords); gl_FragColor = mix(foreground, vec4(1.0, 0.0, 0.0, 1.0), 0.5); } """ # ################## # GLSL Debug # ################## def print_shader_errors(shader): """""" log = Buffer(GL_BYTE, len(fragment_shader)) length = Buffer(GL_INT, 1) print('Shader Code:') glGetShaderSource(shader, len(log), length, log) line = 1 msg = " 1 " for i in range(length[0]): if chr(log[i-1]) == '\n': line += 1 msg += "%3d %s" %(line, chr(log[i])) else: msg += chr(log[i]) print(msg) glGetShaderInfoLog(shader, len(log), length, log) print("Error in GLSL Shader:\n") msg = "" for i in range(length[0]): msg += chr(log[i]) print (msg) def print_program_errors(program): """""" log = Buffer(GL_BYTE, 1024) length = Buffer(GL_INT, 1) glGetProgramInfoLog(program, len(log), length, log) print("Error in GLSL Program:\n") msg = "" for i in range(length[0]): msg += chr(log[i]) print (msg) # ###################### # OpenGL Image Routines # ###################### def resize(self, context): """we can run every frame or only when width/height change""" # remove old textures self.quit() self.width = context.region.width self.height = context.region.height self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # image to dump screen self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) def calculate_image_size(width, height): """get a power of 2 size""" buffer_width, buffer_height = 0,0 i = 0 while (1 << i) <= width:i+= 1 buffer_width = 1 << i i = 0 while (1 << i) <= height:i+= 1 buffer_height = 1 << i return buffer_width, buffer_height def update_image(tex_id, viewport, target=GL_RGBA, texture=GL_TEXTURE0): """copy the current buffer to the image""" glActiveTexture(texture) glBindTexture(GL_TEXTURE_2D, tex_id) glCopyTexImage2D(GL_TEXTURE_2D, 0, target, viewport[0], viewport[1], viewport[2], viewport[3], 0) def create_image(width, height, target=GL_RGBA): """create an empty image, dimensions pow2""" if target == GL_RGBA: target, internal_format, dimension = GL_RGBA, GL_RGB, 3 else: target, internal_format, dimension = GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, 1 null_buffer = Buffer(GL_BYTE, [(width + 1) * (height + 1) * dimension]) id_buf = Buffer(GL_INT, 1) glGenTextures(1, id_buf) tex_id = id_buf.to_list()[0] glBindTexture(GL_TEXTURE_2D, tex_id) glTexImage2D(GL_TEXTURE_2D, 0, target, width, height, 0, internal_format, GL_UNSIGNED_BYTE, null_buffer) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) if target == GL_DEPTH_COMPONENT32: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE) glCopyTexImage2D(GL_TEXTURE_2D, 0, target, 0, 0, width, height, 0) glBindTexture(GL_TEXTURE_2D, 0) del null_buffer return tex_id def delete_image(tex_id): """clear created image""" id_buf = Buffer(GL_INT, 1) id_buf.to_list()[0] = tex_id if glIsTexture(tex_id): glDeleteTextures(1, id_buf) # ################## # GLSL Screen Shader # ################## def create_shader(source, program=None, type=GL_FRAGMENT_SHADER): """""" if program == None: program = glCreateProgram() shader = glCreateShader(type) glShaderSource(shader, source) glCompileShader(shader) success = Buffer(GL_INT, 1) glGetShaderiv(shader, GL_COMPILE_STATUS, success) if not success[0]: print_shader_errors(shader) glAttachShader(program, shader) glLinkProgram(program) return program def setup_uniforms(program, color_id, width, height): """""" uniform = glGetUniformLocation(program, "bgl_RenderedTexture") glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, color_id) if uniform != -1: glUniform1i(uniform, 0) uniform = glGetUniformLocation(program, "bgl_RenderedTextureWidth") if uniform != -1: glUniform1f(uniform, width) uniform = glGetUniformLocation(program, "bgl_RenderedTextureHeight") if uniform != -1: glUniform1f(uniform, height) def bindcode(image): """load the image in the graphic card if necessary""" image.gl_touch(GL_NEAREST) return image.bindcode # ################## # Drawing Routines # ################## def view_setup(): glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glMatrixMode(GL_TEXTURE) glPushMatrix() glLoadIdentity() glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glOrtho(-1, 1, -1, 1, -20, 20) gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0) def view_reset(viewport): # Get texture info glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_TEXTURE) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glViewport(viewport[0], viewport[1], viewport[2], viewport[3]) def draw_rectangle(zed=0.0): texco = [(1, 1), (0, 1), (0, 0), (1,0)] verco = [(1.0, 1.0), (-1.0, 1.0), (-1.0, -1.0), ( 1.0, -1.0)] glPolygonMode(GL_FRONT_AND_BACK , GL_FILL) glBegin(GL_QUADS) for i in range(4): glColor4f(1.0, 1.0, 1.0, 0.0) glTexCoord3f(texco[i][0], texco[i][1], zed) glVertex2f(verco[i][0], verco[i][1]) glEnd() def draw_callback_px(self, context): """core function""" if not self._enabled: return act_tex = Buffer(GL_INT, 1) glGetIntegerv(GL_ACTIVE_TEXTURE, act_tex) glGetIntegerv(GL_VIEWPORT, self.viewport) # (1) dump buffer in texture update_image(self.color_id, self.viewport, GL_RGBA, GL_TEXTURE0) # (3) run screenshader glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) pjm = Buffer(GL_FLOAT, 16) mvm = Buffer(GL_FLOAT, 16) cam_pos = context.scene.camera.location.copy() glMatrixMode(GL_MODELVIEW) glTranslatef(cam_pos[0], cam_pos[1], cam_pos[2]) glGetFloatv(GL_PROJECTION_MATRIX, pjm) glGetFloatv(GL_MODELVIEW_MATRIX, mvm) # set identity matrices view_setup() # calculate matrixes projection_matrix = Matrix((pjm[0:4], pjm[4:8], pjm[8:12], pjm[12:16])).transposed() modelview_matrix = Matrix((mvm[0:4], mvm[4:8], mvm[8:12], mvm[12:16])).transposed() modelviewprojinv_matrix = (projection_matrix * modelview_matrix).inverted() modelviewprojinv_mat = Buffer(GL_FLOAT, (4,4), modelviewprojinv_matrix.transposed()) glUseProgram(self.program_shader) setup_uniforms(self.program_shader, self.color_id, self.width, self.height) draw_rectangle() # (4) restore opengl defaults glUseProgram(0) glActiveTexture(act_tex[0]) glBindTexture(GL_TEXTURE_2D, 0) view_reset(self.viewport) glMatrixMode(GL_MODELVIEW) glTranslatef(-cam_pos[0], -cam_pos[1], -cam_pos[2]) Loading
space_view3d_virtual_reality/__init__.py 0 → 100644 +193 −0 Changes for space_view3d_virtual_reality/__init__.py: 193 added lines, 0 removed lines. Original line number Diff line number Diff line #====================== BEGIN GPL LICENSE BLOCK ====================== # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #======================= END GPL LICENSE BLOCK ======================== # <pep8 compliant> bl_info = { "name": "Virtual Reality Viewport", "author": "Dalai Felinto", "version": (0, 9), "blender": (2, 7, 5), "location": "Window Menu", "description": "", "warning": "", "wiki_url": "", "tracker_url": "", "category": "3D View"} import bpy from bgl import ( Buffer, GL_INT, GL_RGBA, ) from .opengl_helper import ( calculate_image_size, create_image, create_shader, delete_image, draw_callback_px, resize, ) def get_context_3dview (context): """returns area and space""" screen = context.screen for area in screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'WINDOW': return area, region return None, None def get_space_3dview(context): area = context.area for space in area.spaces: if space.type == 'VIEW_3D': return space return None def get_glsl_shader(): import os folderpath = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(folderpath, 'oculus_dk2.glsl') f = open(filepath, 'r') data = f.read() f.close() return data class VirtualRealityViewportOperator(bpy.types.Operator): """""" bl_idname = "view3d.virtual_reality_toggle" bl_label = "Toggle Virtual Reality Mode" bl_description = "" _enabled = True _timer = None def modal(self, context, event): if event.type == 'ESC': return self.cancel(context) if event.type == 'TIMER': # bug, waiting for fix: "[#31026] context.region broken after QuadView on + off" # http://projects.blender.org/tracker/index.php?func=detail&aid=31026&group_id=9&atid=498 if not context.region or \ not context.space_data or \ context.space_data.type != 'VIEW_3D': return {'PASS_THROUGH'} viewport_shade = context.space_data.viewport_shade self._enabled = (viewport_shade != 'RENDERED') if (self.width != context.region.width) or (self.height != context.region.height): resize(self, context) return {'PASS_THROUGH'} def invoke(self, context, event): """ * Create a fullscreen window with the editor in fullscreen with clean UI. * Views should be on, and this window should have stereo 3d mode set to side-by-side * Also you should lock a camera to the viewport to make sure you always look nicely * Sync the Oculus rotation + translation to the Blender camera * Now the opengl fun ... create a GLSL screen shader to run the warping distortions. """ if context.area.type == 'VIEW_3D': #if bpy.ops.wm.window_fullscreen_toggle.poll(): # bpy.ops.wm.window_fullscreen_toggle() context.scene.render.use_multiview = True context.window.stereo_3d_display.display_mode = 'SIDEBYSIDE' #if bpy.ops.screen.screen_full_area.poll(): # bpy.ops.screen.screen_full_area(use_hide_panels=True) if bpy.ops.view3d.view_all.poll(): bpy.ops.view3d.view_all() space = get_space_3dview(context) space.show_only_render = True space.stereo_3d_camera = 'S3D' #bpy.v3d = get_context_3dview(context) #bpy.space = space bpy.ops.view3d.viewnumpad(type='CAMERA') self._timer = context.window_manager.event_timer_add(0.1, context.window) self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) self.viewport = Buffer(GL_INT, 4) self.width = context.region.width self.height = context.region.height # power of two dimensions self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # images to dump the screen buffers self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) # glsl shaders fragment_shader = get_glsl_shader() self.program_shader = create_shader(fragment_shader) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") return {'CANCELLED'} def cancel(self, context): if self._handle: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') del self._handle if self._timer: context.window_manager.event_timer_remove(self._timer) del self._timer self.quit() return {'CANCELLED'} def quit(self): """garbage colect""" if self.color_id: delete_image(self.color_id) def register(): bpy.utils.register_module(__name__) def unregister(): bpy.utils.unregister_module(__name__) if __name__ == '__main__': register()
space_view3d_virtual_reality/oculus_dk2.glsl 0 → 100644 +78 −0 Changes for space_view3d_virtual_reality/oculus_dk2.glsl: 78 added lines, 0 removed lines. Original line number Diff line number Diff line uniform sampler2D bgl_RenderedTexture; uniform float bgl_RenderedTextureWidth; uniform float bgl_RenderedTextureHeight; const vec4 kappa = vec4(1.0,0.7,1.0,1.0); float screen_width = bgl_RenderedTextureWidth; float screen_height = bgl_RenderedTextureHeight; const float scaleFactor = 0.85; const vec2 leftCenter = vec2(0.25, 0.5); const vec2 rightCenter = vec2(0.75, 0.5); const float separation = -0.00; // Scales input texture coordinates for distortion. vec2 hmdWarp(vec2 LensCenter, vec2 texCoord, vec2 Scale, vec2 ScaleIn, float eta) { vec2 theta = (texCoord - LensCenter) * ScaleIn; float rSq = theta.x * theta.x + theta.y * theta.y; vec2 rvector = theta * (kappa.x + kappa.y * rSq + kappa.z * rSq * rSq + kappa.w * rSq * rSq * rSq); vec2 tc = LensCenter + Scale * eta * rvector; return tc; } bool validate(vec2 tc, int left_eye) { //keep within bounds of texture if ((left_eye == 1 && (tc.x < 0.0 || tc.x > 0.5)) || (left_eye == 0 && (tc.x < 0.5 || tc.x > 1.0)) || tc.y < 0.0 || tc.y > 1.0) { return false; } return true; } void main() { vec2 screen = vec2(screen_width, screen_height); vec3 eta = vec3(1.00,1.018,1.042); //refraction indices float as = float(screen.x / 2.0) / float(screen.y); vec2 Scale = vec2(0.47, as); vec2 ScaleIn = vec2(2.0 * scaleFactor, 1.0 / as * scaleFactor); vec2 texCoord = (gl_TexCoord[0].st); vec2 texCoordSeparated = texCoord; vec2 tcR = vec2(0.0); vec2 tcG = vec2(0.0); vec2 tcB = vec2(0.0); vec4 color = vec4(0.0); if (texCoord.x < 0.5) { texCoordSeparated.x += separation; tcR = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.r ); tcG = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.g ); tcB = hmdWarp(leftCenter, texCoordSeparated, Scale, ScaleIn, eta.b ); color.r = texture2D(bgl_RenderedTexture, tcR).r; color.g = texture2D(bgl_RenderedTexture, tcG).g; color.b = texture2D(bgl_RenderedTexture, tcB).b; if (!validate(tcR, 1)) color = vec4(0.0); } else { texCoordSeparated.x -= separation; tcR = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.r ); tcG = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.g ); tcB = hmdWarp(rightCenter, texCoordSeparated, Scale, ScaleIn, eta.b ); color.r = texture2D(bgl_RenderedTexture, tcR).r; color.g = texture2D(bgl_RenderedTexture, tcG).g; color.b = texture2D(bgl_RenderedTexture, tcB).b; if (!validate(tcR, 0)) color = vec4(0.0); } gl_FragColor = color; }
space_view3d_virtual_reality/opengl_helper.py 0 → 100644 +286 −0 Changes for space_view3d_virtual_reality/opengl_helper.py: 286 added lines, 0 removed lines. Original line number Diff line number Diff line import bpy from bgl import * from mathutils import Matrix, Euler SpaceView3D = bpy.types.SpaceView3D callback_handle = [] fragment_shader =""" #version 120 uniform sampler2D color_buffer; void main(void) { vec2 coords = gl_TexCoord[0].st; vec4 foreground = texture2D(color_buffer, coords); gl_FragColor = mix(foreground, vec4(1.0, 0.0, 0.0, 1.0), 0.5); } """ # ################## # GLSL Debug # ################## def print_shader_errors(shader): """""" log = Buffer(GL_BYTE, len(fragment_shader)) length = Buffer(GL_INT, 1) print('Shader Code:') glGetShaderSource(shader, len(log), length, log) line = 1 msg = " 1 " for i in range(length[0]): if chr(log[i-1]) == '\n': line += 1 msg += "%3d %s" %(line, chr(log[i])) else: msg += chr(log[i]) print(msg) glGetShaderInfoLog(shader, len(log), length, log) print("Error in GLSL Shader:\n") msg = "" for i in range(length[0]): msg += chr(log[i]) print (msg) def print_program_errors(program): """""" log = Buffer(GL_BYTE, 1024) length = Buffer(GL_INT, 1) glGetProgramInfoLog(program, len(log), length, log) print("Error in GLSL Program:\n") msg = "" for i in range(length[0]): msg += chr(log[i]) print (msg) # ###################### # OpenGL Image Routines # ###################### def resize(self, context): """we can run every frame or only when width/height change""" # remove old textures self.quit() self.width = context.region.width self.height = context.region.height self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # image to dump screen self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) def calculate_image_size(width, height): """get a power of 2 size""" buffer_width, buffer_height = 0,0 i = 0 while (1 << i) <= width:i+= 1 buffer_width = 1 << i i = 0 while (1 << i) <= height:i+= 1 buffer_height = 1 << i return buffer_width, buffer_height def update_image(tex_id, viewport, target=GL_RGBA, texture=GL_TEXTURE0): """copy the current buffer to the image""" glActiveTexture(texture) glBindTexture(GL_TEXTURE_2D, tex_id) glCopyTexImage2D(GL_TEXTURE_2D, 0, target, viewport[0], viewport[1], viewport[2], viewport[3], 0) def create_image(width, height, target=GL_RGBA): """create an empty image, dimensions pow2""" if target == GL_RGBA: target, internal_format, dimension = GL_RGBA, GL_RGB, 3 else: target, internal_format, dimension = GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, 1 null_buffer = Buffer(GL_BYTE, [(width + 1) * (height + 1) * dimension]) id_buf = Buffer(GL_INT, 1) glGenTextures(1, id_buf) tex_id = id_buf.to_list()[0] glBindTexture(GL_TEXTURE_2D, tex_id) glTexImage2D(GL_TEXTURE_2D, 0, target, width, height, 0, internal_format, GL_UNSIGNED_BYTE, null_buffer) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) if target == GL_DEPTH_COMPONENT32: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE) glCopyTexImage2D(GL_TEXTURE_2D, 0, target, 0, 0, width, height, 0) glBindTexture(GL_TEXTURE_2D, 0) del null_buffer return tex_id def delete_image(tex_id): """clear created image""" id_buf = Buffer(GL_INT, 1) id_buf.to_list()[0] = tex_id if glIsTexture(tex_id): glDeleteTextures(1, id_buf) # ################## # GLSL Screen Shader # ################## def create_shader(source, program=None, type=GL_FRAGMENT_SHADER): """""" if program == None: program = glCreateProgram() shader = glCreateShader(type) glShaderSource(shader, source) glCompileShader(shader) success = Buffer(GL_INT, 1) glGetShaderiv(shader, GL_COMPILE_STATUS, success) if not success[0]: print_shader_errors(shader) glAttachShader(program, shader) glLinkProgram(program) return program def setup_uniforms(program, color_id, width, height): """""" uniform = glGetUniformLocation(program, "bgl_RenderedTexture") glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, color_id) if uniform != -1: glUniform1i(uniform, 0) uniform = glGetUniformLocation(program, "bgl_RenderedTextureWidth") if uniform != -1: glUniform1f(uniform, width) uniform = glGetUniformLocation(program, "bgl_RenderedTextureHeight") if uniform != -1: glUniform1f(uniform, height) def bindcode(image): """load the image in the graphic card if necessary""" image.gl_touch(GL_NEAREST) return image.bindcode # ################## # Drawing Routines # ################## def view_setup(): glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glMatrixMode(GL_TEXTURE) glPushMatrix() glLoadIdentity() glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glOrtho(-1, 1, -1, 1, -20, 20) gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0) def view_reset(viewport): # Get texture info glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_TEXTURE) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glViewport(viewport[0], viewport[1], viewport[2], viewport[3]) def draw_rectangle(zed=0.0): texco = [(1, 1), (0, 1), (0, 0), (1,0)] verco = [(1.0, 1.0), (-1.0, 1.0), (-1.0, -1.0), ( 1.0, -1.0)] glPolygonMode(GL_FRONT_AND_BACK , GL_FILL) glBegin(GL_QUADS) for i in range(4): glColor4f(1.0, 1.0, 1.0, 0.0) glTexCoord3f(texco[i][0], texco[i][1], zed) glVertex2f(verco[i][0], verco[i][1]) glEnd() def draw_callback_px(self, context): """core function""" if not self._enabled: return act_tex = Buffer(GL_INT, 1) glGetIntegerv(GL_ACTIVE_TEXTURE, act_tex) glGetIntegerv(GL_VIEWPORT, self.viewport) # (1) dump buffer in texture update_image(self.color_id, self.viewport, GL_RGBA, GL_TEXTURE0) # (3) run screenshader glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) pjm = Buffer(GL_FLOAT, 16) mvm = Buffer(GL_FLOAT, 16) cam_pos = context.scene.camera.location.copy() glMatrixMode(GL_MODELVIEW) glTranslatef(cam_pos[0], cam_pos[1], cam_pos[2]) glGetFloatv(GL_PROJECTION_MATRIX, pjm) glGetFloatv(GL_MODELVIEW_MATRIX, mvm) # set identity matrices view_setup() # calculate matrixes projection_matrix = Matrix((pjm[0:4], pjm[4:8], pjm[8:12], pjm[12:16])).transposed() modelview_matrix = Matrix((mvm[0:4], mvm[4:8], mvm[8:12], mvm[12:16])).transposed() modelviewprojinv_matrix = (projection_matrix * modelview_matrix).inverted() modelviewprojinv_mat = Buffer(GL_FLOAT, (4,4), modelviewprojinv_matrix.transposed()) glUseProgram(self.program_shader) setup_uniforms(self.program_shader, self.color_id, self.width, self.height) draw_rectangle() # (4) restore opengl defaults glUseProgram(0) glActiveTexture(act_tex[0]) glBindTexture(GL_TEXTURE_2D, 0) view_reset(self.viewport) glMatrixMode(GL_MODELVIEW) glTranslatef(-cam_pos[0], -cam_pos[1], -cam_pos[2])