{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "colab_gl.ipynb",
"version": "0.3.2",
"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": {}
},
"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": {}
},
"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": {}
},
"cell_type": "code",
"source": [
"import numpy as np\n",
"import json\n",
"import moviepy.editor as mvp\n",
"from google.colab import files\n",
"\n",
"import lucid.misc.io.showing as show"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "Y_ytjJ-kM8rJ",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 53
},
"outputId": "567987a4-c321-4285-98e5-7e0ded1ad3e6"
},
"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": 24,
"outputs": [
{
"output_type": "stream",
"text": [
"b'4.5.0 NVIDIA 384.111'\n",
"b'NVIDIA Corporation'\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "C11neUqkNRM5",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 500
},
"outputId": "b759737e-8a3c-4968-93e6-457d17e05efb"
},
"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.image(img/255.0)"
],
"execution_count": 25,
"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",
"We now have the full power of modern OpenGL in our hands! Let's do something interesting with it!\n",
"\n",
"Fetching the source and rendering the [amaizing shader](https://www.shadertoy.com/view/Xtf3Rn) by Kali from [ShaderToy](https://www.shadertoy.com/view/Xtf3Rn). You can also substitute a different `shader_id`, but note that only single-pass shaders that don't use textures are supported by the code below."
]
},
{
"metadata": {
"id": "at5TlI-eofcE",
"colab_type": "code",
"colab": {}
},
"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": {
"base_uri": "https://localhost:8080/",
"height": 500
},
"outputId": "719d57a2-dd8f-4a00-edba-cb3f442fe910"
},
"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.image(render_frame(10.0)/255.0, format='jpeg')"
],
"execution_count": 27,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/html": [
"
"
],
"text/plain": [
""
]
},
"metadata": {
"tags": []
}
}
]
},
{
"metadata": {
"id": "dQ_8-SLU38RY",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"Use [MoviePy](https://zulko.github.io/moviepy/) to generate a video."
]
},
{
"metadata": {
"id": "k8yl5IN2o8Zl",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 125
},
"outputId": "d6201b40-c9e8-4a7d-eaeb-1765722bf5cd"
},
"cell_type": "code",
"source": [
"clip = mvp.VideoClip(render_frame, duration=10.0)\n",
"clip.write_videofile('out.mp4', fps=60)\n",
"files.download('out.mp4')"
],
"execution_count": 13,
"outputs": [
{
"output_type": "stream",
"text": [
"[MoviePy] >>>> Building video out.mp4\n",
"[MoviePy] Writing video out.mp4\n"
],
"name": "stdout"
},
{
"output_type": "stream",
"text": [
"100%|█████████▉| 600/601 [00:16<00:00, 35.86it/s]\n"
],
"name": "stderr"
},
{
"output_type": "stream",
"text": [
"[MoviePy] Done.\n",
"[MoviePy] >>>> Video ready: out.mp4 \n",
"\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "UrZUkEQo1w1i",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}