{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "colab_gl.ipynb", "version": "0.3.2", "views": {}, "default_view": {}, "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "accelerator": "GPU" }, "cells": [ { "metadata": { "id": "uDPDN1lSMl5q", "colab_type": "text" }, "cell_type": "markdown", "source": [ "##### Copyright 2018 Google LLC.\n", "\n", "Licensed under the Apache License, Version 2.0 (the \"License\");" ] }, { "metadata": { "id": "Omj0FSZhLMXW", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "BmsGhnakM0ja", "colab_type": "text" }, "cell_type": "markdown", "source": [ "# Using OpenGL with Colab Cloud GPUs\n", "\n", "This notebook demonstrates obtaining OpenGL context on GPU Colab kernels." ] }, { "metadata": { "id": "qxRuD3-WMqh5", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "!pip install -q lucid>=0.2.3\n", "!pip install -q moviepy" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "ZTWpjkyXNPVD", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "import numpy as np\n", "import json\n", "import moviepy.editor as mvp\n", "from lucid.misc.io import show" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "Y_ytjJ-kM8rJ", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 91 }, "outputId": "15ebfd0d-1d23-4297-c1af-762099e9cf71", "executionInfo": { "status": "ok", "timestamp": 1533313817218, "user_tz": -120, "elapsed": 1167, "user": { "displayName": "Alexander Mordvintsev", "photoUrl": "//lh4.googleusercontent.com/-n1VSNn_ErxQ/AAAAAAAAAAI/AAAAAAAAFpk/BCURumES134/s50-c-k-no/photo.jpg", "userId": "108092561333339272254" } } }, "cell_type": "code", "source": [ "from lucid.misc.gl.glcontext import create_opengl_context\n", "\n", "# Now it's safe to import OpenGL and EGL functions\n", "import OpenGL.GL as gl\n", "\n", "# create_opengl_context() creates GL context that is attached to an\n", "# offscreen surface of specified size. Note that rendering to buffers\n", "# of different size and format is still possible with OpenGL Framebuffers.\n", "#\n", "# Users are expected to directly use EGL calls in case more advanced\n", "# context management is required.\n", "WIDTH, HEIGHT = 640, 480\n", "create_opengl_context((WIDTH, HEIGHT))\n", " \n", "# OpenGL context is available here.\n", "\n", "print(gl.glGetString(gl.GL_VERSION))\n", "print(gl.glGetString(gl.GL_VENDOR)) \n", "print(gl.glGetString(gl.GL_EXTENSIONS))" ], "execution_count": 5, "outputs": [ { "output_type": "stream", "text": [ "b'4.5.0 NVIDIA 384.111'\n", "b'NVIDIA Corporation'\n", "b'GL_AMD_multi_draw_indirect GL_AMD_seamless_cubemap_per_texture GL_ARB_arrays_of_arrays GL_ARB_base_instance GL_ARB_bindless_texture GL_ARB_blend_func_extended GL_ARB_buffer_storage GL_ARB_clear_buffer_object GL_ARB_clear_texture GL_ARB_clip_control GL_ARB_color_buffer_float GL_ARB_compatibility GL_ARB_compressed_texture_pixel_storage GL_ARB_conservative_depth GL_ARB_compute_shader GL_ARB_compute_variable_group_size GL_ARB_conditional_render_inverted GL_ARB_copy_buffer GL_ARB_copy_image GL_ARB_cull_distance GL_ARB_debug_output GL_ARB_depth_buffer_float GL_ARB_depth_clamp GL_ARB_depth_texture GL_ARB_derivative_control GL_ARB_direct_state_access GL_ARB_draw_buffers GL_ARB_draw_buffers_blend GL_ARB_draw_indirect GL_ARB_draw_elements_base_vertex GL_ARB_draw_instanced GL_ARB_enhanced_layouts GL_ARB_ES2_compatibility GL_ARB_ES3_compatibility GL_ARB_ES3_1_compatibility GL_ARB_ES3_2_compatibility GL_ARB_explicit_attrib_location GL_ARB_explicit_uniform_location GL_ARB_fragment_coord_conventions GL_ARB_fragment_layer_viewport GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_fragment_shader GL_ARB_framebuffer_no_attachments GL_ARB_framebuffer_object GL_ARB_framebuffer_sRGB GL_ARB_geometry_shader4 GL_ARB_get_program_binary GL_ARB_get_texture_sub_image GL_ARB_gl_spirv GL_ARB_gpu_shader5 GL_ARB_gpu_shader_fp64 GL_ARB_gpu_shader_int64 GL_ARB_half_float_pixel GL_ARB_half_float_vertex GL_ARB_imaging GL_ARB_indirect_parameters GL_ARB_instanced_arrays GL_ARB_internalformat_query GL_ARB_internalformat_query2 GL_ARB_invalidate_subdata GL_ARB_map_buffer_alignment GL_ARB_map_buffer_range GL_ARB_multi_bind GL_ARB_multi_draw_indirect GL_ARB_multisample GL_ARB_multitexture GL_ARB_occlusion_query GL_ARB_occlusion_query2 GL_ARB_parallel_shader_compile GL_ARB_pipeline_statistics_query GL_ARB_pixel_buffer_object GL_ARB_point_parameters GL_ARB_point_sprite GL_ARB_program_interface_query GL_ARB_provoking_vertex GL_ARB_query_buffer_object GL_ARB_robust_buffer_access_behavior GL_ARB_robustness GL_ARB_sample_shading GL_ARB_sampler_objects GL_ARB_seamless_cube_map GL_ARB_seamless_cubemap_per_texture GL_ARB_separate_shader_objects GL_ARB_shader_atomic_counter_ops GL_ARB_shader_atomic_counters GL_ARB_shader_ballot GL_ARB_shader_bit_encoding GL_ARB_shader_clock GL_ARB_shader_draw_parameters GL_ARB_shader_group_vote GL_ARB_shader_image_load_store GL_ARB_shader_image_size GL_ARB_shader_objects GL_ARB_shader_precision GL_ARB_shader_storage_buffer_object GL_ARB_shader_subroutine GL_ARB_shader_texture_image_samples GL_ARB_shader_texture_lod GL_ARB_shading_language_100 GL_ARB_shading_language_420pack GL_ARB_shading_language_include GL_ARB_shading_language_packing GL_ARB_shadow GL_ARB_sparse_buffer GL_ARB_sparse_texture GL_ARB_stencil_texturing GL_ARB_sync GL_ARB_tessellation_shader GL_ARB_texture_barrier GL_ARB_texture_border_clamp GL_ARB_texture_buffer_object GL_ARB_texture_buffer_object_rgb32 GL_ARB_texture_buffer_range GL_ARB_texture_compression GL_ARB_texture_compression_bptc GL_ARB_texture_compression_rgtc GL_ARB_texture_cube_map GL_ARB_texture_cube_map_array GL_ARB_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar GL_ARB_texture_env_dot3 GL_ARB_texture_float GL_ARB_texture_gather GL_ARB_texture_mirror_clamp_to_edge GL_ARB_texture_mirrored_repeat GL_ARB_texture_multisample GL_ARB_texture_non_power_of_two GL_ARB_texture_query_levels GL_ARB_texture_query_lod GL_ARB_texture_rectangle GL_ARB_texture_rg GL_ARB_texture_rgb10_a2ui GL_ARB_texture_stencil8 GL_ARB_texture_storage GL_ARB_texture_storage_multisample GL_ARB_texture_swizzle GL_ARB_texture_view GL_ARB_timer_query GL_ARB_transform_feedback2 GL_ARB_transform_feedback3 GL_ARB_transform_feedback_instanced GL_ARB_transform_feedback_overflow_query GL_ARB_transpose_matrix GL_ARB_uniform_buffer_object GL_ARB_vertex_array_bgra GL_ARB_vertex_array_object GL_ARB_vertex_attrib_64bit GL_ARB_vertex_attrib_binding GL_ARB_vertex_buffer_object GL_ARB_vertex_program GL_ARB_vertex_shader GL_ARB_vertex_type_10f_11f_11f_rev GL_ARB_vertex_type_2_10_10_10_rev GL_ARB_viewport_array GL_ARB_window_pos GL_ATI_draw_buffers GL_ATI_texture_float GL_ATI_texture_mirror_once GL_S3_s3tc GL_EXT_texture_env_add GL_EXT_abgr GL_EXT_bgra GL_EXT_bindable_uniform GL_EXT_blend_color GL_EXT_blend_equation_separate GL_EXT_blend_func_separate GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_compiled_vertex_array GL_EXT_Cg_shader GL_EXT_depth_bounds_test GL_EXT_direct_state_access GL_EXT_draw_buffers2 GL_EXT_draw_instanced GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_framebuffer_blit GL_EXT_framebuffer_multisample GL_EXTX_framebuffer_mixed_formats GL_EXT_framebuffer_multisample_blit_scaled GL_EXT_framebuffer_object GL_EXT_framebuffer_sRGB GL_EXT_geometry_shader4 GL_EXT_gpu_program_parameters GL_EXT_gpu_shader4 GL_EXT_multi_draw_arrays GL_EXT_packed_depth_stencil GL_EXT_packed_float GL_EXT_packed_pixels GL_EXT_pixel_buffer_object GL_EXT_point_parameters GL_EXT_polygon_offset_clamp GL_EXT_provoking_vertex GL_EXT_rescale_normal GL_EXT_secondary_color GL_EXT_separate_shader_objects GL_EXT_separate_specular_color GL_EXT_shader_image_load_store GL_EXT_shader_integer_mix GL_EXT_shadow_funcs GL_EXT_stencil_two_side GL_EXT_stencil_wrap GL_EXT_texture3D GL_EXT_texture_array GL_EXT_texture_buffer_object GL_EXT_texture_compression_dxt1 GL_EXT_texture_compression_latc GL_EXT_texture_compression_rgtc GL_EXT_texture_compression_s3tc GL_EXT_texture_cube_map GL_EXT_texture_edge_clamp GL_EXT_texture_env_combine GL_EXT_texture_env_dot3 GL_EXT_texture_filter_anisotropic GL_EXT_texture_integer GL_EXT_texture_lod GL_EXT_texture_lod_bias GL_EXT_texture_mirror_clamp GL_EXT_texture_object GL_EXT_texture_shared_exponent GL_EXT_texture_sRGB GL_EXT_texture_sRGB_decode GL_EXT_texture_storage GL_EXT_texture_swizzle GL_EXT_timer_query GL_EXT_transform_feedback2 GL_EXT_vertex_array GL_EXT_vertex_array_bgra GL_EXT_vertex_attrib_64bit GL_EXT_window_rectangles GL_EXT_import_sync_object GL_NV_robustness_video_memory_purge GL_IBM_rasterpos_clip GL_IBM_texture_mirrored_repeat GL_KHR_context_flush_control GL_KHR_debug GL_EXT_memory_object GL_EXT_memory_object_fd GL_KHR_no_error GL_KHR_robust_buffer_access_behavior GL_KHR_robustness GL_EXT_semaphore GL_EXT_semaphore_fd GL_KTX_buffer_region GL_NV_alpha_to_coverage_dither_control GL_NV_bindless_multi_draw_indirect GL_NV_bindless_multi_draw_indirect_count GL_NV_bindless_texture GL_NV_blend_equation_advanced GL_NV_blend_square GL_NV_command_list GL_NV_compute_program5 GL_NV_conditional_render GL_NV_copy_depth_to_color GL_NV_copy_image GL_NV_depth_buffer_float GL_NV_depth_clamp GL_NV_draw_texture GL_NV_draw_vulkan_image GL_NV_ES1_1_compatibility GL_NV_ES3_1_compatibility GL_NV_explicit_multisample GL_NV_fence GL_NV_float_buffer GL_NV_fog_distance GL_NV_fragment_program GL_NV_fragment_program_option GL_NV_fragment_program2 GL_NV_framebuffer_multisample_coverage GL_NV_geometry_shader4 GL_NV_gpu_program4 GL_NV_internalformat_sample_query GL_NV_gpu_program4_1 GL_NV_gpu_program5 GL_NV_gpu_program5_mem_extended GL_NV_gpu_program_fp64 GL_NV_gpu_shader5 GL_NV_half_float GL_NV_light_max_exponent GL_NV_multisample_coverage GL_NV_multisample_filter_hint GL_NV_occlusion_query GL_NV_packed_depth_stencil GL_NV_parameter_buffer_object GL_NV_parameter_buffer_object2 GL_NV_path_rendering GL_NV_point_sprite GL_NV_primitive_restart GL_NV_register_combiners GL_NV_register_combiners2 GL_NV_shader_atomic_counters GL_NV_shader_atomic_float GL_NV_shader_atomic_int64 GL_NV_shader_buffer_load GL_NV_shader_storage_buffer_object GL_NV_texgen_reflection GL_NV_texture_barrier GL_NV_texture_compression_vtc GL_NV_texture_env_combine4 GL_NV_texture_multisample GL_NV_texture_rectangle GL_NV_texture_shader GL_NV_texture_shader2 GL_NV_texture_shader3 GL_NV_transform_feedback GL_NV_transform_feedback2 GL_NV_uniform_buffer_unified_memory GL_NV_vertex_attrib_integer_64bit GL_NV_vertex_buffer_unified_memory GL_NV_vertex_program GL_NV_vertex_program1_1 GL_NV_vertex_program2 GL_NV_vertex_program2_option GL_NV_vertex_program3 GL_NVX_conditional_render GL_NVX_gpu_memory_info GL_NV_shader_thread_group GL_NV_shader_thread_shuffle GL_KHR_blend_equation_advanced GL_SGIS_generate_mipmap GL_SGIS_texture_lod GL_SGIX_depth_texture GL_SGIX_shadow GL_SUN_slice_accum '\n" ], "name": "stdout" } ] }, { "metadata": { "id": "C11neUqkNRM5", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 500 }, "outputId": "61569eab-4b98-4bf3-b492-fca9a75049e6", "executionInfo": { "status": "ok", "timestamp": 1533314123788, "user_tz": -120, "elapsed": 533, "user": { "displayName": "Alexander Mordvintsev", "photoUrl": "//lh4.googleusercontent.com/-n1VSNn_ErxQ/AAAAAAAAAAI/AAAAAAAAFpk/BCURumES134/s50-c-k-no/photo.jpg", "userId": "108092561333339272254" } } }, "cell_type": "code", "source": [ "# Let's render something!\n", "\n", "gl.glClear(gl.GL_COLOR_BUFFER_BIT)\n", "gl.glBegin(gl.GL_TRIANGLES)\n", "gl.glColor3f(1.0, 0.0, 0.0)\n", "gl.glVertex2f(0, 1)\n", "gl.glColor3f(0.0, 1.0, 0.0)\n", "gl.glVertex2f(-1, -1)\n", "gl.glColor3f(0.0, 0.0, 1.0)\n", "gl.glVertex2f(1, -1)\n", "gl.glEnd()\n", "\n", "# Read the result\n", "img_buf = gl.glReadPixelsub(0, 0, WIDTH, HEIGHT, gl.GL_RGB, gl.GL_UNSIGNED_BYTE)\n", "img = np.frombuffer(img_buf, np.uint8).reshape(HEIGHT, WIDTH, 3)[::-1]\n", "show(img/255.0)" ], "execution_count": 24, "outputs": [ { "output_type": "display_data", "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": { "tags": [] } } ] }, { "metadata": { "id": "n_6rvRbOoeFN", "colab_type": "text" }, "cell_type": "markdown", "source": [ "## Render ShaderToy videos on GPU\n", "\n", "Fetching the source and rendering the [amaizing shader](https://www.shadertoy.com/view/Xtf3Rn) by Kali" ] }, { "metadata": { "id": "at5TlI-eofcE", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "shader_id = 'Xtf3Rn' # https://www.shadertoy.com/view/Xtf3Rn\n", "\n", "shader_json = !curl -s 'https://www.shadertoy.com/shadertoy' \\\n", " -H 'Referer: https://www.shadertoy.com/view/$shader_id' \\\n", " --data 's=%7B%20%22shaders%22%20%3A%20%5B%22$shader_id%22%5D%20%7D'\n", "shader_data = json.loads(''.join(shader_json))[0]\n", "\n", "assert len(shader_data['renderpass']) == 1, \"Only single pass shareds are supported\"\n", "assert len(shader_data['renderpass'][0]['inputs']) == 0, \"Input channels are not supported\"\n", "\n", "shader_code = shader_data['renderpass'][0]['code']" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "ISFwuXaUohSQ", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 500 }, "outputId": "cd9de00f-6461-47fe-be47-3320fd8dcc45", "executionInfo": { "status": "ok", "timestamp": 1533314132617, "user_tz": -120, "elapsed": 1208, "user": { "displayName": "Alexander Mordvintsev", "photoUrl": "//lh4.googleusercontent.com/-n1VSNn_ErxQ/AAAAAAAAAAI/AAAAAAAAFpk/BCURumES134/s50-c-k-no/photo.jpg", "userId": "108092561333339272254" } } }, "cell_type": "code", "source": [ "from OpenGL.GL import shaders\n", "\n", "vertexPositions = np.float32([[-1, -1], [1, -1], [-1, 1], [1, 1]])\n", "VERTEX_SHADER = shaders.compileShader(\"\"\"\n", "#version 330\n", "layout(location = 0) in vec4 position;\n", "out vec2 UV;\n", "void main()\n", "{\n", " UV = position.xy*0.5+0.5;\n", " gl_Position = position;\n", "}\n", "\"\"\", gl.GL_VERTEX_SHADER)\n", "\n", "FRAGMENT_SHADER = shaders.compileShader(\"\"\"\n", "#version 330\n", "out vec4 outputColor;\n", "in vec2 UV;\n", "\n", "uniform sampler2D iChannel0;\n", "uniform vec3 iResolution;\n", "vec4 iMouse = vec4(0);\n", "uniform float iTime = 0.0;\n", "\"\"\" + shader_code + \"\"\"\n", "void main()\n", "{\n", " mainImage(outputColor, UV*iResolution.xy);\n", "}\n", "\n", "\"\"\", gl.GL_FRAGMENT_SHADER)\n", "\n", "shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)\n", "\n", "\n", "time_loc = gl.glGetUniformLocation(shader, 'iTime')\n", "res_loc = gl.glGetUniformLocation(shader, 'iResolution')\n", "\n", "def render_frame(time):\n", " gl.glClear(gl.GL_COLOR_BUFFER_BIT)\n", " with shader:\n", " gl.glUniform1f(time_loc, time)\n", " gl.glUniform3f(res_loc, WIDTH, HEIGHT, 1.0)\n", " \n", " gl.glEnableVertexAttribArray(0);\n", " gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, False, 0, vertexPositions)\n", " gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)\n", " img_buf = gl.glReadPixels(0, 0, WIDTH, HEIGHT, gl.GL_RGB, gl.GL_UNSIGNED_BYTE)\n", " img = np.frombuffer(img_buf, np.uint8).reshape(HEIGHT, WIDTH, 3)[::-1]\n", " return img\n", "show(render_frame(10.0)/255.0)" ], "execution_count": 26, "outputs": [ { "output_type": "display_data", "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": { "tags": [] } } ] }, { "metadata": { "id": "k8yl5IN2o8Zl", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 125 }, "outputId": "ccce5bac-a40b-4e16-c5ee-b9c6d8eed40e", "executionInfo": { "status": "ok", "timestamp": 1533314789392, "user_tz": -120, "elapsed": 15403, "user": { "displayName": "Alexander Mordvintsev", "photoUrl": "//lh4.googleusercontent.com/-n1VSNn_ErxQ/AAAAAAAAAAI/AAAAAAAAFpk/BCURumES134/s50-c-k-no/photo.jpg", "userId": "108092561333339272254" } } }, "cell_type": "code", "source": [ "clip = mvp.VideoClip(lambda t: render_frame(2.0+t*2.0), duration=6.0)\n", "clip.write_videofile('out.mp4', fps=60)" ], "execution_count": 33, "outputs": [ { "output_type": "stream", "text": [ "[MoviePy] >>>> Building video out.mp4\n", "[MoviePy] Writing video out.mp4\n" ], "name": "stdout" }, { "output_type": "stream", "text": [ "100%|█████████▉| 360/361 [00:13<00:00, 26.93it/s]\n" ], "name": "stderr" }, { "output_type": "stream", "text": [ "[MoviePy] Done.\n", "[MoviePy] >>>> Video ready: out.mp4 \n", "\n" ], "name": "stdout" } ] }, { "metadata": { "id": "1sRBDcTOpYQV", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 500 }, "outputId": "81b9c55f-6854-477d-d4b9-e5929413afc7", "executionInfo": { "status": "ok", "timestamp": 1533314791690, "user_tz": -120, "elapsed": 2265, "user": { "displayName": "Alexander Mordvintsev", "photoUrl": "//lh4.googleusercontent.com/-n1VSNn_ErxQ/AAAAAAAAAAI/AAAAAAAAFpk/BCURumES134/s50-c-k-no/photo.jpg", "userId": "108092561333339272254" } } }, "cell_type": "code", "source": [ "mvp.ipython_display('out.mp4')" ], "execution_count": 34, "outputs": [ { "output_type": "execute_result", "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": { "tags": [] }, "execution_count": 34 } ] }, { "metadata": { "id": "Xw4u_uX5rrs3", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "" ], "execution_count": 0, "outputs": [] } ] }