Skip to content

Instantly share code, notes, and snippets.

@h3y6e
Created December 14, 2019 07:02
Show Gist options
  • Save h3y6e/456603460d8574279b87a88634ee27f2 to your computer and use it in GitHub Desktop.
Save h3y6e/456603460d8574279b87a88634ee27f2 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 参考文献\n",
"[Anton's OpenGL 4 Tutorials](http://antongerdelan.net/opengl/) \n",
"[capnramses/antons_opengl_tutorials_book](https://github.com/capnramses/antons_opengl_tutorials_book) "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Julia Version 1.2.0\n",
"Commit c6da87ff4b (2019-08-20 00:03 UTC)\n",
"Platform Info:\n",
" OS: macOS (x86_64-apple-darwin18.6.0)\n",
" CPU: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz\n",
" WORD_SIZE: 64\n",
" LIBM: libopenlibm\n",
" LLVM: libLLVM-6.0.1 (ORCJIT, skylake)\n"
]
}
],
"source": [
"versioninfo()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pkg\n",
"JuliaGL の GLFW.jl と ModernGL.jl を導入"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import GLFW\n",
"using ModernGL"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Window Hints\n",
"`GLFW.WindowHint()` で開くウィンドウで使う OpenGL のコンテキストのバージョンやプロファイルを指定出来る\n",
"\n",
"`@static` で OS チェックし, macOS の場合は OpenGL 4.1 を指定する \n",
"(macOS でサポートしている最新バージョンが 4.1 の為)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"@static if Sys.isapple()\n",
" const VERSION_MAJOR = 4\n",
" const VERSION_MINOR = 1\n",
"end\n",
"\n",
"@static if Sys.isapple()\n",
" GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, VERSION_MAJOR)\n",
" GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, VERSION_MINOR)\n",
" GLFW.WindowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE)\n",
" GLFW.WindowHint(GLFW.OPENGL_FORWARD_COMPAT, GL_TRUE)\n",
"else\n",
" GLFW.DefaultWindowHints()\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## window の作成\n",
"> ```julia\n",
"@assert cond [msg]\n",
"```\n",
"で `cond` が `false` の場合、`AssertionError([msg])` を投げる\n",
" \n",
"これを用いて window が作成されなかったときにエラーを吐く"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"window = GLFW.CreateWindow(640, 480, \"Triangle\")\n",
"@assert window != C_NULL \"could not open window with GLFW3.\"\n",
"GLFW.MakeContextCurrent(window)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## バージョン情報\n",
"```julia\n",
"glGetString(name::GLenum)::Ptr{GLchar}\n",
"unsafe_string(p::Ptr{UInt8}, [length::Integer])::String\n",
"```\n",
"\n",
"#### ログメッセージ\n",
"```julia\n",
"@debug message [key=value | value ...]\n",
"@info message [key=value | value ...]\n",
"@warn message [key=value | value ...]\n",
"@error message [key=value | value ...]\n",
"```\n",
"順に重大度が高くなる"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"┌ Info: Renderder: Intel(R) Iris(TM) Plus Graphics 655\n",
"└ @ Main In[5]:3\n",
"┌ Info: OpenGL version supported: 4.1 INTEL-12.10.12\n",
"└ @ Main In[5]:4\n"
]
}
],
"source": [
"renderer = unsafe_string(glGetString(GL_RENDERER))\n",
"version = unsafe_string(glGetString(GL_VERSION))\n",
"@info \"Renderder: $renderer\"\n",
"@info \"OpenGL version supported: $version\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 隠面消去\n",
"\n",
"```julia\n",
"glEnable(GL_DEPTH_TEST)\n",
"```\n",
"深度テストを有効化する(深度の異なる物体が物体を覆い隠すようにする)\n",
"```julia\n",
"glDepthFunc(GL_LESS)\n",
"```\n",
"対象形状を一つの方向から近くにあるものを優先する\n",
"\n",
"↓ \n",
"手前の物体が奥の物体を隠すようにする"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"glEnable(GL_DEPTH_TEST)\n",
"glDepthFunc(GL_LESS)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 頂点バッファで三角形を定義する\n",
"![vertex_buffer](vertex_buffer.png)\n",
"\n",
"```\n",
"-1 <= x <= 1\n",
"-1 <= y <= 1\n",
"-1 <= z <= 1 (ここでは z = 0)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"9-element Array{Float32,1}:\n",
" 0.0\n",
" 0.5\n",
" 0.0\n",
" 0.5\n",
" -0.5\n",
" 0.0\n",
" -0.5\n",
" -0.5\n",
" 0.0"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"points = GLfloat[ 0.0, 0.5, 0.0,\n",
" 0.5, -0.5, 0.0,\n",
" -0.5, -0.5, 0.0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### VBO\n",
"VBO (vertex buffer object) という単位でグラフィックカードにコピーする \n",
"作成した空のバッファをバインドによって現在のバッファとして設定し, `points` をコピーする\n",
" \n",
"#### Ref型\n",
"```julia\n",
"Ref{T}\n",
"```\n",
"T型のデータを安全に参照するオブジェクト \n",
"Refオブジェクトは`[]`で間接参照される \n",
"ccall引数として渡されると参照するデータへのネイティブポインタに変換される"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"pvbo = Ref{GLuint}(0)\n",
"glGenBuffers(1, pvbo)\n",
"vbo = pvbo[]\n",
"glBindBuffer(GL_ARRAY_BUFFER, vbo)\n",
"glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### VAO\n",
"VAO (vertex array object) "
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# create VAO\n",
"pvao = Ref{GLuint}(0)\n",
"glGenVertexArrays(1, pvao)\n",
"vao = pvao[]\n",
"glBindVertexArray(vao)\n",
"glEnableVertexAttribArray(0)\n",
"glBindBuffer(GL_ARRAY_BUFFER, vbo)\n",
"glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, C_NULL)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## シェーダ\n",
"### GLSL (OpenGL Shader Language)\n",
"C言語をベースとしたシェーダ記述言語\n",
"プレーンテキストファイル[$^1$](#1) からロードするのが一般的だが,ここではハードコーディングすることにする\n",
"\n",
"$^1$<small id=\"1\">\n",
" 拡張子は `.vert` と `.flag` が一般的.まとめて `.glsl` とするときもある\n",
" </small>"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"#version 410 core\\nout vec4 frag_colour;\\nvoid main(void) {\\n frag_colour = vec4(0.5, 0.0, 0.5, 1.0);\\n}\""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# hard-coded shaders\n",
"const vert_source = \"\"\"\n",
"#version 410 core\n",
"in vec3 vp;\n",
"void main(void) {\n",
" gl_Position = vec4(vp, 1.0);\n",
"}\"\"\"\n",
"\n",
"const frag_source = \"\"\"\n",
"#version 410 core\n",
"out vec4 frag_colour;\n",
"void main(void) {\n",
" frag_colour = vec4(0.5, 0.0, 0.5, 1.0);\n",
"}\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### GL シェーダにロード, コンパイル"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"vs = glCreateShader(GL_VERTEX_SHADER)\n",
"glShaderSource(vs, 1, Ptr{GLchar}[pointer(vert_source)], C_NULL)\n",
"glCompileShader(vs)\n",
"fs = glCreateShader(GL_FRAGMENT_SHADER)\n",
"glShaderSource(fs, 1, Ptr{GLchar}[pointer(frag_source)], C_NULL)\n",
"glCompileShader(fs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### リンク\n",
"単一の実行可能なGPUシェーダプログラムにするために,空のプログラムを作成してシェーダを接続する"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"program = glCreateProgram()\n",
"glAttachShader(program, vs)\n",
"glAttachShader(program, fs)\n",
"glLinkProgram(program)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 描画\n",
"\n",
"画面の描画をウィンドウが閉じられるまでループさせる\n",
"\n",
"最初に描画面をクリアする\n",
"```julia\n",
"glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)\n",
"```\n",
"\n",
"シェーダプログラムを設定する\n",
"```julia\n",
"glUseProgram(program)\n",
"```\n",
"\n",
"VAO を描画に用いる入力変数として設定する\n",
"```julia\n",
"glBindVertexArray(vao)\n",
"```\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Dict{GLFW.Window,Ref{Array{Union{Nothing, Function},1}}} with 0 entries"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# render\n",
"while !GLFW.WindowShouldClose(window)\n",
" glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)\n",
" glUseProgram(program)\n",
" glBindVertexArray(vao)\n",
" glDrawArrays(GL_TRIANGLES, 0, 3)\n",
" # check and call events\n",
" GLFW.PollEvents()\n",
" # swap the buffers\n",
" GLFW.SwapBuffers(window)\n",
"end\n",
"\n",
"GLFW.DestroyWindow(window)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.2.0",
"language": "julia",
"name": "julia-1.2"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.2.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment