Use the 3d camera

By default the viewer will set a uniform block with all the camera and projection matrices for you, so you can navigate the view in 3d if you want.

//the ViewBlock that is automatically filled by ipywebgl layout(std140) uniform ViewBlock { mat4 u_cameraMatrix; //the camera matrix in world space mat4 u_viewMatrix; //the inverse of the camera matrix mat4 u_projectionMatrix; //the projection matrix mat4 u_viewProjectionMatrix; //the projection * view matrix };

  • By default the matrix will be sent as row major to the shader, but if you prefer you can work in column major.

    • use : w = ipywebgl.GLViewer(shader_matrix_major=’column_major’) to be in column major.

    • all the examples will be ‘row_major’ in this case.

Import

[1]:
import ipywebgl
import numpy as np

Create viewer

And clear the color to make the background visible.

[2]:
w = ipywebgl.GLViewer()
w.clear_color(.8, .8, .8 ,1)
w.clear()
w.execute_commands(execute_once=True)

Program

Create a program that will display a grid on the ground. And use the Camera (ViewProjection) to rotate the view

[3]:
program = w.create_program_ext(
"""#version 300 es

//the ViewBlock that is automatically filled by ipywebgl
layout(std140) uniform ViewBlock
{
    mat4 u_cameraMatrix;          //the camera matrix in world space
    mat4 u_viewMatrix;            //the inverse of the camera matrix
    mat4 u_projectionMatrix;      //the projection matrix
    mat4 u_viewProjectionMatrix;  //the projection * view matrix
};

in vec3 in_vert;

void main() {
    gl_Position = u_viewProjectionMatrix * vec4(in_vert, 1.0);
}
"""
,
"""#version 300 es
precision highp float;
out vec4 f_color;
void main() {
    f_color = vec4(0.1, 0.1, 0.1, 1.0);
}
""")

Grid vertex buffer

Create a grid vertex array. By creating a set of lines in X and Z. (Y is up in our viewport)

[10]:
def grid(size, steps):
    u = np.repeat(np.linspace(-size, size, steps), 2)
    v = np.tile([-size, size], steps)
    w = np.zeros(steps * 2)
    return np.concatenate([np.dstack([u, w, v]), np.dstack([v, w, u])], dtype=np.float32)

points = grid(100,20)

vbo = w.create_buffer_ext(
    src_data=points
)

vao = w.create_vertex_array_ext(
    program,
    [
        (vbo, '3f32', 'in_vert'),
    ]
)
[5]:
#number of points in the buffer :
points.reshape([-1,3]).shape
[5]:
(80, 3)

Render

Render the view, you can now interact with the view with your mouse (left click and drag) to rotate and the ‘wasd’ keys to move

  • if you need to change the default keys:

    • you can do it at init time with : GLViewer(move_keys=’ijkl’)

    • or runtime with : w.move_keys = ‘ijkl’

Any letters can be used.

[15]:
w.clear()
w.use_program(program)
w.bind_vertex_array(vao)
w.draw_arrays('LINES', 0, points.reshape([-1,3]).shape[0])
w.execute_commands()
w
[15]:

Interact with the camera from python

Let’s set the camera values using the python code

We can build a simple rotating camera control with an interact slider

[7]:
w.camera_pos, w.camera_pitch, w.camera_yaw
[7]:
([0, 50, 200], 0.0, 0.0)
[14]:
from ipywidgets import widgets, interact

def set_camera(angle):
    rad = angle/180.0*np.pi
    w.camera_pos = [np.sin(rad)*200, 70, np.cos(rad)*200]
    w.camera_yaw = angle
    w.camera_pitch = -20

interact(
    set_camera,
    angle=widgets.IntSlider(min=0, max=360, step=1, value=0),
)
w
[14]:
[11]:
w.verbose = 0