diff --git a/example/setup.js b/example/setup.js index c1a9b5b..3dbdeb0 100644 --- a/example/setup.js +++ b/example/setup.js @@ -27,28 +27,30 @@ Example selection /** @enum {(typeof Example_Kind)[keyof typeof Example_Kind]} */ const Example_Kind = /** @type {const} */ ({ - Rectangle: 0, - Pyramid : 1, - Boxes : 2, - Camera : 3, - Lighting : 4, - Specular : 5, - Spotlight: 6, - Candy : 7, + Rectangle : 0, + Pyramid : 1, + Boxes : 2, + Camera : 3, + Lighting : 4, + Specular : 5, + Spotlight : 6, + Candy : 7, + Sol_System: 8, }) /** @type {Example_Kind[]} */ const example_kinds = Object.values(Example_Kind) /** @type {Record} */ const example_kind_href_hashes = { - [Example_Kind.Rectangle]: "#rectangle", - [Example_Kind.Pyramid] : "#pyramid", - [Example_Kind.Boxes] : "#boxes", - [Example_Kind.Camera] : "#camera", - [Example_Kind.Lighting] : "#lighting", - [Example_Kind.Specular] : "#specular", - [Example_Kind.Spotlight]: "#spotlight", - [Example_Kind.Candy] : "#candy", + [Example_Kind.Rectangle] : "#rectangle", + [Example_Kind.Pyramid] : "#pyramid", + [Example_Kind.Boxes] : "#boxes", + [Example_Kind.Camera] : "#camera", + [Example_Kind.Lighting] : "#lighting", + [Example_Kind.Specular] : "#specular", + [Example_Kind.Spotlight] : "#spotlight", + [Example_Kind.Candy] : "#candy", + [Example_Kind.Sol_System]: "#sol-system", } /** @type {Example_Kind} */ diff --git a/example/setup.odin b/example/setup.odin index 64df839..423a622 100644 --- a/example/setup.odin +++ b/example/setup.odin @@ -28,6 +28,7 @@ Example_Kind :: enum { Specular, Spotlight, Candy, + Sol_System, } example: Example_Kind @@ -66,18 +67,23 @@ demos: [Example_Kind]struct { vs_sources = {#load("./candy.vert", string)}, fs_sources = {#load("./candy.frag", string)}, }, + .Sol_System = { + vs_sources = {#load("./sol_system.vert", string)}, + fs_sources = {#load("./sol_system.frag", string)}, + }, } // state is a union because it is being used by only one of the examples demo_state: struct #raw_union { - rectangle: State_Rectangle, - pyramid: State_Pyramid, - boxes: State_Boxes, - camera: State_Camera, - lighting: State_Lighting, - specular: State_Specular, - spotlight: State_Spotlight, - candy: State_Candy, + rectangle: State_Rectangle, + pyramid: State_Pyramid, + boxes: State_Boxes, + camera: State_Camera, + lighting: State_Lighting, + specular: State_Specular, + spotlight: State_Spotlight, + candy: State_Candy, + sol_system: State_Sol_System, } @@ -157,14 +163,15 @@ start :: proc "c" (ctx: ^runtime.Context, example_kind: Example_Kind) -> (ok: bo gl.UseProgram(program) switch example { - case .Rectangle: setup_rectangle(&demo_state.rectangle, program) - case .Pyramid: setup_pyramid (&demo_state.pyramid, program) - case .Boxes: setup_boxes (&demo_state.boxes, program) - case .Camera: setup_camera (&demo_state.camera, program) - case .Lighting: setup_lighting (&demo_state.lighting, program) - case .Specular: setup_specular (&demo_state.specular, program) - case .Spotlight: setup_spotlight(&demo_state.spotlight, program) - case .Candy: setup_candy (&demo_state.candy, program) + case .Rectangle: setup_rectangle (&demo_state.rectangle, program) + case .Pyramid: setup_pyramid (&demo_state.pyramid, program) + case .Boxes: setup_boxes (&demo_state.boxes, program) + case .Camera: setup_camera (&demo_state.camera, program) + case .Lighting: setup_lighting (&demo_state.lighting, program) + case .Specular: setup_specular (&demo_state.specular, program) + case .Spotlight: setup_spotlight (&demo_state.spotlight, program) + case .Candy: setup_candy (&demo_state.candy, program) + case .Sol_System: setup_sol_system(&demo_state.sol_system, program) } if err := gl.GetError(); err != gl.NO_ERROR { @@ -188,13 +195,14 @@ frame :: proc "c" (ctx: ^runtime.Context, delta: f32) { } switch example { - case .Rectangle: frame_rectangle(&demo_state.rectangle, delta) - case .Pyramid: frame_pyramid (&demo_state.pyramid, delta) - case .Boxes: frame_boxes (&demo_state.boxes, delta) - case .Camera: frame_camera (&demo_state.camera, delta) - case .Lighting: frame_lighting (&demo_state.lighting, delta) - case .Specular: frame_specular (&demo_state.specular, delta) - case .Spotlight: frame_spotlight(&demo_state.spotlight, delta) - case .Candy: frame_candy (&demo_state.candy, delta) + case .Rectangle: frame_rectangle (&demo_state.rectangle, delta) + case .Pyramid: frame_pyramid (&demo_state.pyramid, delta) + case .Boxes: frame_boxes (&demo_state.boxes, delta) + case .Camera: frame_camera (&demo_state.camera, delta) + case .Lighting: frame_lighting (&demo_state.lighting, delta) + case .Specular: frame_specular (&demo_state.specular, delta) + case .Spotlight: frame_spotlight (&demo_state.spotlight, delta) + case .Candy: frame_candy (&demo_state.candy, delta) + case .Sol_System: frame_sol_system(&demo_state.sol_system, delta) } } diff --git a/example/shaders_generated.odin b/example/shaders_generated.odin index e565088..44933f5 100644 --- a/example/shaders_generated.odin +++ b/example/shaders_generated.odin @@ -36,6 +36,37 @@ Attribute_Values_Rectangle :: struct { a_color: vec4, } +Input_Locations_Sol_System :: struct { + a_position: Attribute_vec3, + a_color : Attribute_vec4, + u_matrix : Uniform_mat4, + u_color_mult: Uniform_vec4, +} + +input_locations_sol_system :: proc(s: ^Input_Locations_Sol_System, program: gl.Program) { + s.a_position = attribute_location_vec3(program, "a_position") + s.a_color = attribute_location_vec4(program, "a_color") + s.u_matrix = uniform_location_mat4(program, "u_matrix") + s.u_color_mult = uniform_location_vec4(program, "u_color_mult") +} + +Uniform_Values_Sol_System :: struct { + u_matrix : mat4, + u_color_mult: vec4, +} + +uniforms_sol_system :: proc(loc: Input_Locations_Sol_System, v: Uniform_Values_Sol_System) { + @static last: Uniform_Values_Sol_System + if v.u_matrix != last.u_matrix do uniform_mat4(loc.u_matrix , v.u_matrix ) + if v.u_color_mult != last.u_color_mult do uniform_vec4(loc.u_color_mult , v.u_color_mult ) + last = v +} + +Attribute_Values_Sol_System :: struct { + a_position: vec3, + a_color: vec4, +} + Input_Locations_Lighting :: struct { a_position: Attribute_vec3, a_normal : Attribute_vec3, diff --git a/example/sol_system.frag b/example/sol_system.frag new file mode 100644 index 0000000..725bf89 --- /dev/null +++ b/example/sol_system.frag @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec4 v_color; + +uniform vec4 u_color_mult; + +out vec4 out_color; + +void main() { + out_color = v_color * u_color_mult; +} diff --git a/example/sol_system.odin b/example/sol_system.odin new file mode 100644 index 0000000..2fca3f1 --- /dev/null +++ b/example/sol_system.odin @@ -0,0 +1,87 @@ +//+private file +package example + +import glm "core:math/linalg/glsl" +import gl "../wasm/webgl" + + +@private +State_Sol_System :: struct { + objects : []Object, + rotation: [2]f32, +} + +Shape :: struct { + using locations: Input_Locations_Sol_System, + vao : VAO, + positions: []vec3, + normals : []vec3, + colors : []u8vec4, +} + +Object :: struct { + using uniforms: Uniform_Values_Sol_System, + shape : Shape, + rotation : vec3, + rotation_speed: vec3, + translation : vec3, + scale : f32, +} + + +@private +setup_sol_system :: proc(s: ^State_Sol_System, program: gl.Program) { + gl.Enable(gl.CULL_FACE) + gl.Enable(gl.DEPTH_TEST) + + /* + Sphere + */ + + sphere_segments :: 6 + sphere_vertices := get_sphere_vertices(sphere_segments) + + sphere_shape: Shape = { + positions = make([]vec3 , sphere_vertices), + normals = make([]vec3 , sphere_vertices), + colors = make([]u8vec4, sphere_vertices), + vao = gl.CreateVertexArray(), + } + + get_sphere_base_triangle(sphere_shape.positions, sphere_shape.normals, 1, sphere_segments) + rand_colors_gray(sphere_shape.colors) + + gl.BindVertexArray(sphere_shape.vao) + input_locations_sol_system(&sphere_shape, program) + + attribute(sphere_shape.a_position, gl.CreateBuffer(), sphere_shape.positions) + attribute(sphere_shape.a_color , gl.CreateBuffer(), sphere_shape.colors) + + /* + Objects + */ + s.objects = make([]Object, 60) + + /* Init rotation */ + s.rotation = 1 +} + +@private +frame_sol_system :: proc(s: ^State_Sol_System, delta: f32) { + gl.Viewport(0, 0, canvas_res.x, canvas_res.y) + gl.ClearColor(0, 0, 0, 0) + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + + s.rotation -= 0.01 * delta * mouse_rel.yx + + view_mat: mat4 = 1 + view_mat *= glm.mat4PerspectiveInfinite( + fovy = glm.radians_f32(80), + aspect = aspect_ratio, + near = 1, + ) + view_mat *= glm.mat4Translate({0, 0, -900 + scale * 720}) + view_mat *= mat4_rotate_x(s.rotation.x) + view_mat *= mat4_rotate_y(s.rotation.y) + +} diff --git a/example/sol_system.vert b/example/sol_system.vert new file mode 100644 index 0000000..ecea27b --- /dev/null +++ b/example/sol_system.vert @@ -0,0 +1,19 @@ +#version 300 es + +// an attribute is an input (in) to a vertex shader. +// It will receive data from a buffer +in vec3 a_position; +in vec4 a_color; + +// A matrix to transform the positions by +uniform mat4 u_matrix; + +// a varying the color to the fragment shader +out vec4 v_color; + +void main() { + gl_Position = u_matrix * vec4(a_position, 1.0); + + // Pass the color to the fragment shader. + v_color = a_color; +}