#!/usr/bin/env ruby require 'sfml/all' require 'opengl' class Example include SFML TITLE = "Josh's Ruby SFML/OpenGL Example" def initialize @fullscreen = false @window = Window.new create_window end def load_shaders v_id = glCreateShader(GL_VERTEX_SHADER) glShaderSource(v_id, <<-EOS) uniform vec2 offset; uniform vec2 screen_size; attribute vec2 pos; varying vec4 pos_i; void main() { vec2 scaled_pos = vec2((offset.x - screen_size.x / 2) / screen_size.x * 2, (offset.y - screen_size.y / 2) / screen_size.y * 2); pos_i = vec4(pos + scaled_pos, 0, 1); gl_Position = pos_i; } EOS glCompileShader(v_id) unless glGetShaderiv(v_id, GL_COMPILE_STATUS) raise glGetShaderInfoLog(v_id) end f_id = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(f_id, <<-EOS) varying vec4 pos_i; void main() { gl_FragColor = vec4((pos_i.x + 1.0) / 2.0, (pos_i.y + 1.0) / 2.0, 0, 1); } EOS glCompileShader(f_id) unless glGetShaderiv(f_id, GL_COMPILE_STATUS) raise glGetShaderInfoLog(f_id) end p_id = glCreateProgram() glAttachShader(p_id, v_id) glAttachShader(p_id, f_id) glLinkProgram(p_id) unless glGetProgramiv(p_id, GL_LINK_STATUS) raise glGetProgramInfoLog(p_id) end $offset_loc = glGetUniformLocation(p_id, "offset") $screen_size_loc = glGetUniformLocation(p_id, "screen_size") glUseProgram(p_id) end def create_window if @fullscreen @window.create(VideoMode.get_desktop_mode, TITLE, Style::Fullscreen) else @window.create([1200, 900], TITLE) end glClearColor(1, 0.5, 0, 0) load_shaders end def run quad_attrs = [0.02, 0.02, -0.02, 0.02, -0.02, -0.02, 0.02, -0.02].pack("f*") b_id = glGenBuffers(1).first glBindBuffer(GL_ARRAY_BUFFER, b_id); glBufferData(GL_ARRAY_BUFFER, 2 * 4 * 4, quad_attrs, GL_STATIC_DRAW); x, y = 0, 0 while @window.open? @window.each_event do |event| case event.type when Event::Closed @window.close when Event::KeyPressed case event.key.code when Keyboard::Escape @window.close when Keyboard::F @fullscreen = !@fullscreen create_window end when Event::MouseMoved x = event.mouse_move.x y = event.mouse_move.y when Event::Resized # Resize event : adjust viewport x = event.size.width / 2 y = event.size.height / 2 glViewport(0, 0, event.size.width, event.size.height) end end break unless @window.open? glClear(GL_COLOR_BUFFER_BIT) glUniform2f($offset_loc, x, @window.getSize.y - y) glUniform2f($screen_size_loc, @window.getSize.x, @window.getSize.y) glEnableVertexAttribArray(0) glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * 4, 0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @window.display end end end Example.new.run