jax 0.0.0.3 → 0.0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +19 -0
  2. data/README.rdoc +32 -15
  3. data/Rakefile +8 -2
  4. data/builtin/shaders/functions/lights.ejs +19 -31
  5. data/builtin/shaders/lighting/fragment.ejs +20 -14
  6. data/builtin/shaders/normal_map/manifest.yml +2 -2
  7. data/builtin/shaders/texture/manifest.yml +2 -2
  8. data/guides/assets/images/getting_started/dungeon-complete.png +0 -0
  9. data/guides/assets/images/getting_started/dungeon-normal-map.png +0 -0
  10. data/guides/assets/images/getting_started/dungeon-rainbow-textured.png +0 -0
  11. data/guides/assets/images/getting_started/dungeon-rainbow.png +0 -0
  12. data/guides/assets/images/getting_started/dungeon-textured-lighting.png +0 -0
  13. data/guides/assets/images/getting_started/dungeon-textured.png +0 -0
  14. data/guides/assets/images/getting_started/teapot-red-directional-point.png +0 -0
  15. data/guides/assets/images/getting_started/teapot-red-directional.png +0 -0
  16. data/guides/assets/images/getting_started/teapot-red-nolight.png +0 -0
  17. data/guides/assets/images/getting_started/teapot-red-spot-point-directional.png +0 -0
  18. data/guides/assets/images/getting_started/teapot-white.png +0 -0
  19. data/guides/assets/images/getting_started/teapot-with-model.png +0 -0
  20. data/guides/source/getting_started.textile +80 -39
  21. data/guides/source/index.html.erb +5 -1
  22. data/guides/source/matrices.textile +5 -0
  23. data/lib/jax/generators/app/app_generator.rb +16 -5
  24. data/lib/jax/generators/app/templates/public/javascripts/jax.js +27 -11
  25. data/lib/jax/generators/commands.rb +17 -4
  26. data/lib/jax/generators/material/material_generator.rb +1 -1
  27. data/lib/jax/generators/shader/USAGE +4 -0
  28. data/lib/jax/generators/shader/shader_generator.rb +71 -0
  29. data/lib/jax/generators/shader/templates/common.ejs.tt +16 -0
  30. data/lib/jax/generators/shader/templates/fragment.ejs.tt +8 -0
  31. data/lib/jax/generators/shader/templates/manifest.yml.tt +15 -0
  32. data/lib/jax/generators/shader/templates/material.js.tt +28 -0
  33. data/lib/jax/generators/shader/templates/spec.js.tt +28 -0
  34. data/lib/jax/generators/shader/templates/vertex.ejs.tt +10 -0
  35. data/lib/jax/version.rb +1 -1
  36. data/spec/javascripts/jax/webgl/shader_chain_spec.js +1 -1
  37. data/spec/javascripts/{jax/builtin/materials → shaders}/core_materials_spec.js +0 -0
  38. data/spec/javascripts/{jax/builtin/materials → shaders}/dual_paraboloid_spec.js +0 -0
  39. data/spec/javascripts/{jax/builtin/materials → shaders}/fog_spec.js +0 -0
  40. data/spec/javascripts/{jax/builtin/materials → shaders}/lighting_spec.js +0 -0
  41. data/spec/javascripts/{jax/builtin/materials → shaders}/normal_map_spec.js +0 -0
  42. data/spec/javascripts/{jax/builtin/materials → shaders}/shadow_map_spec.js +0 -0
  43. data/spec/javascripts/{jax/builtin/materials → shaders}/texture_spec.js +0 -0
  44. data/src/jax/core/matrix_stack.js +7 -3
  45. data/src/jax/webgl/core/framebuffer.js +5 -0
  46. data/src/jax/webgl/scene/light_manager.js +4 -1
  47. data/src/jax/webgl/shader.js +11 -1
  48. data/src/jax/webgl/shader/manifest.js +6 -6
  49. data/src/jax/webgl/shader_chain.js +9 -2
  50. data/src/jax/webgl/world.js +8 -4
  51. metadata +40 -18
@@ -36,13 +36,17 @@
36
36
  <% end %>
37
37
 
38
38
  <%= guide("Lighting", 'lighting.html', :work_in_progress => true) do %>
39
- <p>This guide shows how to make the most of lighting support in Jax, and outlines potential caveats.</p>
39
+ <p>This guide shows how to make the most of lighting support in Jax, and outlines potential caveats. It will also discuss how to prevent certain objects from being lit at all, and in what circumstances you'd want to do this.</p>
40
40
  <% end %>
