Slide 1

Slide 1 text

Play GLSL on mruby with OpenFrameworks 襝儗䓚⛲

Slide 2

Slide 2 text

Web Developer Game Developer Major in Digital Media Design Taiwanese who likes Anime, Manga, Game @elct9620 襝儗䓚⛲

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

https://www.flickr.com/photos/hsbt/21251922399/in/album-72157658244299230/

Slide 5

Slide 5 text

Demo First Talk What is OpenFrameworks and GLSL? Shader Generator written in mruby Using mruby in C++

Slide 6

Slide 6 text

Learn some physics knowledge before demo

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

DEMO TIME!

Slide 9

Slide 9 text

Who use the OpenFrameworks? What is the Shader mean? What is the GLSL? OpenFrameworks and GLSL

Slide 10

Slide 10 text

http://blog.bongiovi.tw/calligraphy-in-3d/ OpenFrameworks demo

Slide 11

Slide 11 text

The Shader Role

Slide 12

Slide 12 text

The Shader Role

Slide 13

Slide 13 text

Vertex Shader http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

Slide 14

Slide 14 text

Vertex Shader http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

Slide 15

Slide 15 text

Vertex Shader http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

Slide 16

Slide 16 text

Vertex Shader http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/

Slide 17

Slide 17 text

Fragment Shader

Slide 18

Slide 18 text

Fragment Shader

Slide 19

Slide 19 text

“GLSL is a language OpenGL provide for us”

Slide 20

Slide 20 text

@5xruby @s_cat555

Slide 21

Slide 21 text

Open Class to extend C++ class How to convert Ruby to GLSL The DSL limitation Arithmetic Problem Shader Generator

Slide 22

Slide 22 text

class Shader def vertex(&block) code = Code.new code.instance_eval(&block) self.vertex = code.to_s end end Open Class

Slide 23

Slide 23 text

mrb_define_method(mrb, klass, "draw", draw, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "vertex=", setVertexShader, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "fragment=", setFragmentShader, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "bind", bind, MRB_ARGS_OPT(3)); mrb_define_method(mrb, klass, "apply", apply, MRB_ARGS_NONE()); Open Class

Slide 24

Slide 24 text

vec4 lightIntensity = vec4(1, 1, 1, 1); lightIntensity = clamp(lightIntensity.x, 0, 1); lightIntensity is Vec4 vec4(1, 1, 1, 1) lightIntensity is clamp(lightIntensity.x, 0, 1) Ruby Code GLSL Code Convert to GLSL

Slide 25

Slide 25 text

@5xruby @s_cat555

Slide 26

Slide 26 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL Convert to GLSL

Slide 27

Slide 27 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL

Slide 28

Slide 28 text

=> # Convert to GLSL

Slide 29

Slide 29 text

TYPES.each do |type, typename| define_method(type) { |*args| Type.new(type, *args) } end Convert to GLSL

Slide 30

Slide 30 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL

Slide 31

Slide 31 text

def is(*args) value = args value = args.first if args.first.is_a?(Array) AssignNode.new(*value) end Convert to GLSL

Slide 32

Slide 32 text

=> # @expression=#> Convert to GLSL

Slide 33

Slide 33 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL

Slide 34

Slide 34 text

def method_missing(name, *args, &block) value = args.first return assign(name, value) if value.is_a? (AssignNode) return [send(name.downcase), value] if is_const?(name) Variable.new(name) end Convert to GLSL

Slide 35

Slide 35 text

=> "vec4 lightIntensity = vec4(1, 1, 1, 1);" Convert to GLSL

Slide 36

Slide 36 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL

Slide 37

Slide 37 text

class Shader::AssignNode def initialize(type, *args) @type = type @expression = args.shift unless type.is_a?(Type) && [email protected]? @expression = @type @type = nil end end end Convert to GLSL

Slide 38

Slide 38 text

def to(name) name = "-#{name}" if @negative return "#{name} = #{expression};" if @type.nil? return "#{@type.to_typename} #{name} = #{expression};" unless is_const?(name) "const #{@type.to_typename} #{name} = #{expression};" end Convert to GLSL

Slide 39

Slide 39 text

Convert to GLSL lightIntensity is Vec4 vec4(1, 1, 1, 1)

Slide 40

Slide 40 text

Convert to GLSL vec4(1, 1, 1, 1) => #

Slide 41

Slide 41 text

