Remark: in the following article, words GLSL Hacker and GeeXLab are swappable! They represent the same software with a different name…
Today we are going to see how to build and render a simple scene that includes a camera, a triangle, a reference grid and a GPU program (in GLSL). GLSL Hacker supports both Lua and Python programming languages. We will use Lua for this article. So let’s go!
Article index:
- 1 – The Camera (INIT script)
- 2 – The Triangle (INIT script)
- 3 – The Reference Grid (INIT script)
- 4 – The GPU Program (INIT script)
- 5 – Scene Rendering (FRAME script)
- 6 – The Demo
Note: the overview of GLSL Hacker can be useful to understand the concept of INIT and FRAME scripts
1 – The Camera (INIT script)
Here is the code to create and initialize a perspective camera. The camera is the core element of the viewing pipeline and we need a perspective camera to see the 3D world. The camera has a field of view (fov) of 60 degrees and its position is X=2, Y=2 and Z=4.
winW, winH = gh_window.getsize(0)
local aspect = winW / winH
camera_params = { fov=60, znear=1.0, zfar=1000.0 }
camera = gh_camera.create_persp(camera_params.fov,
aspect,
camera_params.znear,
camera_params.zfar)
gh_camera.set_viewport(camera, 0, 0, winW, winH)
gh_camera.set_position(camera, 2, 2, 4)
gh_camera.set_lookat(camera, 0, 0, 0)
gh_camera.set_upvec(camera, 0, 1, 0, 0)
2 – The Triangle (INIT script)
GLSL Hacker has a built-in function that creates a triangle (gh_mesh.create_triangle). This function works fine but I prefer to show you how to build a triangle manually using a more flexible way. The triangle is the most simple mesh and is made up of 3 vertices:
triangle = gh_mesh.create_v2()
local num_vertices = 3
local num_faces = 0 -- non-indexed rendering
gh_mesh.alloc_mesh_data(triangle, num_vertices, num_faces)
gh_mesh.create_v2 creates a generic mesh. gh_mesh.alloc_mesh_data allocates memory for storing the vertices (and the faces if we build an indexed mesh). After the call to gh_mesh.alloc_mesh_data, we have a mesh with enough room to store 3 vertices. Let’s see now how to initialize the position and color of these vertices:
gh_mesh.set_vertex_position(triangle, 0, -1, -1, 0, 1)
gh_mesh.set_vertex_position(triangle, 1, 0, 1, 0, 1)
gh_mesh.set_vertex_position(triangle, 2, 1, -1, 0, 1)
gh_mesh.set_vertex_color(triangle, 0, 1, 0, 0, 1)
gh_mesh.set_vertex_color(triangle, 1, 0, 1, 0, 1)
gh_mesh.set_vertex_color(triangle, 2, 0, 0, 1, 1)
That’s all for the triangle.
3 – The Reference Grid (INIT script)
The reference grid is a helper object that allows to easily visualize the ground. The creation and initialization of the grid is really simple:
grid = gh_utils.grid_create()
gh_utils.grid_set_geometry_params(grid, 10, 10, 20, 20)
More parameters to customize the grid have been covered in THIS ARTICLE.
4 – The GPU Program (INIT script)
We live today in full shader world so we need a GPU program to draw (render) 3D objects on the screen. To draw both the triangle and the grid, all we need is a GPU program that can deal with the position and color of objects vertices. This GPU program has a vertex shader to transform the geometry (the vertices) and a pixel shader to draw the pixels of the primitives (here a triangle and lines).
Here is the source code of the GPU program in GLSL (the OpenGL Shading Language) for an OpenGL 3.0 demo:
Remark: I used the version 130 in this GLSL program because it’s supported by any OpenGL 3.2+ implementation but and that’s the important thing, it’s supported by some Gallium drivers on Linux. Those drivers do not support OpenGL 3.2 (version 150) but only OpenGL 3.0 (version 130). A good example of such a driver is the default driver that is installed with Linux Mint 17 when a NVIDIA GeForce card is present.
If you want to test this demo on a Raspberry Pi, you have to use this GPU program (OpenGL ES 2.0):
To get the handle to the GPU program in the Lua code, just include this instruction:
vertex_color_prog = gh_node.getid("vertex_color_prog")
5 – Scene Rendering (FRAME script)
All the previous steps took place in the INIT script. Now let’s see the FRAME script that will perform the real drawing of the scene:
-- Apply the params of the main camera and clear the color
-- and depth buffers.
--
gh_camera.bind(camera)
gh_renderer.clear_color_depth_buffers(0.2, 0.2, 0.2, 1.0, 1.0)
gh_renderer.set_depth_test_state(1)
-- Bind vertex_color_prog to make it the active GPU program.
--
gh_gpu_program.bind(vertex_color_prog)
-- Render the triangle and the grid
--
gh_object.render(triangle)
gh_object.render(grid)
Simple isn’t it?
6 – The Demo
The demo is available in GLSL Hacker GeeXLab code sample pack in the host_api/Triangle/ folder. You can download both GLSL Hacker GeeXLab and the code sample pack from THIS PAGE.
The demo is available in two flavors: GL3 for desktop systems (Windows, Linux and OS X) and GLES2 for the Raspberry Pi.