41
41
 
42
42
  <%= guide("Custom Shaders", 'shaders.html', :work_in_progress => true) do %>
43
43
  <p>This guide shows how to add and use your own shaders to add advanced custom visual effects.</p>
44
44
  <% end %>
45
45
 
46
+ <%= guide("Matrices", "matrices.html", :work_in_progress => true) do%>
47
+ <p>This guide explains all of the various matrices and "spaces", and how they relate to one another. It will help you understand the difference between world space, camera space and object space; and how a 3D object goes from a set of vertices in object space to a translated, rotated and scaled image on your computer screen.</p>
48
+ <% end %>
49
+
46
50
  <%= guide("Testing Jax Applications", 'testing.html', :work_in_progress => true) do %>
47
51
  <p>This is a comprehensive guide to testing a Jax application. It covers everything from &quot;What is a test?&quot; to the testing APIs.</p>
48
52
  <% end %>
@@ -0,0 +1,5 @@
1
+ h2. This Guide Not Yet Started
2
+
3
+ Please come back after I've had time to work on this guide a bit.
4
+
5
+ endprologue.
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext'
2
+ require 'rbconfig'
2
3
  require File.join(File.dirname(__FILE__), "../../../jax")
3
4
 
4
5
  module Jax
@@ -55,14 +56,24 @@ module Jax
55
56
  end
56
57
 
57
58
  def git
58
- if File.exist? '.git'
59
- say_status :exist, 'git', :blue
59
+ void = RbConfig::CONFIG['host_os'] =~ /msdos|mswin|djgpp|mingw/ ? 'NUL' : '/dev/null'
60
+ if system "git --version >>#{void} 2>&1"
61
+ if File.exist? '.git'
62
+ say_status :exist, 'git', :blue
63
+ else
64
+ `git init`
65
+ `git add *`
66
+ say_status :init, 'git', :green
67
+ end
60
68
  else
61
- `git init`
62
- `git add *`
63
- say_status :init, 'git', :green
69
+ say_status :warn, "Git does not seem to be installed. Skipping...", :yellow
64
70
  end
65
71
  end
72
+
73
+ def done
74
+ # to clarify that everything is fine, just in case the user got warnings about git
75
+ say_status :complete, "Done!", :green
76
+ end
66
77
 
67
78
  protected
68
79
  def self.banner