Convert to GLSL Vec4 [Argument] => [#, #]

Slide 42

Slide 42 text

Convert to GLSL is [type, expression] => # @expression=#>

Slide 43

Slide 43 text

Convert to GLSL lightIntensity [expression] => (Insert into Buffer)

Slide 44

Slide 44 text

lightIntensity(is(Vec4(vec4(1, 1, 1, 1)))) lightIntensity(is(clamp(lightIntensity.x, 0, 1)) Convert to GLSL

Slide 45

Slide 45 text

def method_missing(name, *args, &block) @suffix << name self end Convert to GLSL

Slide 46

Slide 46 text

def to_s return "#{@name}" if @suffix.empty? "#{@name}.#{@suffix.join(".")}" end Convert to GLSL

Slide 47

Slide 47 text

lightIntensity.x # => “lightIntensity.x" lightIntensity.x.z # => “lightIntensity.x.z" Convert to GLSL

Slide 48

Slide 48 text

class Shader::FunctionCall < Shader::Variable def initialize(name, *args) super(name) @args = args end def to_funtion "#{@name}(#{@args.join(", ")})" end def to_s return "#{to_funtion}" if @suffix.empty? "#{to_funtion}.#{@suffix.join(".")}" end end Convert to GLSL

Slide 49

Slide 49 text

FUNCTIONS.each do |name| define_method(name) do |*args| FunctionCall.new(name, *args) end end Convert to GLSL

Slide 50

Slide 50 text

“But, why not use = to assign variable?”

Slide 51

Slide 51 text

main do @variable = 1234 # Captured by class variable = 1234 # Not captured end Limitation

Slide 52

Slide 52 text

main do vec4 @variable = vec4(1, 1, 1, 1) @variable = vec4 vec4(1, 1, 1, 1) end Limitation

Slide 53

Slide 53 text

Limitation

Slide 54

Slide 54 text

main do variable is Vec4 vec4(1, 1, 1, 1) variable is Vec4 vec4(1, 1, 1, 1) end Limitation

Slide 55

Slide 55 text

main do variable is vec4 vec4(1, 1, 1, 1) + 1 variable is Vec4 vec4(1) * normal end Arithmetic Problem

Slide 56

Slide 56 text

module Shader::Calculable def operation @operation ||= [] end def +(other) operation.push("+", other) self end end Arithmetic Problem

Slide 57

Slide 57 text

module Shader::Calculable def to_expression return to_s if operation.empty? "#{to_s} #{operation.join(" ")}" end end Arithmetic Problem

Slide 58

Slide 58 text

module Shader::Calculable def expanded_operation operation.map do |node| if node.respond_to?(:to_expression) node.to_expression else node.to_s end end end end Arithmetic Problem

Slide 59

Slide 59 text

main do variable is Vec4 ( 1 - delta ) * normal end # => vec4 variable = 1 - delat * normal Arithmetic Problem

Slide 60

Slide 60 text

module Shader::Calculable def operation @operation ||= [] end def +(other) operation.push("+", other) BracketsNode.new(self) end end Arithmetic Problem

Slide 61

Slide 61 text

main do variable is Vec4 ( 1 - delta ) * normal end # => vec4 variable = ((1 - delat) * normal) Arithmetic Problem

Slide 62

Slide 62 text

How to define a class in C++ Save data inside ruby class in C++ Using mruby in C++

Slide 63

Slide 63 text

mrb_state* mrb = mrb_start(); RClass* klass = mrb_define_class(mrb, "Shader", mrb->object_class); Define Class in C++

Slide 64

Slide 64 text

mrb_define_method(mrb, klass, "initialize", init, MRG_ARGS_NONE()); Define Class in C++

Slide 65

Slide 65 text

mrb_value init(mrb_state* mrb, mrb_value self) { // Do something return self; } Define Class in C++

Slide 66

Slide 66 text

Let’s try create Shader class for Ruby

Slide 67

Slide 67 text

struct Shader { ofShader* instance; } Save data in Class

Slide 68

Slide 68 text

static struct mrb_data_type ShaderType { "Shader", freeShader } Save data in Class

Slide 69

Slide 69 text

Shader* allocaShader(mrb_state* mrb) { return (Shader*) mrb_alloca(mrb, sizeof(struct Shader)); } Save data in Class

Slide 70

Slide 70 text

void freeShader(mrb_state* mrb, void* ptr) { Shader* shader = static_cast(ptr); if(shader != NULL) { free(shader); } mrb_free(ptr); } Save data in Class

Slide 71

Slide 71 text

mrb_value init(mrb_state* mrb, mrb_value self) { Shader* shader = (Shader*) DATA_PTR(self); if(shader) { mrb_free(mrb, shader); } DATA_TYPE(self) = &ShaderType; DATA_PTR(self) = NULL; shader = allocaShader(mrb); shader->instance = new ofShader; DATA_PTR(self) = shader; return self; } Save data in Class

Slide 72

Slide 72 text

OpenFrameworks + mruby https://github.com/elct9620/MRubyShader GLSL generator https://github.com/elct9620/mruby-shader- generator Github

Slide 73

Slide 73 text

No content