$:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib") $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext") def path_of(res) File.expand_path(File.dirname(__FILE__) + "/../../test/res/#{res}") end require 'ray' Ray::GL.core_profile = true Ray::GL.major_version = 3 Ray::GL.minor_version = 2 class Sprites < Ray::Drawable Radius = 300 def initialize(image) super() @image = image self.vertex_count = 400 end def fill_vertices Array.new(vertex_count) do angle = rand * 2 * Math::PI radius = Math.sqrt(rand) * Radius pos = [Math.cos(angle) * radius, Math.sin(angle) * radius] Ray::Vertex.new(pos, Ray::Color.new(rand(256), rand(256), rand(256))) end end def render(first, index) @image.bind Ray::GL.draw_arrays :points, first, vertex_count end end Ray.game "Geometry shader" do register { add_hook :quit, method(:exit!) } scene :shader do @sprites = Sprites.new image(path_of("stone.png")) @sprites.pos = window.size / 2 vertex = <<-vertex #version 150 in vec2 in_Vertex; in vec4 in_Color; in vec2 in_TexCoord; uniform mat4 in_ModelView; uniform mat4 in_Projection; out vec4 geom_Color; out vec2 geom_TexCoord; void main() { gl_Position = vec4(in_Vertex, 0, 1) * (in_ModelView * in_Projection); geom_Color = in_Color; geom_TexCoord = in_TexCoord; } vertex geometry = <<-geometry #version 150 layout(points) in; layout(triangle_strip, max_vertices = 4) out; in vec4 geom_Color[]; in vec2 geom_TexCoord[]; out vec4 var_Color; out vec2 var_TexCoord; uniform float square_size; const float pixel_width = 1.0 / 640; const float pixel_height = 1.0 / 480; struct vertex { vec4 pos; vec4 color; vec2 tex_coord; }; void emit_vertex(vertex v) { gl_Position = v.pos; var_Color = v.color; var_TexCoord = v.tex_coord; EmitVertex(); } void main() { float width = pixel_width * square_size / 2; float height = pixel_height * square_size / 2; vec4 position = gl_in[0].gl_Position; vec4 color = geom_Color[0]; vertex vertices[4]; vertices[0].pos = position + vec4(-width, -height, 0, 0); vertices[0].tex_coord = vec2(0, 0); vertices[0].color = color; vertices[1].pos = position + vec4(-width, +height, 0, 0); vertices[1].tex_coord = vec2(0, 1); vertices[1].color = color; vertices[2].pos = position + vec4(+width, -height, 0, 0); vertices[2].tex_coord = vec2(1, 0); vertices[2].color = color; vertices[3].pos = position + vec4(+width, +height, 0, 0); vertices[3].tex_coord = vec2(1, 1); vertices[3].color = color; for (int i = 0; i < 4; i++) emit_vertex(vertices[i]); EndPrimitive(); } geometry frag = <<-frag #version 150 uniform sampler2D in_Texture; uniform bool in_TextureEnabled; in vec4 var_Color; in vec2 var_TexCoord; out vec4 out_FragColor; void main() { out_FragColor = var_Color * texture(in_Texture, var_TexCoord); } frag window.shader.compile(:frag => StringIO.new(frag), :vertex => StringIO.new(vertex), :geometry => StringIO.new(geometry)) window.shader[:square_size] = @size = 15 always do if holding? :+ window.shader[:square_size] = (@size += 3) elsif holding? :- window.shader[:square_size] = (@size -= 3) end @sprites.angle += 1.0 end render do |win| win.draw @sprites end end scenes << :shader end