-- -- pixwerx - bare rendering engine binding usage -- -- we need everything pw.script:load_all() print("executable path:",pw.path.get().executable_path) print("resource paths:",pw.path.get().resource_paths) for k,v in pairs(pw.path.get().resource_paths) do print(k,v) end -- create image local img = pw.image() -- initialize with data if not img:create(pw.size(512,512),pw.pixel_layout.rgb8,nil) then print("image couldnt be created") else -- generate some noise img:generate_noise() -- for debugging pw.image_io.get():write("test.png",img,0) end -- create a window (remember windows are invisible by default) local w = pw.window.new() -- set title w.title = "pixwerx - bare rendering" -- set size w.size = pw.size(640,480) -- move window w.position = pw.point(100,100) -- create a new geometry local g = pw.geometry() g.primitive_topology = pw.primitive_topology_type.triangle_list -- meh -- create texture coordinates g.texture_coordinates = { { { 0.0, 0.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 1.0 } } } z = 0 s = 1 -- 0 --- 3 -- | \ | -- 1 --- 2 -- indices g.indices = { 0, 1, 2, -- triangle #1 2, 3, 0 -- triangle #2 } print(g.indices,#g.indices) -- geometry can only build with indexed facesets g.vertices = { { -s,-s, z }, { s,-s, z }, { s, s, z }, { -s, s, z } } g:compute_normals() local mm = pw.matrix4x4.identity local mv = pw.matrix4x4() local mp = pw.matrix4x4() local s = pw.shader() s:set_source(pw.shader_type.vertex,[[ #version 400 layout (location = 0) in vec3 vertices; layout (location = 1) in vec3 normals; layout (location = 2) in vec2 texture_coords; uniform mat4 model; uniform mat4 view; uniform mat4 projection; out vec2 tex_c; void main() { tex_c = texture_coords; gl_Position = projection * view * model * vec4(vertices, 1.0); } ]]) s:set_source(pw.shader_type.fragment,[[ #version 400 uniform vec4 color = vec4(1.0, 0.0, 0.0, 1.0); uniform sampler2D tex_color; in vec2 tex_c; out vec4 frag_color; void main() { frag_color = texture(tex_color,tex_c) * color; } ]]) -- check if the shader can be compiled and linked if not s:build() then print("Error!") end -- the renderer for a geometry local renderer = pw.renderer() -- camera position local cam_pos = pw.vector3(0,0,5) -- model position local model_pos = pw.vector3(0,0,0) -- create new context (should move into a scene later) local ctx = pw.context() -- create a texture local tx = pw.texture() -- create texture from an image tx:create(img) -- unload it - would only make sense for static textures -- img:release() -- set function to w.on_resize = function(self) -- use client_size to resize the viewport ctx:set_viewport(pw.rectangle(pw.point(0,0),self.client_size:cast_to_float())) end -- setup a lua callback function as callback w.on_update = function(self) -- we set the clear color ctx.clearcolor = pw.color(pw.mathf.ping_pong(pw.time.now,1.0),0,1,1) ctx:clear() -- set view matrix with look_at - view matrix is moving the world - hence inverse! mv = pw.matrixtransform.look_at(cam_pos,cam_pos + pw.vector3.forward,pw.vector3.up).inverse -- compute aspect ratio from canvas size aspect_ratio = self.client_size.width / self.client_size.height -- create a view frustum for a perspective projection mp = pw.matrixtransform.perspective_projection(math.rad(45),aspect_ratio,0.2,100) -- -- this code is raw rendering mode -- -- just some toying around local color_red = pw.mathf.ping_pong(pw.time.now,1.0) local color_green = pw.mathf.ping_pong(pw.time.now + 1,1.0) local color_blue = 1.0 - pw.mathf.ping_pong(pw.time.now,1.0) -- color is currently still a vector4 local cl = pw.vector4( color_red, color_green, color_blue, 1.0 ) img:generate_noise() tx:update(img) -- bind the shader s:use() -- update the uniforms, currently the slow path s:set_uniform_mat4("model",mm) s:set_uniform_mat4("view",mv) s:set_uniform_mat4("projection",mp) s:set_uniform_vec4("color",cl) -- specific to our shader s:set_uniform_int("tex_color",0) -- unit 0 -- bind the texture tx:bind() -- update renderer from geometry renderer:update(g) -- draw renderer:draw() local e = ctx:get_error() if e ~= 0 then print("OpenGL error",e) end end -- before entering the update loop make the window visible w.visible = true -- some fluffyness local speed = 0 -- main update loop while w:update() do -- only check if get a new input if pw.input.get().has_input then -- somehow (depending on X11/Wayland) works if pw.input.get().input_string == 'f' then w.fullscreen = not w.fullscreen end -- keycode for quit if pw.input.get().input_string == 'q' then break end -- just to quickly modify speed local move_step = 0.05 -- camera if pw.input.get().input_string == 'w' then cam_pos.z = cam_pos.z - move_step elseif pw.input.get().input_string == 's' then cam_pos.z = cam_pos.z + move_step elseif pw.input.get().input_string == 'a' then cam_pos.x = cam_pos.x - move_step elseif pw.input.get().input_string == 'd' then cam_pos.x = cam_pos.x + move_step elseif pw.input.get().input_string == 'z' then cam_pos.y = cam_pos.y + move_step elseif pw.input.get().input_string == 'x' then cam_pos.y = cam_pos.y - move_step end -- just some debugging print(cam_pos.x,cam_pos.y,cam_pos.z) end -- just to check if pw.input:get().mouse_button == 1 then print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y,w.client_size.width,w.client_size.height) end end