@@ -3073,11 +3073,11 @@ Jax.MatrixStack = (function() {
3073
3073
  }
3074
3074
 
3075
3075
  return Jax.Class.create({
3076
- push: function() { pushMatrix(this); },
3076
+ push: function() { pushMatrix(this); return this; },
3077
3077
 
3078
- pop: function() { this.depth--; },
3078
+ pop: function() { this.depth--; return this; },
3079
3079
 
3080
- reset: function() { this.depth = 0; },
3080
+ reset: function() { this.depth = 0; return this; },
3081
3081
 
3082
3082
  loadModelMatrix: function(values) { loadMatrix(this, MODEL, values); return this; },
3083
3083
 
@@ -3819,8 +3819,12 @@ Jax.Shader = (function() {
3819
3819
  return source;
3820
3820
  }
3821
3821
 
3822
+ function sourceWithoutComments(source) {
3823
+ return source.replace(/\/\*.*\*\//g, "");
3824
+ }
3825
+
3822
3826
  function numArgumentsInMain(source) {
3823
- var result = /void\s*main\((.*?)\)\s*\{/.exec(source);
3827
+ var result = /void\s*main\((.*?)\)\s*\{/.exec(sourceWithoutComments(source));
3824
3828
  if (result) {
3825
3829
  result = result[1].replace(/\s*/g, '');
3826
3830
  if (result == "" || result == "void") return 0;
@@ -4310,7 +4314,7 @@ Jax.ShaderChain = (function() {
4310
4314
  function preprocessFunctions(self, prefix, suffix, source) {
4311
4315
  /* TODO mangle all function and structure names to prevent conflicts -- right now we only mangle main() */
4312
4316
 
4313
- return source.replace(/void\s*main\s*\(/, 'void '+sanitizeName(prefix)+'_main_'+sanitizeName(suffix)+'(');
4317
+ return source.replace(/void\s*main\s*\(/g, 'void '+sanitizeName(prefix)+'_main_'+sanitizeName(suffix)+'(');
4314
4318
  }
4315
4319
 
4316
4320
  function preprocessorOptions(self) {
@@ -4450,11 +4454,18 @@ Jax.ShaderChain = (function() {
4450
4454
  functionCalls += " "+sanitizeName(this.phases[i].getName())+i+"_main_f("+args+");\n";
4451
4455
  }
4452
4456
 
4457
+ var colors = "#ifdef PASS_TYPE\n"
4458
+ + " if (PASS_TYPE == "+Jax.Scene.ILLUMINATION_PASS+") gl_FragColor = ambient + diffuse + specular;\n"
4459
+ + " else gl_FragColor = ambient;\n"
4460
+ + "#else\n"
4461
+ + " gl_FragColor = ambient + diffuse + specular;\n"
4462
+ + "#endif\n";
4463
+
4453
4464
  return "/**** Shader chain generated #main ****/\n" +
4454
4465
  "void main(void) {\n" +
4455
4466
  "vec4 ambient = vec4(1.0,1.0,1.0,1.0), diffuse = vec4(1.0,1.0,1.0,1.0), specular = vec4(1.0,1.0,1.0,1.0);\n" +
4456
4467
  functionCalls +
4457
- (lastTookArguments ? "gl_FragColor = ambient + diffuse + specular;\n" : "") +
4468
+ (lastTookArguments ? colors : "") +
4458
4469
  "}\n";
4459
4470
  },
4460
4471
 
@@ -6100,13 +6111,15 @@ Jax.Scene.LightManager = (function() {
6100
6111
  },
6101
6112
 
6102
6113
  illuminate: function(context, objects, options) {
6114
+ this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6103
6115
  for (var i = 0; i < this._lights.length; i++) {
6104
- this._current_light = i;
6105
6116
  for (var j = 0; j < objects.length; j++) {
6117
+ this._current_light = i;
6106
6118
  /* TODO optimization: see if objects[j] is even affected by this._lights[i] (based on attenuation) */
6107
6119
  if (objects[j].isLit())
6108
6120
  objects[j].render(context, options);
6109
6121
  }
6122
+ this.context.glBlendFunc(GL_ONE, GL_ONE);
6110
6123
  }
6111
6124
  delete this._current_light;
6112
6125
  },
@@ -6562,11 +6575,15 @@ Jax.World = (function() {
6562
6575
 
6563
6576
  if (this.lighting.isEnabled()) {
6564
6577
  /* ambient pass */
6565
- for (i = 0; i < this.objects.length; i++) {
6578
+ /*
6579
+ So.... I see a legit need for an ambient pass for A) unlit objects and B)
6580
+ scene lighting. But jax doesn't yet support scene lighting so really only
6581
+ unlit objects need an ambient pass. For lit objects, why not let
6582
+ lighting take care of (ambient + diffuse + specular) all at once?
6583
+ */
6584
+ for (i = 0; i < this.objects.length; i++)
6566
6585
  if (!this.objects[i].lit)
6567
6586
  this.objects[i].render(this.context, unlit);
6568
- }
6569
- this.lighting.ambient(this.context, this.objects);
6570
6587
 
6571
6588
  /* shadowgen pass */
6572
6589
  this.context.current_pass = Jax.Scene.SHADOWMAP_PASS;
@@ -6576,7 +6593,6 @@ Jax.World = (function() {
6576
6593
  }
6577
6594
 
6578
6595
  /* illumination pass */
6579
- this.context.glBlendFunc(GL_ONE, GL_ONE);
6580
6596
  this.context.current_pass = Jax.Scene.ILLUMINATION_PASS;
6581
6597
  this.lighting.illuminate(this.context, this.objects);
6582
6598
  } else {
@@ -19,11 +19,15 @@ module Jax
19
19
  def base_path=(path)
20
20
  @base_path = path
21
21
  end
22
+
23
+ def usage
24
+ usage = ERB.new(File.read(File.expand_path("USAGE", base_path)), nil, '-')
25
+ usage.result(binding)
26
+ end
22
27
 
23
28
  def start(given_args=ARGV, config={})
24
29
  if (given_args.length == 0)
25
- usage = ERB.new(File.read(File.expand_path("USAGE", base_path)), nil, '-')
26
- puts usage.result(binding)
30
+ puts usage
27
31
  else
28
32
  super
29
33
  end
@@ -35,6 +39,7 @@ module Jax
35
39
  autoload :Model, File.join(File.dirname(__FILE__), "model/model_generator")
36
40
  autoload :LightSource,File.join(File.dirname(__FILE__), "light_source/light_source_generator")
37
41
  autoload :Material, File.join(File.dirname(__FILE__), "material/material_generator")
42
+ autoload :Shader, File.join(File.dirname(__FILE__), "shader/shader_generator")
38
43
  end
39
44
  end
40
45
 
@@ -66,16 +71,24 @@ class JaxGeneratorInvoker < Thor
66
71
  end
67
72
 
68
73
  desc "scaffold", "generates a controller, model and material, all with the same name"
69
- def scaffold(name)
74
+ def scaffold(*name)
75
+ name = name.shift || []
70
76
  Jax::Generators::Controller::ControllerGenerator.start([name, 'index'])
71
77
  Jax::Generators::Model::ModelGenerator.start([name])
72
78
  Jax::Generators::Material::MaterialGenerator.start([name])
73
79
  end
80
+
81
+ desc "shader", "generates a new custom shader"
82
+ def shader(*name)
83
+ Jax::Generators::Shader::ShaderGenerator.start(name)
84
+ end
74
85
  end
75
86
 
76
87
  class JaxGenerator < Thor
77
- desc "generate", "generates a controller, model, light source, or material"
88
+ desc "generate", "generates a controller, model, light source, material or shader"
78
89
  def generate(*args)
79
90
  JaxGeneratorInvoker.start(args)
91
+ rescue ArgumentError
92
+ puts $!.message
80
93
  end
81
94
  end
@@ -61,7 +61,7 @@ module Jax
61
61
  end
62
62
 
63
63
  def banner
64
- "jax generate light #{self.arguments.map { |a| a.usage }.join(' ')}"
64
+ "jax generate material #{self.arguments.map { |a| a.usage }.join(' ')}"
65
65
  end
66
66
 
67
67
  def file_name
@@ -0,0 +1,4 @@
1
+ Usage:
2
+ jax generate shader NAME
3
+
4
+ Generates a new custom shader, which can then be used in materials.
@@ -0,0 +1,71 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module Jax
4
+ module Generators
5
+ module Shader
6
+ class ShaderGenerator < Jax::Generators::Command
7
+ include Thor::Actions
8
+ argument :name, :desc => "The name of this shader", :banner => "[name]"
9
+
10
+ def self.source_root
11
+ File.expand_path("templates", File.dirname(__FILE__))
12
+ end
13
+
14
+ def check_conflicts
15
+ if Jax.application.shaders.find(file_name)
16
+ raise ArgumentError, "A shader called '#{file_name}' already exists!"
17
+ end
18
+ end
19
+
20
+ def common
21
+ template_to 'common.ejs'
22
+ end
23
+
24
+ def fragment
25
+ template_to 'fragment.ejs'
26
+ end
27
+
28
+ def manifest
29
+ template_to 'manifest.yml'
30
+ end
31
+
32
+ def material
33
+ template_to 'material.js'
34
+ end
35
+
36
+ def vertex
37
+ template_to 'vertex.ejs'
38
+ end
39
+
40
+ def spec
41
+ template "spec.js.tt", File.join("spec/javascripts/shaders", "#{file_name}_spec.js")
42
+ end
43
+
44
+ protected
45
+ def template_to(basename)
46
+ template "#{basename}.tt", path_to(basename)
47
+ end
48
+
49
+ def path_to(basename)
50
+ File.join("app/shaders", file_name, basename)
51
+ end
52
+
53
+ def banner
54
+ "jax generate shader #{self.arguments.map { |a| a.usage }.join(' ')}"
55
+ end
56
+
57
+ def file_name
58
+ name.underscore
59
+ end
60
+
61
+ def class_name
62
+ name.camelize
63
+ end
64
+
65
+ def plural_name
66
+ name.pluralize
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,16 @@
1
+ // Shared variables save on graphics memory and allow you to "piggy-back" off of
2
+ // variables defined in other shaders:
3
+
4
+ shared uniform mat3 nMatrix;
5
+ shared uniform mat4 mvMatrix, pMatrix;
6
+
7
+ shared varying vec2 vTexCoords;
8
+ shared varying vec3 vNormals;
9
+ shared varying vec4 vColors;
10
+
11
+ // If a variable isn't shared, it will be defined specifically for this shader.
12
+ // If this shader is used twice in one materials, unshared variables will be
13
+ // defined twice -- once for each use of the shader.
14
+
15
+ // uniform sampler2D Texture;
16
+ // uniform float TextureScaleX, TextureScaleY;
@@ -0,0 +1,8 @@
1
+ /*
2
+ If you don't need the color attributes, use
3
+ void main(void)
4
+ to make your shader more efficient.
5
+ */
6
+ void main(inout vec4 ambient, inout vec4 diffuse, inout vec4 specular) {
7
+
8
+ }
@@ -0,0 +1,15 @@
1
+ description: |
2
+ Write a brief description for your shader.
3
+
4
+
5
+ # Add an 'options' attribute if your shader's Material can accept
6
+ # multiple configurations. Usually, you'll have an option for each
7
+ # corresponding uniform or attribute variable.
8
+
9
+ # Example:
10
+
11
+ #options:
12
+ # path: "/path/to/texture.png"
13
+ # flip_y: false
14
+ # scale_x: 1.0
15
+ # scale_y: 1.0
@@ -0,0 +1,28 @@
1
+ Jax.Material.<%=class_name%> = Jax.Class.create(Jax.Material, {
2
+ initialize: function($super, options) {
3
+ options = Jax.Util.normalizeOptions(options, {
4
+ shader: "<%=file_name%>",
5
+
6
+ // You can specify default options (see +manifest.yml+) here.
7
+ });
8
+
9
+ $super(options);
10
+ },
11
+
12
+ setUniforms: function($super, context, mesh, options, uniforms) {
13
+ $super(context, mesh, options, uniforms);
14
+
15
+ uniforms.set('mvMatrix', context.getModelViewMatrix());
16
+ uniforms.set('nMatrix', context.getNormalMatrix());
17
+ uniforms.set('pMatrix', context.getProjectionMatrix());
18
+
19
+ // uniforms.texture('Texture', this.texture, context);
20
+ },
21
+
22
+ setAttributes: function($super, context, mesh, options, attributes) {
23
+ attributes.set('VERTEX_POSITION', mesh.getVertexBuffer());
24
+ attributes.set('VERTEX_COLOR', mesh.getColorBuffer());
25
+ attributes.set('VERTEX_NORMAL', mesh.getNormalBuffer());
26
+ attributes.set('VERTEX_TEXCOORDS', mesh.getTextureCoordsBuffer());
27
+ }
28
+ });
@@ -0,0 +1,28 @@
1
+ describe("Shader '<%=file_name%>'", function() {
2
+ var context, material, mesh;
3
+
4
+ beforeEach(function() {
5
+ context = new Jax.Context('webgl-canvas');
6
+ mesh = new Jax.Mesh.Quad();
7
+ });
8
+
9
+ describe("stand-alone", function() {
10
+ beforeEach(function() { mesh.material = new Jax.Material.<%=class_name%>(); });
11
+
12
+ it("should render without error", function() {
13
+ expect(function() { mesh.render(context); }).not.toThrow();
14
+ });
15
+ });
16
+
17
+ describe("as a layer", function() {
18
+ beforeEach(function() {
19
+ mesh.material = new Jax.Material({layers:[{
20
+ type:"<%=class_name%>"
21
+ }]});
22
+ });
23
+
24
+ it("should render without error", function() {
25
+ expect(function() { mesh.render(context); }).not.toThrow();
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,10 @@
1
+ shared attribute vec4 VERTEX_POSITION, VERTEX_COLOR;
2
+ shared attribute vec3 VERTEX_NORMAL;
3
+ shared attribute vec2 VERTEX_TEXCOORDS;
4
+
5
+ void main(void) {
6
+ gl_Position = pMatrix * mvMatrix * VERTEX_POSITION;
7
+ // vNormal = VERTEX_NORMAL;
8
+ // vColor = VERTEX_COLOR;
9
+ // vTexCoords = VERTEX_TEXCOORDS;
10
+ }
@@ -3,7 +3,7 @@ module Jax
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
5
  TINY = 0
6
- PATCH = 3
6
+ PATCH = 4
7
7
 
8
8
  STRING = PATCH == 0 ? "#{MAJOR}.#{MINOR}.#{TINY}" : "#{MAJOR}.#{MINOR}.#{TINY}.#{PATCH}"
9
9
  end
@@ -25,7 +25,7 @@ describe("Jax.ShaderChain", function() {
25
25
 
26
26
  describe("with a fragment main with 3 unqualified arguments", function() {
27
27
  beforeEach(function() {
28
- chain.addShader(new Jax.Shader({fragment:"void main(vec4 amb, vec4 dif, vec4 spec) { }",name:"one"}));
28
+ chain.addShader(new Jax.Shader({fragment:"/* comment with void main(void) in it*/\nvoid main(vec4 amb, vec4 dif, vec4 spec) { }",name:"one"}));
29
29
  });
30
30
 
31
31
  it("should mangle #main but keep the arguments", function() {