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.
- data/LICENSE +19 -0
- data/README.rdoc +32 -15
- data/Rakefile +8 -2
- data/builtin/shaders/functions/lights.ejs +19 -31
- data/builtin/shaders/lighting/fragment.ejs +20 -14
- data/builtin/shaders/normal_map/manifest.yml +2 -2
- data/builtin/shaders/texture/manifest.yml +2 -2
- data/guides/assets/images/getting_started/dungeon-complete.png +0 -0
- data/guides/assets/images/getting_started/dungeon-normal-map.png +0 -0
- data/guides/assets/images/getting_started/dungeon-rainbow-textured.png +0 -0
- data/guides/assets/images/getting_started/dungeon-rainbow.png +0 -0
- data/guides/assets/images/getting_started/dungeon-textured-lighting.png +0 -0
- data/guides/assets/images/getting_started/dungeon-textured.png +0 -0
- data/guides/assets/images/getting_started/teapot-red-directional-point.png +0 -0
- data/guides/assets/images/getting_started/teapot-red-directional.png +0 -0
- data/guides/assets/images/getting_started/teapot-red-nolight.png +0 -0
- data/guides/assets/images/getting_started/teapot-red-spot-point-directional.png +0 -0
- data/guides/assets/images/getting_started/teapot-white.png +0 -0
- data/guides/assets/images/getting_started/teapot-with-model.png +0 -0
- data/guides/source/getting_started.textile +80 -39
- data/guides/source/index.html.erb +5 -1
- data/guides/source/matrices.textile +5 -0
- data/lib/jax/generators/app/app_generator.rb +16 -5
- data/lib/jax/generators/app/templates/public/javascripts/jax.js +27 -11
- data/lib/jax/generators/commands.rb +17 -4
- data/lib/jax/generators/material/material_generator.rb +1 -1
- data/lib/jax/generators/shader/USAGE +4 -0
- data/lib/jax/generators/shader/shader_generator.rb +71 -0
- data/lib/jax/generators/shader/templates/common.ejs.tt +16 -0
- data/lib/jax/generators/shader/templates/fragment.ejs.tt +8 -0
- data/lib/jax/generators/shader/templates/manifest.yml.tt +15 -0
- data/lib/jax/generators/shader/templates/material.js.tt +28 -0
- data/lib/jax/generators/shader/templates/spec.js.tt +28 -0
- data/lib/jax/generators/shader/templates/vertex.ejs.tt +10 -0
- data/lib/jax/version.rb +1 -1
- data/spec/javascripts/jax/webgl/shader_chain_spec.js +1 -1
- data/spec/javascripts/{jax/builtin/materials → shaders}/core_materials_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/dual_paraboloid_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/fog_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/lighting_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/normal_map_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/shadow_map_spec.js +0 -0
- data/spec/javascripts/{jax/builtin/materials → shaders}/texture_spec.js +0 -0
- data/src/jax/core/matrix_stack.js +7 -3
- data/src/jax/webgl/core/framebuffer.js +5 -0
- data/src/jax/webgl/scene/light_manager.js +4 -1
- data/src/jax/webgl/shader.js +11 -1
- data/src/jax/webgl/shader/manifest.js +6 -6
- data/src/jax/webgl/shader_chain.js +9 -2
- data/src/jax/webgl/world.js +8 -4
- 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 "What is a test?" to the testing APIs.</p>
|
48
52
|
<% end %>
|
@@ -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
|
-
|
59
|
-
|
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
|
-
|
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*\(
|
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 ?
|
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
|
-
|
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
|
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
|
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
|
@@ -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,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
|
+
}
|
data/lib/jax/version.rb
CHANGED
@@ -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() {
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|